summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-03-03 03:15:51 +0000
committerDamien Miller <djm@mindrot.org>2018-03-03 14:37:16 +1100
commit7c856857607112a3dfe6414696bf4c7ab7fb0cb3 (patch)
tree48c837fc9c9e11d64862d4f54c1a886b54d8721c
parent90c4bec8b5f9ec4c003ae4abdf13fc7766f00c8b (diff)
downloadopenssh-git-7c856857607112a3dfe6414696bf4c7ab7fb0cb3.tar.gz
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
-rw-r--r--.depend7
-rw-r--r--auth-options.c650
-rw-r--r--auth-options.h46
-rw-r--r--auth-pam.c4
-rw-r--r--auth-pam.h4
-rw-r--r--auth-passwd.c30
-rw-r--r--auth.c180
-rw-r--r--auth.h28
-rw-r--r--auth2-none.c4
-rw-r--r--auth2-passwd.c4
-rw-r--r--auth2-pubkey.c532
-rw-r--r--auth2.c4
-rw-r--r--misc.c3
-rw-r--r--monitor.c70
-rw-r--r--monitor_wrap.c44
-rw-r--r--monitor_wrap.h11
-rw-r--r--serverloop.c33
-rw-r--r--session.c85
-rw-r--r--sshd.c12
19 files changed, 767 insertions, 984 deletions
diff --git a/.depend b/.depend
index 4c6b49d5..0893a87a 100644
--- a/.depend
+++ b/.depend
@@ -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
diff --git a/auth-options.c b/auth-options.c
index 8b93b51e..484e44b7 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -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
diff --git a/auth-options.h b/auth-options.h
index 0dbfc325..16871d75 100644
--- a/auth-options.h
+++ b/auth-options.h
@@ -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.
diff --git a/auth-pam.c b/auth-pam.c
index de29c04c..50d2073d 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -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));
}
diff --git a/auth-pam.h b/auth-pam.h
index c47b442e..41986074 100644
--- a/auth-pam.h
+++ b/auth-pam.h
@@ -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 *);
diff --git a/auth-passwd.c b/auth-passwd.c
index 996c2cf7..6097fdd2 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -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;
diff --git a/auth.c b/auth.c
index fd02eff0..041a09e3 100644
--- a/auth.c
+++ b/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;
+}
diff --git a/auth.h b/auth.h
index 64f3c2eb..23ce67ca 100644
--- a/auth.h
+++ b/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: "
diff --git a/auth2-none.c b/auth2-none.c
index 35d25fa6..8d4e9bb8 100644
--- a/auth2-none.c
+++ b/auth2-none.c
@@ -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);
}
diff --git a/auth2-passwd.c b/auth2-passwd.c
index 5f7ba324..445016ae 100644
--- a/auth2-passwd.c
+++ b/auth2-passwd.c
@@ -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);
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 8fb7ffe7..8024b1d6 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -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
+check_principals_line(struct ssh *ssh, char *cp, const struct sshkey_cert *cert,
+ const char *loc, struct sshauthopt **authoptsp)
+{
+ u_int i, found = 0;
+ char *ep, *line_opts;
+ const char *reason = NULL;
+ struct sshauthopt *opts = NULL;
+
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+
+ /* Trim trailing whitespace. */
+ ep = cp + strlen(cp) - 1;
+ while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
+ *ep-- = '\0';
+
+ /*
+ * If the line has internal whitespace then assume it has
+ * key options.
+ */
+ line_opts = NULL;
+ if ((ep = strrchr(cp, ' ')) != NULL ||
+ (ep = strrchr(cp, '\t')) != NULL) {
+ for (; *ep == ' ' || *ep == '\t'; ep++)
+ ;
+ line_opts = cp;
+ cp = ep;
+ }
+ if ((opts = sshauthopt_parse(line_opts, &reason)) == NULL) {
+ debug("%s: bad principals options: %s", loc, reason);
+ auth_debug_add("%s: bad principals options: %s", loc, reason);
+ return -1;
+ }
+ /* Check principals in cert against those on line */
+ for (i = 0; i < cert->nprincipals; i++) {
+ if (strcmp(cp, cert->principals[i]) != 0)
+ continue;
+ debug3("%s: matched principal \"%.100s\"",
+ loc, cert->principals[i]);
+ found = 1;
+ }
+ if (found && authoptsp != NULL) {
+ *authoptsp = opts;
+ opts = NULL;
+ }
+ sshauthopt_free(opts);
+ return found ? 0 : -1;
+}
+
static int
-process_principals(FILE *f, const char *file, struct passwd *pw,
- const struct sshkey_cert *cert)
+process_principals(struct ssh *ssh, FILE *f, const char *file,
+ const struct sshkey_cert *cert, struct sshauthopt **authoptsp)
{
- char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
+ 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;
- while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
- char *cp, *key_options = NULL, *fp = NULL;
- const char *reason = NULL;
+ if (authoptsp != NULL)
+ *authoptsp = NULL;
+ while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
/* 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);
- 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);
+ snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum);
+ if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0)
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)
+
+ /* 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;
}
diff --git a/auth2.c b/auth2.c
index c80911ae..e0034229 100644
--- a/auth2.c
+++ b/auth2.c
@@ -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));
diff --git a/misc.c b/misc.c
index b45a9ec6..1e660b02 100644
--- a/misc.c
+++ b/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);
}
diff --git a/monitor.c b/monitor.c
index e4ac3ccf..c68e1b0d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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);
diff --git a/monitor_wrap.c b/monitor_wrap.c
index cce318bc..9666bda4 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -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;
}
/*
diff --git a/monitor_wrap.h b/monitor_wrap.h
index f5af1e81..76233270 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -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,
diff --git a/serverloop.c b/serverloop.c
index 7e2abd52..d6fe24cc 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -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 "
diff --git a/session.c b/session.c
index 51c5ea0e..58826db1 100644
--- a/session.c
+++ b/session.c
@@ -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) {
diff --git a/sshd.c b/sshd.c
index 0b9a7ec4..fd95b681 100644
--- a/sshd.c
+++ b/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