upstream: switch over to the new authorized_keys options API and

remove the legacy one.

Includes a fairly big refactor of auth2-pubkey.c to retain less state
between key file lines.

feedback and ok markus@

OpenBSD-Commit-ID: dece6cae0f47751b9892080eb13d6625599573df
This commit is contained in:
djm@openbsd.org 2018-03-03 03:15:51 +00:00 коммит произвёл Damien Miller
Родитель 90c4bec8b5
Коммит 7c85685760
19 изменённых файлов: 768 добавлений и 985 удалений

Просмотреть файл

@ -7,8 +7,7 @@ audit-linux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-c
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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h xmalloc.h ssh.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h misc.h servconf.h uidswap.h key.h sshkey.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h openbsd-compat/sys-queue.h key.h sshkey.h xmalloc.h match.h ssherr.h log.h canohost.h packet.h dispatch.h opacket.h misc.h channels.h servconf.h auth-options.h hostfile.h auth.h auth-pam.h
auth-options.o: 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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h log.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h misc.h servconf.h key.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h uidswap.h pathnames.h log.h misc.h key.h sshkey.h servconf.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
@ -16,7 +15,7 @@ auth-shadow.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-c
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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h
auth-skey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h xmalloc.h match.h groupaccess.h log.h misc.h servconf.h key.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h openbsd-compat/sys-queue.h
auth.o: dispatch.h opacket.h authfile.h monitor_wrap.h ssherr.h compat.h
auth.o: dispatch.h opacket.h authfile.h monitor_wrap.h ssherr.h compat.h channels.h
auth2-chall.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h xmalloc.h ssh2.h key.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h canohost.h
@ -161,7 +160,7 @@ sshconnect.o: ssh2.h version.h authfile.h ssherr.h authfd.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h packet.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h key.h sshkey.h kex.h mac.h
sshconnect2.o: myproposal.h sshconnect.h authfile.h dh.h authfd.h log.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h ssherr.h utf8.h
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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h opacket.h log.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h
sshd.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h key.h sshkey.h kex.h mac.h myproposal.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h ssh-sandbox.h version.h ssherr.h
sshd.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h key.h sshkey.h kex.h mac.h myproposal.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h ssh-sandbox.h auth-options.h version.h ssherr.h
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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.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/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h buffer.h sshbuf.h crypto_api.h ssh2.h ssherr.h misc.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h sshkey-xmss.h match.h xmss_fast.h

Просмотреть файл

@ -1,14 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.75 2018/03/03 03:06:02 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* $OpenBSD: auth-options.c,v 1.76 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
*
@ -39,649 +29,15 @@
#include "openbsd-compat/sys-queue.h"
#include "key.h" /* XXX for typedef */
#include "buffer.h" /* XXX for typedef */
#include "xmalloc.h"
#include "match.h"
#include "ssherr.h"
#include "ssh2.h"
#include "log.h"
#include "canohost.h"
#include "packet.h"
#include "sshbuf.h"
#include "misc.h"
#include "channels.h"
#include "servconf.h"
#include "sshkey.h"
#include "match.h"
#include "ssh2.h"
#include "auth-options.h"
#include "hostfile.h"
#include "auth.h"
/* Flags set authorized_keys flags */
int no_port_forwarding_flag = 0;
int no_agent_forwarding_flag = 0;
int no_x11_forwarding_flag = 0;
int no_pty_flag = 0;
int no_user_rc = 0;
int key_is_cert_authority = 0;
/* "command=" option. */
char *forced_command = NULL;
/* "environment=" options. */
struct envstring *custom_environment = NULL;
/* "tunnel=" option. */
int forced_tun_device = -1;
/* "principals=" option. */
char *authorized_principals = NULL;
extern ServerOptions options;
/* XXX refactor to be stateless */
void
auth_clear_options(void)
{
struct ssh *ssh = active_state; /* XXX */
no_agent_forwarding_flag = 0;
no_port_forwarding_flag = 0;
no_pty_flag = 0;
no_x11_forwarding_flag = 0;
no_user_rc = 0;
key_is_cert_authority = 0;
while (custom_environment) {
struct envstring *ce = custom_environment;
custom_environment = ce->next;
free(ce->s);
free(ce);
}
free(forced_command);
forced_command = NULL;
free(authorized_principals);
authorized_principals = NULL;
forced_tun_device = -1;
channel_clear_permitted_opens(ssh);
}
/*
* 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 and, if 'msg' is not NULL
* then a message based on it added via auth_debug_add().
*/
static int
match_flag(const char *opt, int allow_negate, char **optsp, const char *msg)
{
size_t opt_len = strlen(opt);
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;
if (msg != NULL) {
auth_debug_add("%s %s.", msg,
negate ? "disabled" : "enabled");
}
return negate ? 0 : 1;
}
return -1;
}
/*
* return 1 if access is granted, 0 if not.
* side effect: sets key option flags
* XXX remove side effects; fill structure instead.
*/
int
auth_parse_options(struct passwd *pw, char *opts, const char *file,
u_long linenum)
{
struct ssh *ssh = active_state; /* XXX */
const char *cp;
int i, r;
/* reset options */
auth_clear_options();
if (!opts)
return 1;
while (*opts && *opts != ' ' && *opts != '\t') {
if ((r = match_flag("cert-authority", 0, &opts, NULL)) != -1) {
key_is_cert_authority = r;
goto next_option;
}
if ((r = match_flag("restrict", 0, &opts, NULL)) != -1) {
auth_debug_add("Key is restricted.");
no_port_forwarding_flag = 1;
no_agent_forwarding_flag = 1;
no_x11_forwarding_flag = 1;
no_pty_flag = 1;
no_user_rc = 1;
goto next_option;
}
if ((r = match_flag("port-forwarding", 1, &opts,
"Port forwarding")) != -1) {
no_port_forwarding_flag = r != 1;
goto next_option;
}
if ((r = match_flag("agent-forwarding", 1, &opts,
"Agent forwarding")) != -1) {
no_agent_forwarding_flag = r != 1;
goto next_option;
}
if ((r = match_flag("x11-forwarding", 1, &opts,
"X11 forwarding")) != -1) {
no_x11_forwarding_flag = r != 1;
goto next_option;
}
if ((r = match_flag("pty", 1, &opts,
"PTY allocation")) != -1) {
no_pty_flag = r != 1;
goto next_option;
}
if ((r = match_flag("user-rc", 1, &opts,
"User rc execution")) != -1) {
no_user_rc = r != 1;
goto next_option;
}
cp = "command=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
free(forced_command);
forced_command = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
forced_command[i++] = '"';
continue;
}
forced_command[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(forced_command);
forced_command = NULL;
goto bad_option;
}
forced_command[i] = '\0';
auth_debug_add("Forced command.");
opts++;
goto next_option;
}
cp = "principals=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
free(authorized_principals);
authorized_principals = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
authorized_principals[i++] = '"';
continue;
}
authorized_principals[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(authorized_principals);
authorized_principals = NULL;
goto bad_option;
}
authorized_principals[i] = '\0';
auth_debug_add("principals: %.900s",
authorized_principals);
opts++;
goto next_option;
}
cp = "environment=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *s;
struct envstring *new_envstring;
opts += strlen(cp);
s = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
s[i++] = '"';
continue;
}
s[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(s);
goto bad_option;
}
s[i] = '\0';
opts++;
if (options.permit_user_env) {
auth_debug_add("Adding to environment: "
"%.900s", s);
debug("Adding to environment: %.900s", s);
new_envstring = xcalloc(1,
sizeof(*new_envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
custom_environment = new_envstring;
s = NULL;
}
free(s);
goto next_option;
}
cp = "from=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
const char *remote_ip = ssh_remote_ipaddr(ssh);
const char *remote_host = auth_get_canonical_hostname(
ssh, options.use_dns);
char *patterns = xmalloc(strlen(opts) + 1);
opts += strlen(cp);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
patterns[i++] = '"';
continue;
}
patterns[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(patterns);
goto bad_option;
}
patterns[i] = '\0';
opts++;
switch (match_host_and_ip(remote_host, remote_ip,
patterns)) {
case 1:
free(patterns);
/* Host name matches. */
goto next_option;
case -1:
debug("%.100s, line %lu: invalid criteria",
file, linenum);
auth_debug_add("%.100s, line %lu: "
"invalid criteria", file, linenum);
/* FALLTHROUGH */
case 0:
free(patterns);
logit("Authentication tried for %.100s with "
"correct key but not from a permitted "
"host (host=%.200s, ip=%.200s).",
pw->pw_name, remote_host, remote_ip);
auth_debug_add("Your host '%.200s' is not "
"permitted to use this key for login.",
remote_host);
break;
}
/* deny access */
return 0;
}
cp = "permitopen=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *host, *p;
int port;
char *patterns = xmalloc(strlen(opts) + 1);
opts += strlen(cp);
i = 0;
while (*opts) {
if (*opts == '"')
break;
if (*opts == '\\' && opts[1] == '"') {
opts += 2;
patterns[i++] = '"';
continue;
}
patterns[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing "
"end quote", file, linenum);
free(patterns);
goto bad_option;
}
patterns[i] = '\0';
opts++;
p = patterns;
/* XXX - add streamlocal support */
host = hpdelim(&p);
if (host == NULL || strlen(host) >= NI_MAXHOST) {
debug("%.100s, line %lu: Bad permitopen "
"specification <%.100s>", file, linenum,
patterns);
auth_debug_add("%.100s, line %lu: "
"Bad permitopen specification", file,
linenum);
free(patterns);
goto bad_option;
}
host = cleanhostname(host);
if (p == NULL || (port = permitopen_port(p)) < 0) {
debug("%.100s, line %lu: Bad permitopen port "
"<%.100s>", file, linenum, p ? p : "");
auth_debug_add("%.100s, line %lu: "
"Bad permitopen port", file, linenum);
free(patterns);
goto bad_option;
}
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
channel_add_permitted_opens(ssh, host, port);
free(patterns);
goto next_option;
}
cp = "tunnel=\"";
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *tun = NULL;
opts += strlen(cp);
tun = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
if (*opts == '"')
break;
tun[i++] = *opts++;
}
if (!*opts) {
debug("%.100s, line %lu: missing end quote",
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
free(tun);
forced_tun_device = -1;
goto bad_option;
}
tun[i] = '\0';
forced_tun_device = a2tun(tun, NULL);
free(tun);
if (forced_tun_device == SSH_TUNID_ERR) {
debug("%.100s, line %lu: invalid tun device",
file, linenum);
auth_debug_add("%.100s, line %lu: invalid tun device",
file, linenum);
forced_tun_device = -1;
goto bad_option;
}
auth_debug_add("Forced tun device: %d", forced_tun_device);
opts++;
goto next_option;
}
next_option:
/*
* Skip the comma, and move to the next option
* (or break out if there are no more).
*/
if (!*opts)
fatal("Bugs in auth-options.c option processing.");
if (*opts == ' ' || *opts == '\t')
break; /* End of options. */
if (*opts != ',')
goto bad_option;
opts++;
/* Process the next option. */
}
/* grant access */
return 1;
bad_option:
logit("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
file, linenum, opts);
/* deny access */
return 0;
}
#define OPTIONS_CRITICAL 1
#define OPTIONS_EXTENSIONS 2
static int
parse_option_list(struct sshbuf *oblob, struct passwd *pw,
u_int which, int crit,
int *cert_no_port_forwarding_flag,
int *cert_no_agent_forwarding_flag,
int *cert_no_x11_forwarding_flag,
int *cert_no_pty_flag,
int *cert_no_user_rc,
char **cert_forced_command,
int *cert_source_address_done)
{
struct ssh *ssh = active_state; /* XXX */
char *command, *allowed;
const char *remote_ip;
char *name = NULL;
struct sshbuf *c = NULL, *data = NULL;
int r, ret = -1, result, found;
if ((c = sshbuf_fromb(oblob)) == NULL) {
error("%s: sshbuf_fromb failed", __func__);
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("Unable to parse certificate options: %s",
ssh_err(r));
goto out;
}
debug3("found certificate option \"%.100s\" len %zu",
name, sshbuf_len(data));
found = 0;
if ((which & OPTIONS_EXTENSIONS) != 0) {
if (strcmp(name, "permit-X11-forwarding") == 0) {
*cert_no_x11_forwarding_flag = 0;
found = 1;
} else if (strcmp(name,
"permit-agent-forwarding") == 0) {
*cert_no_agent_forwarding_flag = 0;
found = 1;
} else if (strcmp(name,
"permit-port-forwarding") == 0) {
*cert_no_port_forwarding_flag = 0;
found = 1;
} else if (strcmp(name, "permit-pty") == 0) {
*cert_no_pty_flag = 0;
found = 1;
} else if (strcmp(name, "permit-user-rc") == 0) {
*cert_no_user_rc = 0;
found = 1;
}
}
if (!found && (which & OPTIONS_CRITICAL) != 0) {
if (strcmp(name, "force-command") == 0) {
if ((r = sshbuf_get_cstring(data, &command,
NULL)) != 0) {
error("Unable to parse \"%s\" "
"section: %s", name, ssh_err(r));
goto out;
}
if (*cert_forced_command != NULL) {
error("Certificate has multiple "
"force-command options");
free(command);
goto out;
}
*cert_forced_command = command;
found = 1;
}
if (strcmp(name, "source-address") == 0) {
if ((r = sshbuf_get_cstring(data, &allowed,
NULL)) != 0) {
error("Unable to parse \"%s\" "
"section: %s", name, ssh_err(r));
goto out;
}
if ((*cert_source_address_done)++) {
error("Certificate has multiple "
"source-address options");
free(allowed);
goto out;
}
remote_ip = ssh_remote_ipaddr(ssh);
result = addr_match_cidr_list(remote_ip,
allowed);
free(allowed);
switch (result) {
case 1:
/* accepted */
break;
case 0:
/* no match */
logit("Authentication tried for %.100s "
"with valid certificate but not "
"from a permitted host "
"(ip=%.200s).", pw->pw_name,
remote_ip);
auth_debug_add("Your address '%.200s' "
"is not permitted to use this "
"certificate for login.",
remote_ip);
goto out;
case -1:
default:
error("Certificate source-address "
"contents invalid");
goto out;
}
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:
if (ret != 0 &&
cert_forced_command != NULL &&
*cert_forced_command != NULL) {
free(*cert_forced_command);
*cert_forced_command = NULL;
}
free(name);
sshbuf_free(data);
sshbuf_free(c);
return ret;
}
/*
* Set options from critical certificate options. These supersede user key
* options so this must be called after auth_parse_options().
*/
int
auth_cert_options(struct sshkey *k, struct passwd *pw, const char **reason)
{
int cert_no_port_forwarding_flag = 1;
int cert_no_agent_forwarding_flag = 1;
int cert_no_x11_forwarding_flag = 1;
int cert_no_pty_flag = 1;
int cert_no_user_rc = 1;
char *cert_forced_command = NULL;
int cert_source_address_done = 0;
*reason = "invalid certificate options";
/* Separate options and extensions for v01 certs */
if (parse_option_list(k->cert->critical, pw,
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
&cert_forced_command,
&cert_source_address_done) == -1)
return -1;
if (parse_option_list(k->cert->extensions, pw,
OPTIONS_EXTENSIONS, 0,
&cert_no_port_forwarding_flag,
&cert_no_agent_forwarding_flag,
&cert_no_x11_forwarding_flag,
&cert_no_pty_flag,
&cert_no_user_rc,
NULL, NULL) == -1)
return -1;
no_port_forwarding_flag |= cert_no_port_forwarding_flag;
no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
no_pty_flag |= cert_no_pty_flag;
no_user_rc |= cert_no_user_rc;
/*
* Only permit both CA and key option forced-command if they match.
* Otherwise refuse the certificate.
*/
if (cert_forced_command != NULL && forced_command != NULL) {
if (strcmp(forced_command, cert_forced_command) == 0) {
free(forced_command);
forced_command = cert_forced_command;
} else {
*reason = "certificate and key options forced command "
"do not match";
free(cert_forced_command);
return -1;
}
} else if (cert_forced_command != NULL)
forced_command = cert_forced_command;
/* success */
*reason = NULL;
return 0;
}
/*
* authorized_keys options processing.
*/
/*
* Match flag 'opt' in *optsp, and if allow_negate is set then also match

Просмотреть файл

@ -1,15 +1,19 @@
/* $OpenBSD: auth-options.h,v 1.24 2018/03/03 03:06:02 djm Exp $ */
/* $OpenBSD: auth-options.h,v 1.25 2018/03/03 03:15:51 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef AUTH_OPTIONS_H
@ -18,30 +22,6 @@
struct passwd;
struct sshkey;
/* Linked list of custom environment strings */
struct envstring {
struct envstring *next;
char *s;
};
/* Flags that may be set in authorized_keys options. */
extern int no_port_forwarding_flag;
extern int no_agent_forwarding_flag;
extern int no_x11_forwarding_flag;
extern int no_pty_flag;
extern int no_user_rc;
extern char *forced_command;
extern struct envstring *custom_environment;
extern int forced_tun_device;
extern int key_is_cert_authority;
extern char *authorized_principals;
int auth_parse_options(struct passwd *, char *, const char *, u_long);
void auth_clear_options(void);
int auth_cert_options(struct sshkey *, struct passwd *, const char **);
/* authorized_keys options handling */
/*
* sshauthopt represents key options parsed from authorized_keys or
* from certificate extensions/options.

Просмотреть файл

@ -1077,7 +1077,7 @@ do_pam_chauthtok(void)
}
void
do_pam_session(void)
do_pam_session(struct ssh *ssh)
{
debug3("PAM: opening session");
@ -1093,7 +1093,7 @@ do_pam_session(void)
sshpam_session_open = 1;
else {
sshpam_session_open = 0;
disable_forwarding();
auth_restrict_session(ssh);
error("PAM: pam_open_session(): %s",
pam_strerror(sshpam_handle, sshpam_err));
}

Просмотреть файл

@ -25,10 +25,12 @@
#include "includes.h"
#ifdef USE_PAM
struct ssh;
void start_pam(Authctxt *);
void finish_pam(void);
u_int do_pam_account(void);
void do_pam_session(void);
void do_pam_session(struct ssh *);
void do_pam_setcred(int );
void do_pam_chauthtok(void);
int do_pam_putenv(char *, char *);

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: auth-passwd.c,v 1.45 2016/07/21 01:39:35 dtucker Exp $ */
/* $OpenBSD: auth-passwd.c,v 1.46 2018/03/03 03:15:51 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -68,22 +68,15 @@ extern login_cap_t *lc;
#define MAX_PASSWORD_LEN 1024
void
disable_forwarding(void)
{
no_port_forwarding_flag = 1;
no_agent_forwarding_flag = 1;
no_x11_forwarding_flag = 1;
}
/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int
auth_password(Authctxt *authctxt, const char *password)
auth_password(struct ssh *ssh, const char *password)
{
struct passwd * pw = authctxt->pw;
Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
int result, ok = authctxt->valid;
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
static int expire_checked = 0;
@ -128,9 +121,9 @@ auth_password(Authctxt *authctxt, const char *password)
authctxt->force_pwchange = 1;
}
#endif
result = sys_auth_passwd(authctxt, password);
result = sys_auth_passwd(ssh, password);
if (authctxt->force_pwchange)
disable_forwarding();
auth_restrict_session(ssh);
return (result && ok);
}
@ -170,19 +163,19 @@ warn_expiry(Authctxt *authctxt, auth_session_t *as)
}
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
sys_auth_passwd(struct ssh *ssh, const char *password)
{
struct passwd *pw = authctxt->pw;
Authctxt *authctxt = ssh->authctxt;
auth_session_t *as;
static int expire_checked = 0;
as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh",
as = auth_usercheck(authctxt->pw->pw_name, authctxt->style, "auth-ssh",
(char *)password);
if (as == NULL)
return (0);
if (auth_getstate(as) & AUTH_PWEXPIRED) {
auth_close(as);
disable_forwarding();
auth_restrict_session(ssh);
authctxt->force_pwchange = 1;
return (1);
} else {
@ -195,8 +188,9 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
}
#elif !defined(CUSTOM_SYS_AUTH_PASSWD)
int
sys_auth_passwd(Authctxt *authctxt, const char *password)
sys_auth_passwd(struct ssh *ssh, const char *password)
{
Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
char *encrypted_password, *salt = NULL;

180
auth.c
Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.125 2018/01/08 15:21:49 markus Exp $ */
/* $OpenBSD: auth.c,v 1.126 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -74,12 +74,14 @@
#include "authfile.h"
#include "ssherr.h"
#include "compat.h"
#include "channels.h"
/* import */
extern ServerOptions options;
extern int use_privsep;
extern Buffer loginmsg;
extern struct passwd *privsep_pw;
extern struct sshauthopt *auth_opts;
/* Debugging messages */
Buffer auth_debug;
@ -386,10 +388,8 @@ auth_maxtries_exceeded(Authctxt *authctxt)
* Check whether root logins are disallowed.
*/
int
auth_root_allowed(const char *method)
auth_root_allowed(struct ssh *ssh, const char *method)
{
struct ssh *ssh = active_state; /* XXX */
switch (options.permit_root_login) {
case PERMIT_YES:
return 1;
@ -400,7 +400,7 @@ auth_root_allowed(const char *method)
return 1;
break;
case PERMIT_FORCED_ONLY:
if (forced_command) {
if (auth_opts->force_command != NULL) {
logit("Root login accepted for forced command.");
return 1;
}
@ -993,3 +993,173 @@ subprocess(const char *tag, struct passwd *pw, const char *command,
*child = f;
return pid;
}
/* These functions link key/cert options to the auth framework */
/* Log sshauthopt options locally and (optionally) for remote transmission */
void
auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
{
int do_env = options.permit_user_env && opts->nenv > 0;
int do_permitopen = opts->npermitopen > 0 &&
(options.allow_tcp_forwarding & FORWARD_LOCAL) != 0;
size_t i;
char msg[1024], tbuf[32];
snprintf(tbuf, sizeof(tbuf), "%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",
opts->permit_agent_forwarding_flag ? " agent-forwarding" : "",
opts->force_command == NULL ? "" : " command",
do_env ? " environment" : "",
do_permitopen ? " permitopen" : "",
opts->permit_port_forwarding_flag ? " port-forwarding" : "",
opts->cert_principals == NULL ? "" : " principals",
opts->permit_pty_flag ? " pty" : "",
opts->force_tun_device == -1 ? "" : " tun=",
opts->force_tun_device == -1 ? "" : tbuf,
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->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 ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) {
for (i = 0; i < opts->npermitopen; i++) {
debug("%s: permitted open: %s",
loc, opts->permitopen[i]);
}
}
}
/* Activate a new set of key/cert options; merging with what is there. */
int
auth_activate_options(struct ssh *ssh, struct sshauthopt *opts)
{
struct sshauthopt *old = auth_opts;
const char *emsg = NULL;
debug("%s: setting new authentication options", __func__);
if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) {
error("Inconsistent authentication options: %s", emsg);
return -1;
}
return 0;
}
/* Disable forwarding, etc for the session */
void
auth_restrict_session(struct ssh *ssh)
{
struct sshauthopt *restricted;
debug("%s: restricting session", __func__);
/* A blank sshauthopt defaults to permitting nothing */
restricted = sshauthopt_new();
restricted->restricted = 1;
if (auth_activate_options(ssh, restricted) != 0)
fatal("%s: failed to restrict session", __func__);
sshauthopt_free(restricted);
}
int
auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw,
struct sshauthopt *opts, int allow_cert_authority, const char *loc)
{
const char *remote_ip = ssh_remote_ipaddr(ssh);
const char *remote_host = auth_get_canonical_hostname(ssh,
options.use_dns);
/* 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;
}

28
auth.h
Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.94 2018/01/08 15:21:49 markus Exp $ */
/* $OpenBSD: auth.h,v 1.95 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -42,9 +42,11 @@
#include <krb5.h>
#endif
struct passwd;
struct ssh;
struct sshkey;
struct sshbuf;
struct sshkey;
struct sshauthopt;
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
@ -128,11 +130,12 @@ struct KbdintDevice
int
auth_rhosts2(struct passwd *, const char *, const char *, const char *);
int auth_password(Authctxt *, const char *);
int auth_password(struct ssh *, const char *);
int hostbased_key_allowed(struct passwd *, const char *, char *,
struct sshkey *);
int user_key_allowed(struct passwd *, struct sshkey *, int);
int user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int,
struct sshauthopt **);
int auth2_key_already_used(Authctxt *, const struct sshkey *);
/*
@ -163,14 +166,12 @@ int auth_shadow_pwexpired(Authctxt *);
#include "audit.h"
void remove_kbdint_device(const char *);
void disable_forwarding(void);
void do_authentication2(Authctxt *);
void auth_log(Authctxt *, int, int, const char *, const char *);
void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
void userauth_finish(struct ssh *, int, const char *, const char *);
int auth_root_allowed(const char *);
int auth_root_allowed(struct ssh *, const char *);
void userauth_send_banner(const char *);
@ -214,8 +215,17 @@ int get_hostkey_index(struct sshkey *, int, struct ssh *);
int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **,
size_t *, const u_char *, size_t, const char *, u_int);
/* Key / cert options linkage to auth layer */
const struct sshauthopt *auth_options(struct ssh *);
int auth_activate_options(struct ssh *, struct sshauthopt *);
void auth_restrict_session(struct ssh *);
int auth_authorise_keyopts(struct ssh *, struct passwd *pw,
struct sshauthopt *, int, const char *);
void auth_log_authopts(const char *, const struct sshauthopt *, int);
/* debug messages during authentication */
void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void auth_debug_add(const char *fmt,...)
__attribute__((format(printf, 1, 2)));
void auth_debug_send(void);
void auth_debug_reset(void);
@ -227,7 +237,7 @@ struct passwd *fakepw(void);
pid_t subprocess(const char *, struct passwd *,
const char *, int, char **, FILE **, u_int flags);
int sys_auth_passwd(Authctxt *, const char *);
int sys_auth_passwd(struct ssh *, const char *);
#define SKEY_PROMPT "\nS/Key Password: "

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-none.c,v 1.20 2017/05/30 14:29:59 markus Exp $ */
/* $OpenBSD: auth2-none.c,v 1.21 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -68,7 +68,7 @@ userauth_none(struct ssh *ssh)
if ((r = sshpkt_get_end(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
if (options.permit_empty_passwd && options.password_authentication)
return (PRIVSEP(auth_password(ssh->authctxt, "")));
return (PRIVSEP(auth_password(ssh, "")));
return (0);
}

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-passwd.c,v 1.14 2017/05/30 14:29:59 markus Exp $ */
/* $OpenBSD: auth2-passwd.c,v 1.15 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -63,7 +63,7 @@ userauth_passwd(struct ssh *ssh)
if (change)
logit("password change not supported");
else if (PRIVSEP(auth_password(ssh->authctxt, password)) == 1)
else if (PRIVSEP(auth_password(ssh, password)) == 1)
authenticated = 1;
explicit_bzero(password, len);
free(password);

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.76 2018/02/07 22:52:45 dtucker Exp $ */
/* $OpenBSD: auth2-pubkey.c,v 1.77 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -88,6 +88,7 @@ static int
userauth_pubkey(struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
struct sshbuf *b;
struct sshkey *key = NULL;
char *pkalg, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
@ -95,6 +96,7 @@ userauth_pubkey(struct ssh *ssh)
size_t blen, slen;
int r, pktype;
int authenticated = 0;
struct sshauthopt *authopts = NULL;
if (!authctxt->valid) {
debug2("%s: disabled because of invalid user", __func__);
@ -185,7 +187,7 @@ userauth_pubkey(struct ssh *ssh)
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
sshbuf_len(b), NULL, ssh->compat)) == 0) {
authenticated = 1;
@ -210,7 +212,7 @@ userauth_pubkey(struct ssh *ssh)
* if a user is not allowed to login. is this an
* issue? -markus
*/
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
if (PRIVSEP(user_key_allowed(ssh, pw, key, 0, NULL))) {
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK))
!= 0 ||
(r = sshpkt_put_cstring(ssh, pkalg)) != 0 ||
@ -221,10 +223,14 @@ userauth_pubkey(struct ssh *ssh)
authctxt->postponed = 1;
}
}
if (authenticated != 1)
auth_clear_options();
done:
if (authenticated == 1 && auth_activate_options(ssh, authopts) != 0) {
debug("%s: key options inconsistent with existing", __func__);
authenticated = 0;
}
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
sshauthopt_free(authopts);
sshkey_free(key);
free(userstyle);
free(pkalg);
@ -254,18 +260,77 @@ match_principals_option(const char *principal_list, struct sshkey_cert *cert)
return 0;
}
/*
* Process a single authorized_principals format line. Returns 0 and sets
* authoptsp is principal is authorised, -1 otherwise. "loc" is used as a
* log preamble for file/line information.
*/
static int
process_principals(FILE *f, const char *file, struct passwd *pw,
const struct sshkey_cert *cert)
check_principals_line(struct ssh *ssh, char *cp, const struct sshkey_cert *cert,
const char *loc, struct sshauthopt **authoptsp)
{
char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
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;
}
static int
process_principals(struct ssh *ssh, FILE *f, const char *file,
const struct sshkey_cert *cert, struct sshauthopt **authoptsp)
{
char loc[256], line[SSH_MAX_PUBKEY_BYTES], *cp, *ep;
u_long linenum = 0;
u_int i, found_principal = 0;
u_int found_principal = 0;
if (authoptsp != NULL)
*authoptsp = NULL;
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
/* Always consume entire input */
if (found_principal)
continue;
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
@ -274,50 +339,33 @@ process_principals(FILE *f, const char *file, struct passwd *pw,
*ep = '\0';
if (!*cp || *cp == '\n')
continue;
/* Trim trailing whitespace. */
ep = cp + strlen(cp) - 1;
while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
*ep-- = '\0';
/*
* If the line has internal whitespace then assume it has
* key options.
*/
line_opts = NULL;
if ((ep = strrchr(cp, ' ')) != NULL ||
(ep = strrchr(cp, '\t')) != NULL) {
for (; *ep == ' ' || *ep == '\t'; ep++)
;
line_opts = cp;
cp = ep;
}
for (i = 0; i < cert->nprincipals; i++) {
if (strcmp(cp, cert->principals[i]) == 0) {
debug3("%s:%lu: matched principal \"%.100s\"",
file, linenum, cert->principals[i]);
if (auth_parse_options(pw, line_opts,
file, linenum) != 1)
continue;
found_principal = 1;
continue;
}
}
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum);
if (check_principals_line(ssh, cp, cert, loc, authoptsp) == 0)
found_principal = 1;
}
return found_principal;
}
/* XXX remove pw args here and elsewhere once ssh->authctxt is guaranteed */
static int
match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
match_principals_file(struct ssh *ssh, struct passwd *pw, char *file,
struct sshkey_cert *cert, struct sshauthopt **authoptsp)
{
FILE *f;
int success;
if (authoptsp != NULL)
*authoptsp = NULL;
temporarily_use_uid(pw);
debug("trying authorized principals file %s", file);
if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
restore_uid();
return 0;
}
success = process_principals(f, file, pw, cert);
success = process_principals(ssh, f, file, cert, authoptsp);
fclose(f);
restore_uid();
return success;
@ -328,12 +376,13 @@ match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
* returns 1 if the principal is allowed or 0 otherwise.
*/
static int
match_principals_command(struct passwd *user_pw, const struct sshkey *key)
match_principals_command(struct ssh *ssh, struct passwd *user_pw,
const struct sshkey *key, struct sshauthopt **authoptsp)
{
struct passwd *runas_pw = NULL;
const struct sshkey_cert *cert = key->cert;
FILE *f = NULL;
int r, ok, found_principal = 0;
struct passwd *pw;
int i, ac = 0, uid_swapped = 0;
pid_t pid;
char *tmp, *username = NULL, *command = NULL, **av = NULL;
@ -341,6 +390,8 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
char serial_s[16];
void (*osigchld)(int);
if (authoptsp != NULL)
*authoptsp = NULL;
if (options.authorized_principals_command == NULL)
return 0;
if (options.authorized_principals_command_user == NULL) {
@ -358,8 +409,8 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
/* Prepare and verify the user for the command */
username = percent_expand(options.authorized_principals_command_user,
"u", user_pw->pw_name, (char *)NULL);
pw = getpwnam(username);
if (pw == NULL) {
runas_pw = getpwnam(username);
if (runas_pw == NULL) {
error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s",
username, strerror(errno));
goto out;
@ -417,15 +468,15 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
/* Prepare a printable command for logs, etc. */
command = argv_assemble(ac, av);
if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command,
ac, av, &f,
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
goto out;
uid_swapped = 1;
temporarily_use_uid(pw);
temporarily_use_uid(runas_pw);
ok = process_principals(f, "(command)", pw, cert);
ok = process_principals(ssh, f, "(command)", cert, authoptsp);
fclose(f);
f = NULL;
@ -452,130 +503,225 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
free(keytext);
return found_principal;
}
static void
skip_space(char **cpp)
{
char *cp;
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
*cpp = cp;
}
/*
* 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).
*/
static int
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;
}
/*
* Check a single line of an authorized_keys-format file. Returns 0 if key
* matches, -1 otherwise. Will return key/cert options via *authoptsp
* on success. "loc" is used as file/line location in log messages.
*/
static int
check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
char *cp, const char *loc, struct sshauthopt **authoptsp)
{
int want_keytype = sshkey_is_cert(key) ? KEY_UNSPEC : key->type;
struct sshkey *found = NULL;
struct sshauthopt *keyopts = NULL, *certopts = NULL, *finalopts = NULL;
char *key_options = NULL, *fp = NULL;
const char *reason = NULL;
int ret = -1;
if (authoptsp != NULL)
*authoptsp = NULL;
if ((found = sshkey_new(want_keytype)) == NULL) {
debug3("%s: keytype %d failed", __func__, want_keytype);
goto out;
}
/* XXX djm: peek at key type in line and skip if unwanted */
if (sshkey_read(found, &cp) != 0) {
/* no key? check for options */
debug2("%s: check options: '%s'", loc, cp);
key_options = cp;
if (advance_past_options(&cp) != 0) {
reason = "invalid key option string";
goto fail_reason;
}
skip_space(&cp);
if (sshkey_read(found, &cp) != 0) {
/* still no key? advance to next line*/
debug2("%s: advance: '%s'", loc, cp);
goto out;
}
}
/* Parse key options now; we need to know if this is a CA key */
if ((keyopts = sshauthopt_parse(key_options, &reason)) == NULL) {
debug("%s: bad key options: %s", loc, reason);
auth_debug_add("%s: bad key options: %s", loc, reason);
goto out;
}
/* Ignore keys that don't match or incorrectly marked as CAs */
if (sshkey_is_cert(key)) {
/* Certificate; check signature key against CA */
if (!sshkey_equal(found, key->cert->signature_key) ||
!keyopts->cert_authority)
goto out;
} else {
/* Plain key: check it against key found in file */
if (!sshkey_equal(found, key) || keyopts->cert_authority)
goto out;
}
/* We have a candidate key, perform authorisation checks */
if ((fp = sshkey_fingerprint(found,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: fingerprint failed", __func__);
debug("%s: matching %s found: %s %s", loc,
sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp);
if (auth_authorise_keyopts(ssh, pw, keyopts,
sshkey_is_cert(key), loc) != 0) {
reason = "Refused by key options";
goto fail_reason;
}
/* That's all we need for plain keys. */
if (!sshkey_is_cert(key)) {
verbose("Accepted key %s %s found at %s",
sshkey_type(found), fp, loc);
finalopts = keyopts;
keyopts = NULL;
goto success;
}
/*
* Additional authorisation for certificates.
*/
/* Parse and check options present in certificate */
if ((certopts = sshauthopt_from_cert(key)) == NULL) {
reason = "Invalid certificate options";
goto fail_reason;
}
if (auth_authorise_keyopts(ssh, pw, certopts, 0, loc) != 0) {
reason = "Refused by certificate options";
goto fail_reason;
}
if ((finalopts = sshauthopt_merge(keyopts, certopts, &reason)) == NULL)
goto fail_reason;
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
* their username in the certificate principals list.
*/
if (keyopts->cert_principals != NULL &&
!match_principals_option(keyopts->cert_principals, key->cert)) {
reason = "Certificate does not contain an authorized principal";
goto fail_reason;
}
if (sshkey_cert_check_authority(key, 0, 0,
keyopts->cert_principals == NULL ? pw->pw_name : NULL, &reason) != 0)
goto fail_reason;
verbose("Accepted certificate ID \"%s\" (serial %llu) "
"signed by CA %s %s found at %s",
key->cert->key_id,
(unsigned long long)key->cert->serial,
sshkey_type(found), fp, loc);
success:
if (finalopts == NULL)
fatal("%s: internal error: missing options", __func__);
if (authoptsp != NULL) {
*authoptsp = finalopts;
finalopts = NULL;
}
/* success */
ret = 0;
goto out;
fail_reason:
error("%s", reason);
auth_debug_add("%s", reason);
out:
free(fp);
sshauthopt_free(keyopts);
sshauthopt_free(certopts);
sshauthopt_free(finalopts);
sshkey_free(found);
return ret;
}
/*
* Checks whether key is allowed in authorized_keys-format file,
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw)
check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f,
char *file, struct sshkey *key, struct sshauthopt **authoptsp)
{
char line[SSH_MAX_PUBKEY_BYTES];
char *cp, line[SSH_MAX_PUBKEY_BYTES], loc[256];
int found_key = 0;
u_long linenum = 0;
struct sshkey *found = NULL;
if (authoptsp != NULL)
*authoptsp = NULL;
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
char *cp, *key_options = NULL, *fp = NULL;
const char *reason = NULL;
/* Always consume entire file */
if (found_key)
continue;
sshkey_free(found);
found = sshkey_new(sshkey_is_cert(key) ? KEY_UNSPEC : key->type);
if (found == NULL)
goto done;
auth_clear_options();
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
cp = line;
skip_space(&cp);
if (!*cp || *cp == '\n' || *cp == '#')
continue;
if (sshkey_read(found, &cp) != 0) {
/* no key? check if there are options for this key */
int quoted = 0;
debug2("user_key_allowed: check options: '%s'", cp);
key_options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (sshkey_read(found, &cp) != 0) {
debug2("user_key_allowed: advance: '%s'", cp);
/* still no key? advance to next line*/
continue;
}
}
if (sshkey_is_cert(key)) {
if (!sshkey_equal(found, key->cert->signature_key))
continue;
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
if (!key_is_cert_authority)
continue;
if ((fp = sshkey_fingerprint(found,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching CA found: file %s, line %lu, %s %s",
file, linenum, sshkey_type(found), fp);
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
* their username in the certificate principals list.
*/
if (authorized_principals != NULL &&
!match_principals_option(authorized_principals,
key->cert)) {
reason = "Certificate does not contain an "
"authorized principal";
fail_reason:
free(fp);
error("%s", reason);
auth_debug_add("%s", reason);
continue;
}
if (sshkey_cert_check_authority(key, 0, 0,
authorized_principals == NULL ? pw->pw_name : NULL,
&reason) != 0)
goto fail_reason;
if (auth_cert_options(key, pw, &reason) != 0)
goto fail_reason;
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(found), fp, file);
free(fp);
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum);
if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0)
found_key = 1;
break;
} else if (sshkey_equal(found, key)) {
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
if (key_is_cert_authority)
continue;
if ((fp = sshkey_fingerprint(found,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching key found: file %s, line %lu %s %s",
file, linenum, sshkey_type(found), fp);
free(fp);
found_key = 1;
continue;
}
}
done:
sshkey_free(found);
if (!found_key)
debug2("key not found");
return found_key;
}
/* Authenticate a certificate key against TrustedUserCAKeys */
static int
user_cert_trusted_ca(struct passwd *pw, struct sshkey *key)
user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
struct sshauthopt **authoptsp)
{
char *ca_fp, *principals_file = NULL;
const char *reason;
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;
@ -596,36 +742,69 @@ user_cert_trusted_ca(struct passwd *pw, struct sshkey *key)
* against the username.
*/
if ((principals_file = authorized_principals_file(pw)) != NULL) {
if (match_principals_file(principals_file, pw, key->cert))
if (match_principals_file(ssh, pw, principals_file,
key->cert, &principals_opts))
found_principal = 1;
}
/* Try querying command if specified */
if (!found_principal && match_principals_command(pw, key))
if (!found_principal && match_principals_command(ssh, pw, key,
&principals_opts))
found_principal = 1;
/* If principals file or command is specified, then require a match */
use_authorized_principals = principals_file != NULL ||
options.authorized_principals_command != NULL;
if (!found_principal && use_authorized_principals) {
reason = "Certificate does not contain an authorized principal";
fail_reason:
error("%s", reason);
auth_debug_add("%s", reason);
goto out;
goto fail_reason;
}
if (use_authorized_principals && principals_opts == NULL)
fatal("%s: internal error: missing principals_opts", __func__);
if (sshkey_cert_check_authority(key, 0, 1,
use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
goto fail_reason;
if (auth_cert_options(key, pw, &reason) != 0)
goto fail_reason;
/* Check authority from options in key and from principals file/cmd */
if ((cert_opts = sshauthopt_from_cert(key)) == NULL) {
reason = "Invalid certificate options";
goto fail_reason;
}
if (auth_authorise_keyopts(ssh, pw, cert_opts, 0, "cert") != 0) {
reason = "Refused by certificate options";
goto fail_reason;
}
if (principals_opts == NULL) {
final_opts = cert_opts;
cert_opts = NULL;
} else {
if (auth_authorise_keyopts(ssh, pw, principals_opts, 0,
"principals") != 0) {
reason = "Refused by certificate principals options";
goto fail_reason;
}
if ((final_opts = sshauthopt_merge(principals_opts,
cert_opts, &reason)) == NULL) {
fail_reason:
error("%s", reason);
auth_debug_add("%s", reason);
goto out;
}
}
/* 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;
@ -636,17 +815,22 @@ user_cert_trusted_ca(struct passwd *pw, struct sshkey *key)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
user_key_allowed2(struct passwd *pw, struct sshkey *key, char *file)
user_key_allowed2(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
char *file, struct sshauthopt **authoptsp)
{
FILE *f;
int found_key = 0;
if (authoptsp != NULL)
*authoptsp = NULL;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
found_key = check_authkeys_file(f, file, key, pw);
found_key = check_authkeys_file(ssh, pw, f, file,
key, authoptsp);
fclose(f);
}
@ -659,17 +843,20 @@ user_key_allowed2(struct passwd *pw, struct sshkey *key, char *file)
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw,
struct sshkey *key, struct sshauthopt **authoptsp)
{
struct passwd *runas_pw = NULL;
FILE *f = NULL;
int r, ok, found_key = 0;
struct passwd *pw;
int i, uid_swapped = 0, ac = 0;
pid_t pid;
char *username = NULL, *key_fp = NULL, *keytext = NULL;
char *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) {
@ -686,8 +873,8 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
/* Prepare and verify the user for the command */
username = percent_expand(options.authorized_keys_command_user,
"u", user_pw->pw_name, (char *)NULL);
pw = getpwnam(username);
if (pw == NULL) {
runas_pw = getpwnam(username);
if (runas_pw == NULL) {
error("AuthorizedKeysCommandUser \"%s\" not found: %s",
username, strerror(errno));
goto out;
@ -745,15 +932,16 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
xasprintf(&command, "%s %s", av[0], av[1]);
}
if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command,
ac, av, &f,
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
goto out;
uid_swapped = 1;
temporarily_use_uid(pw);
temporarily_use_uid(runas_pw);
ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
ok = check_authkeys_file(ssh, user_pw, f,
options.authorized_keys_command, key, authoptsp);
fclose(f);
f = NULL;
@ -783,10 +971,14 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
* Check whether key authenticates and authorises the user.
*/
int
user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt)
user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
int auth_attempt, struct sshauthopt **authoptsp)
{
u_int success, i;
char *file;
struct sshauthopt *opts = NULL;
if (authoptsp != NULL)
*authoptsp = NULL;
if (auth_key_is_revoked(key))
return 0;
@ -794,25 +986,31 @@ user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt)
auth_key_is_revoked(key->cert->signature_key))
return 0;
success = user_cert_trusted_ca(pw, key);
if (success)
return success;
if ((success = user_cert_trusted_ca(ssh, pw, key, &opts)) != 0)
goto out;
sshauthopt_free(opts);
opts = NULL;
success = user_key_command_allowed2(pw, key);
if (success > 0)
return success;
if ((success = user_key_command_allowed2(ssh, pw, key, &opts)) != 0)
goto out;
sshauthopt_free(opts);
opts = NULL;
for (i = 0; !success && i < options.num_authkeys_files; i++) {
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
success = user_key_allowed2(pw, key, file);
success = user_key_allowed2(ssh, pw, key, file, &opts);
free(file);
}
out:
if (success && authoptsp != NULL) {
*authoptsp = opts;
opts = NULL;
}
sshauthopt_free(opts);
return success;
}

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: auth2.c,v 1.144 2018/01/23 05:27:21 djm Exp $ */
/* $OpenBSD: auth2.c,v 1.145 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -310,7 +310,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method,
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(method)) {
!auth_root_allowed(ssh, method)) {
authenticated = 0;
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));

3
misc.c
Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: misc.c,v 1.124 2018/03/02 03:02:11 djm Exp $ */
/* $OpenBSD: misc.c,v 1.125 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@ -1921,6 +1921,7 @@ child_set_env(char ***envp, u_int *envsizep, const char *name,
}
/* 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);
}

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.179 2018/02/05 05:37:46 tb Exp $ */
/* $OpenBSD: monitor.c,v 1.180 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -116,6 +116,7 @@ extern u_char session_id[];
extern Buffer auth_debug;
extern int auth_debug_init;
extern Buffer loginmsg;
extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */
/* State exported from the child */
static struct sshbuf *child_state;
@ -172,6 +173,7 @@ static Authctxt *authctxt;
static u_char *key_blob = NULL;
static u_int key_bloblen = 0;
static int key_blobtype = MM_NOKEY;
static struct sshauthopt *key_opts = NULL;
static char *hostbased_cuser = NULL;
static char *hostbased_chost = NULL;
static char *auth_method = "unknown";
@ -252,7 +254,6 @@ struct mon_table mon_dispatch_postauth20[] = {
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)
{
@ -297,6 +298,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
authctxt = _authctxt;
memset(authctxt, 0, sizeof(*authctxt));
ssh->authctxt = authctxt;
authctxt->loginmsg = &loginmsg;
@ -331,7 +333,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
fatal("%s: unexpected authentication from %d",
__func__, ent->type);
if (authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(auth_method))
!auth_root_allowed(ssh, auth_method))
authenticated = 0;
#ifdef USE_PAM
/* PAM needs to perform account checks after auth */
@ -365,6 +367,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
debug("%s: %s has been authenticated by privileged process",
__func__, authctxt->user);
ssh->authctxt = NULL;
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
mm_get_keystate(pmonitor);
@ -413,7 +416,7 @@ monitor_child_postauth(struct monitor *pmonitor)
monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
if (!no_pty_flag) {
if (auth_opts->permit_pty_flag) {
monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
}
@ -558,9 +561,11 @@ monitor_reset_key_state(void)
free(key_blob);
free(hostbased_cuser);
free(hostbased_chost);
sshauthopt_free(key_opts);
key_blob = NULL;
key_bloblen = 0;
key_blobtype = MM_NOKEY;
key_opts = NULL;
hostbased_cuser = NULL;
hostbased_chost = NULL;
}
@ -828,6 +833,7 @@ mm_answer_authserv(int sock, Buffer *m)
int
mm_answer_authpassword(int sock, Buffer *m)
{
struct ssh *ssh = active_state; /* XXX */
static int call_count;
char *passwd;
int authenticated;
@ -838,7 +844,7 @@ mm_answer_authpassword(int sock, Buffer *m)
passwd = buffer_get_string(m, &plen);
/* Only authenticate if the context is valid */
authenticated = options.password_authentication &&
auth_password(authctxt, passwd);
auth_password(ssh, passwd);
explicit_bzero(passwd, strlen(passwd));
free(passwd);
@ -1129,15 +1135,16 @@ mm_answer_pam_free_ctx(int sock, Buffer *m)
int
mm_answer_keyallowed(int sock, Buffer *m)
{
struct ssh *ssh = active_state; /* XXX */
struct sshkey *key;
char *cuser, *chost;
u_char *blob;
u_int bloblen, pubkey_auth_attempt;
enum mm_keytype type = 0;
int allowed = 0;
int r, allowed = 0;
struct sshauthopt *opts = NULL;
debug3("%s entering", __func__);
type = buffer_get_int(m);
cuser = buffer_get_string(m, NULL);
chost = buffer_get_string(m, NULL);
@ -1156,28 +1163,31 @@ mm_answer_keyallowed(int sock, Buffer *m)
switch (type) {
case MM_USERKEY:
allowed = options.pubkey_authentication &&
!auth2_key_already_used(authctxt, key) &&
match_pattern_list(sshkey_ssh_name(key),
options.pubkey_key_types, 0) == 1 &&
user_key_allowed(authctxt->pw, key,
pubkey_auth_attempt);
auth_method = "publickey";
if (options.pubkey_authentication &&
(!pubkey_auth_attempt || allowed != 1))
auth_clear_options();
if (!options.pubkey_authentication)
break;
if (auth2_key_already_used(authctxt, key))
break;
if (match_pattern_list(sshkey_ssh_name(key),
options.pubkey_key_types, 0) != 1)
break;
allowed = user_key_allowed(ssh, authctxt->pw, key,
pubkey_auth_attempt, &opts);
break;
case MM_HOSTKEY:
allowed = options.hostbased_authentication &&
!auth2_key_already_used(authctxt, key) &&
match_pattern_list(sshkey_ssh_name(key),
options.hostbased_key_types, 0) == 1 &&
hostbased_key_allowed(authctxt->pw,
auth_method = "hostbased";
if (!options.hostbased_authentication)
break;
if (auth2_key_already_used(authctxt, key))
break;
if (match_pattern_list(sshkey_ssh_name(key),
options.hostbased_key_types, 0) != 1)
break;
allowed = hostbased_key_allowed(authctxt->pw,
cuser, chost, key);
auth2_record_info(authctxt,
"client user \"%.100s\", client host \"%.100s\"",
cuser, chost);
auth_method = "hostbased";
break;
default:
fatal("%s: unknown key type %d", __func__, type);
@ -1185,7 +1195,10 @@ mm_answer_keyallowed(int sock, Buffer *m)
}
}
debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");
debug3("%s: %s authentication%s: %s key is %s", __func__,
auth_method, pubkey_auth_attempt ? "" : " test",
(key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key),
allowed ? "allowed" : "not allowed");
auth2_record_key(authctxt, 0, key);
sshkey_free(key);
@ -1198,6 +1211,7 @@ mm_answer_keyallowed(int sock, Buffer *m)
key_blob = blob;
key_bloblen = bloblen;
key_blobtype = type;
key_opts = opts;
hostbased_cuser = cuser;
hostbased_chost = chost;
} else {
@ -1210,10 +1224,13 @@ mm_answer_keyallowed(int sock, Buffer *m)
buffer_clear(m);
buffer_put_int(m, allowed);
buffer_put_int(m, forced_command != NULL);
if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0)
fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
if (!allowed)
sshauthopt_free(opts);
return (0);
}
@ -1336,6 +1353,7 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
int
mm_answer_keyverify(int sock, struct sshbuf *m)
{
struct ssh *ssh = active_state; /* XXX */
struct sshkey *key;
u_char *signature, *data, *blob;
char *sigalg;
@ -1390,6 +1408,8 @@ mm_answer_keyverify(int sock, struct sshbuf *m)
free(data);
free(sigalg);
if (key_blobtype == MM_USERKEY)
auth_activate_options(ssh, key_opts);
monitor_reset_key_state();
sshkey_free(key);

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.98 2018/01/08 15:14:44 markus Exp $ */
/* $OpenBSD: monitor_wrap.c,v 1.99 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -351,7 +351,7 @@ mm_inform_authserv(char *service, char *style)
/* Do the password authentication */
int
mm_auth_password(Authctxt *authctxt, char *password)
mm_auth_password(struct ssh *ssh, char *password)
{
Buffer m;
int authenticated = 0;
@ -378,34 +378,38 @@ mm_auth_password(Authctxt *authctxt, char *password)
}
int
mm_user_key_allowed(struct passwd *pw, struct sshkey *key,
int pubkey_auth_attempt)
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));
pubkey_auth_attempt, authoptp));
}
int
mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
struct sshkey *key)
{
return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0));
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 sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp)
{
Buffer m;
u_char *blob;
u_int len;
int allowed = 0, have_forced = 0;
int r, allowed = 0;
struct sshauthopt *opts = NULL;
debug3("%s entering", __func__);
if (authoptp != NULL)
*authoptp = NULL;
/* Convert the key to a blob and the pass it over */
if (!key_to_blob(key, &blob, &len))
return (0);
return 0;
buffer_init(&m);
buffer_put_int(&m, type);
@ -418,18 +422,24 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_KEYALLOWED, &m);
allowed = buffer_get_int(&m);
/* fake forced command */
auth_clear_options();
have_forced = buffer_get_int(&m);
forced_command = have_forced ? xstrdup("true") : NULL;
if (allowed && type == MM_USERKEY) {
if ((r = sshauthopt_deserialise(&m, &opts)) != 0)
fatal("%s: sshauthopt_deserialise: %s",
__func__, ssh_err(r));
}
buffer_free(&m);
return (allowed);
if (authoptp != NULL) {
*authoptp = opts;
opts = NULL;
}
sshauthopt_free(opts);
return allowed;
}
/*

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.h,v 1.36 2017/12/18 02:25:15 djm Exp $ */
/* $OpenBSD: monitor_wrap.h,v 1.37 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -35,6 +35,8 @@ enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY };
struct monitor;
struct Authctxt;
struct sshkey;
struct sshauthopt;
void mm_log_handler(LogLevel, const char *, void *);
int mm_is_monitor(void);
@ -44,10 +46,11 @@ int mm_key_sign(struct sshkey *, u_char **, u_int *, const u_char *, u_int,
void mm_inform_authserv(char *, char *);
struct passwd *mm_getpwnamallow(const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct Authctxt *, char *);
int mm_auth_password(struct ssh *, char *);
int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *,
int);
int mm_user_key_allowed(struct passwd *, struct sshkey *, int);
int, struct sshauthopt **);
int mm_user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int,
struct sshauthopt **);
int mm_hostbased_key_allowed(struct passwd *, const char *,
const char *, struct sshkey *);
int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.c,v 1.204 2018/02/11 21:16:56 dtucker Exp $ */
/* $OpenBSD: serverloop.c,v 1.205 2018/03/03 03:15:51 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -82,6 +82,7 @@ extern ServerOptions options;
/* XXX */
extern Authctxt *the_authctxt;
extern struct sshauthopt *auth_opts;
extern int use_privsep;
static int no_more_sessions = 0; /* Disallow further sessions. */
@ -456,12 +457,13 @@ server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
originator_port = packet_get_int();
packet_check_eom();
debug("server_request_direct_tcpip: originator %s port %d, target %s "
"port %d", originator, originator_port, target, target_port);
debug("%s: originator %s port %d, target %s port %d", __func__,
originator, originator_port, target, target_port);
/* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding) {
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 {
@ -487,20 +489,20 @@ server_request_direct_streamlocal(struct ssh *ssh)
struct passwd *pw = the_authctxt->pw;
if (pw == NULL || !the_authctxt->valid)
fatal("server_input_global_request: no/invalid user");
fatal("%s: no/invalid user", __func__);
target = packet_get_string(NULL);
originator = packet_get_string(NULL);
originator_port = packet_get_int();
packet_check_eom();
debug("server_request_direct_streamlocal: originator %s port %d, target %s",
debug("%s: originator %s port %d, target %s", __func__,
originator, originator_port, target);
/* XXX fine grained permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding &&
(pw->pw_uid == 0 || use_privsep)) {
auth_opts->permit_port_forwarding_flag &&
!options.disable_forwarding && (pw->pw_uid == 0 || use_privsep)) {
c = channel_connect_to_path(ssh, target,
"direct-streamlocal@openssh.com", "direct-streamlocal");
} else {
@ -519,8 +521,7 @@ static Channel *
server_request_tun(struct ssh *ssh)
{
Channel *c = NULL;
int mode, tun;
int sock;
int mode, tun, sock;
char *tmp, *ifname = NULL;
mode = packet_get_int();
@ -539,10 +540,10 @@ server_request_tun(struct ssh *ssh)
}
tun = packet_get_int();
if (forced_tun_device != -1) {
if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
if (auth_opts->force_tun_device != -1) {
if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != tun)
goto done;
tun = forced_tun_device;
tun = auth_opts->force_tun_device;
}
sock = tun_open(tun, mode, &ifname);
if (sock < 0)
@ -767,7 +768,8 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
/* check permissions */
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
no_port_forwarding_flag || options.disable_forwarding ||
!auth_opts->permit_port_forwarding_flag ||
options.disable_forwarding ||
(!want_reply && fwd.listen_port == 0) ||
(fwd.listen_port != 0 &&
!bind_permitted(fwd.listen_port, pw->pw_uid))) {
@ -805,7 +807,8 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
/* check permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
|| no_port_forwarding_flag || options.disable_forwarding ||
|| !auth_opts->permit_port_forwarding_flag ||
options.disable_forwarding ||
(pw->pw_uid != 0 && !use_privsep)) {
success = 0;
packet_send_debug("Server has disabled "

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.293 2017/10/23 05:08:00 djm Exp $ */
/* $OpenBSD: session.c,v 1.294 2018/03/03 03:15:51 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -140,6 +140,7 @@ extern u_int utmp_len;
extern int startup_pipe;
extern void destroy_sensitive_data(void);
extern Buffer loginmsg;
extern struct sshauthopt *auth_opts;
char *tun_fwd_ifnames; /* serverloop.c */
/* original command from peer. */
@ -288,14 +289,42 @@ prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
restore_uid();
}
static void
set_permitopen_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)
return;
channel_clear_permitted_opens(ssh);
for (i = 0; i < auth_opts->npermitopen; i++) {
tmp = cp = xstrdup(auth_opts->permitopen[i]);
/* This shouldn't fail as it has already been checked */
if ((host = hpdelim(&cp)) == NULL)
fatal("%s: internal error: hpdelim", __func__);
host = cleanhostname(host);
if (cp == NULL || (port = permitopen_port(cp)) < 0)
fatal("%s: internal error: permitopen port",
__func__);
channel_add_permitted_opens(ssh, 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? */
if (no_port_forwarding_flag || options.disable_forwarding ||
set_permitopen_from_authopts(ssh, auth_opts);
if (!auth_opts->permit_port_forwarding_flag ||
options.disable_forwarding ||
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
channel_disable_adm_local_opens(ssh);
else
@ -642,9 +671,9 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
original_command = command;
command = options.adm_forced_command;
forced = "(config)";
} else if (forced_command) {
} else if (auth_opts->force_command != NULL) {
original_command = command;
command = forced_command;
command = auth_opts->force_command;
forced = "(key-option)";
}
if (forced != NULL) {
@ -947,8 +976,9 @@ static char **
do_setup_env(struct ssh *ssh, Session *s, const char *shell)
{
char buf[256];
size_t n;
u_int i, envsize;
char **env, *laddr;
char *ocp, *cp, **env, *laddr;
struct passwd *pw = s->pw;
#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
char *path = NULL;
@ -1023,20 +1053,17 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
/* Set custom environment options from RSA authentication. */
while (custom_environment) {
struct envstring *ce = custom_environment;
char *str = ce->s;
for (i = 0; str[i] != '=' && str[i]; i++)
;
if (str[i] == '=') {
str[i] = 0;
child_set_env(&env, &envsize, str, str + i + 1);
/* Set custom environment options from pubkey authentication. */
if (options.permit_user_env) {
for (n = 0 ; n < auth_opts->nenv; n++) {
ocp = xstrdup(auth_opts->env[n]);
cp = strchr(ocp, '=');
if (*cp == '=') {
*cp = '\0';
child_set_env(&env, &envsize, ocp, cp + 1);
}
free(ocp);
}
custom_environment = ce->next;
free(ce->s);
free(ce);
}
/* SSH_CLIENT deprecated */
@ -1138,7 +1165,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
* first in this order).
*/
static void
do_rc_files(Session *s, const char *shell)
do_rc_files(struct ssh *ssh, Session *s, const char *shell)
{
FILE *f = NULL;
char cmd[1024];
@ -1150,7 +1177,7 @@ do_rc_files(Session *s, const char *shell)
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
if (!s->is_subsystem && options.adm_forced_command == NULL &&
!no_user_rc && options.permit_user_rc &&
auth_opts->permit_user_rc && options.permit_user_rc &&
stat(_PATH_SSH_USER_RC, &st) >= 0) {
snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
@ -1570,7 +1597,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
closefrom(STDERR_FILENO + 1);
do_rc_files(s, shell);
do_rc_files(ssh, s, shell);
/* restore SIGPIPE for child */
signal(SIGPIPE, SIG_DFL);
@ -1833,8 +1860,8 @@ session_pty_req(struct ssh *ssh, Session *s)
u_int len;
int n_bytes;
if (no_pty_flag || !options.permit_tty) {
debug("Allocating a pty not permitted for this authentication.");
if (!auth_opts->permit_pty_flag || !options.permit_tty) {
debug("Allocating a pty not permitted for this connection.");
return 0;
}
if (s->ttyfd != -1) {
@ -2022,9 +2049,11 @@ static int
session_auth_agent_req(struct ssh *ssh, Session *s)
{
static int called = 0;
packet_check_eom();
if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
debug("session_auth_agent_req: no_agent_forwarding_flag");
if (!auth_opts->permit_agent_forwarding_flag ||
!options.allow_agent_forwarding) {
debug("%s: agent forwarding disabled", __func__);
return 0;
}
if (called) {
@ -2402,8 +2431,8 @@ session_setup_x11fwd(struct ssh *ssh, Session *s)
char hostname[NI_MAXHOST];
u_int i;
if (no_x11_forwarding_flag) {
packet_send_debug("X11 forwarding disabled in user configuration file.");
if (!auth_opts->permit_x11_forwarding_flag) {
packet_send_debug("X11 forwarding disabled by key options.");
return 0;
}
if (!options.x11_forwarding) {
@ -2412,7 +2441,7 @@ session_setup_x11fwd(struct ssh *ssh, Session *s)
}
if (options.xauth_location == NULL ||
(stat(options.xauth_location, &st) == -1)) {
packet_send_debug("No xauth program; cannot forward with spoofing.");
packet_send_debug("No xauth program; cannot forward X11.");
return 0;
}
if (s->display != NULL) {

12
sshd.c
Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.505 2018/02/23 15:58:38 markus Exp $ */
/* $OpenBSD: sshd.c,v 1.506 2018/03/03 03:15:51 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -119,6 +119,7 @@
#endif
#include "monitor_wrap.h"
#include "ssh-sandbox.h"
#include "auth-options.h"
#include "version.h"
#include "ssherr.h"
@ -232,6 +233,9 @@ static int privsep_chroot = 1;
/* global authentication context */
Authctxt *the_authctxt = NULL;
/* global key/cert auth options. XXX move to permanent ssh->authctxt? */
struct sshauthopt *auth_opts = NULL;
/* sshd_config buffer */
Buffer cfg;
@ -2066,6 +2070,10 @@ main(int ac, char **av)
/* XXX global for cleanup, access from other modules */
the_authctxt = authctxt;
/* Set default key authentication options */
if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL)
fatal("allocation failed");
/* prepare buffer to collect messages to display to user after login */
buffer_init(&loginmsg);
auth_debug_reset();
@ -2122,7 +2130,7 @@ main(int ac, char **av)
#ifdef USE_PAM
if (options.use_pam) {
do_pam_setcred(1);
do_pam_session();
do_pam_session(ssh);
}
#endif