Import debian 5.9p1-1
authorSam Hartman <hartmans@debian.org>
Mon, 19 Sep 2011 20:21:20 +0000 (16:21 -0400)
committerSam Hartman <hartmans@debian.org>
Mon, 19 Sep 2011 20:21:20 +0000 (16:21 -0400)
320 files changed:
.pc/.quilt_patches [new file with mode: 0644]
.pc/.quilt_series [new file with mode: 0644]
.pc/.version [new file with mode: 0644]
.pc/applied-patches [new file with mode: 0644]
.pc/auth-log-verbosity.patch/auth-options.c [new file with mode: 0644]
.pc/auth-log-verbosity.patch/auth-options.h [new file with mode: 0644]
.pc/auth-log-verbosity.patch/auth-rsa.c [new file with mode: 0644]
.pc/auth-log-verbosity.patch/auth2-pubkey.c [new file with mode: 0644]
.pc/authorized-keys-man-symlink.patch/Makefile.in [new file with mode: 0644]
.pc/debian-banner.patch/servconf.c [new file with mode: 0644]
.pc/debian-banner.patch/servconf.h [new file with mode: 0644]
.pc/debian-banner.patch/sshd.c [new file with mode: 0644]
.pc/debian-banner.patch/sshd_config.5 [new file with mode: 0644]
.pc/debian-config.patch/readconf.c [new file with mode: 0644]
.pc/debian-config.patch/ssh_config [new file with mode: 0644]
.pc/debian-config.patch/ssh_config.5 [new file with mode: 0644]
.pc/debian-config.patch/sshd_config [new file with mode: 0644]
.pc/debian-config.patch/sshd_config.5 [new file with mode: 0644]
.pc/dnssec-sshfp.patch/dns.c [new file with mode: 0644]
.pc/dnssec-sshfp.patch/openbsd-compat/getrrsetbyname.c [new file with mode: 0644]
.pc/dnssec-sshfp.patch/openbsd-compat/getrrsetbyname.h [new file with mode: 0644]
.pc/doc-hash-tab-completion.patch/ssh_config.5 [new file with mode: 0644]
.pc/gnome-ssh-askpass2-icon.patch/contrib/gnome-ssh-askpass2.c [new file with mode: 0644]
.pc/gssapi.patch/ChangeLog.gssapi [new file with mode: 0644]
.pc/gssapi.patch/Makefile.in [new file with mode: 0644]
.pc/gssapi.patch/auth-krb5.c [new file with mode: 0644]
.pc/gssapi.patch/auth2-gss.c [new file with mode: 0644]
.pc/gssapi.patch/auth2.c [new file with mode: 0644]
.pc/gssapi.patch/clientloop.c [new file with mode: 0644]
.pc/gssapi.patch/config.h.in [new file with mode: 0644]
.pc/gssapi.patch/configure [new file with mode: 0755]
.pc/gssapi.patch/configure.ac [new file with mode: 0644]
.pc/gssapi.patch/gss-genr.c [new file with mode: 0644]
.pc/gssapi.patch/gss-serv-krb5.c [new file with mode: 0644]
.pc/gssapi.patch/gss-serv.c [new file with mode: 0644]
.pc/gssapi.patch/kex.c [new file with mode: 0644]
.pc/gssapi.patch/kex.h [new file with mode: 0644]
.pc/gssapi.patch/kexgssc.c [new file with mode: 0644]
.pc/gssapi.patch/kexgsss.c [new file with mode: 0644]
.pc/gssapi.patch/key.c [new file with mode: 0644]
.pc/gssapi.patch/key.h [new file with mode: 0644]
.pc/gssapi.patch/monitor.c [new file with mode: 0644]
.pc/gssapi.patch/monitor.h [new file with mode: 0644]
.pc/gssapi.patch/monitor_wrap.c [new file with mode: 0644]
.pc/gssapi.patch/monitor_wrap.h [new file with mode: 0644]
.pc/gssapi.patch/readconf.c [new file with mode: 0644]
.pc/gssapi.patch/readconf.h [new file with mode: 0644]
.pc/gssapi.patch/servconf.c [new file with mode: 0644]
.pc/gssapi.patch/servconf.h [new file with mode: 0644]
.pc/gssapi.patch/ssh-gss.h [new file with mode: 0644]
.pc/gssapi.patch/ssh_config [new file with mode: 0644]
.pc/gssapi.patch/ssh_config.5 [new file with mode: 0644]
.pc/gssapi.patch/sshconnect2.c [new file with mode: 0644]
.pc/gssapi.patch/sshd.c [new file with mode: 0644]
.pc/gssapi.patch/sshd_config [new file with mode: 0644]
.pc/gssapi.patch/sshd_config.5 [new file with mode: 0644]
.pc/helpful-wait-terminate.patch/serverloop.c [new file with mode: 0644]
.pc/keepalive-extensions.patch/readconf.c [new file with mode: 0644]
.pc/keepalive-extensions.patch/ssh_config.5 [new file with mode: 0644]
.pc/keepalive-extensions.patch/sshd_config.5 [new file with mode: 0644]
.pc/lintian-symlink-pickiness.patch/Makefile.in [new file with mode: 0644]
.pc/openbsd-docs.patch/moduli.5 [new file with mode: 0644]
.pc/openbsd-docs.patch/ssh-keygen.1 [new file with mode: 0644]
.pc/openbsd-docs.patch/ssh.1 [new file with mode: 0644]
.pc/openbsd-docs.patch/sshd.8 [new file with mode: 0644]
.pc/openbsd-docs.patch/sshd_config.5 [new file with mode: 0644]
.pc/package-versioning.patch/sshconnect.c [new file with mode: 0644]
.pc/package-versioning.patch/sshd.c [new file with mode: 0644]
.pc/package-versioning.patch/version.h [new file with mode: 0644]
.pc/quieter-signals.patch/clientloop.c [new file with mode: 0644]
.pc/scp-quoting.patch/scp.c [new file with mode: 0644]
.pc/selinux-role.patch/auth.h [new file with mode: 0644]
.pc/selinux-role.patch/auth1.c [new file with mode: 0644]
.pc/selinux-role.patch/auth2.c [new file with mode: 0644]
.pc/selinux-role.patch/monitor.c [new file with mode: 0644]
.pc/selinux-role.patch/monitor.h [new file with mode: 0644]
.pc/selinux-role.patch/monitor_wrap.c [new file with mode: 0644]
.pc/selinux-role.patch/monitor_wrap.h [new file with mode: 0644]
.pc/selinux-role.patch/openbsd-compat/port-linux.c [new file with mode: 0644]
.pc/selinux-role.patch/openbsd-compat/port-linux.h [new file with mode: 0644]
.pc/selinux-role.patch/platform.c [new file with mode: 0644]
.pc/selinux-role.patch/platform.h [new file with mode: 0644]
.pc/selinux-role.patch/session.c [new file with mode: 0644]
.pc/selinux-role.patch/session.h [new file with mode: 0644]
.pc/selinux-role.patch/sshd.c [new file with mode: 0644]
.pc/selinux-role.patch/sshpty.c [new file with mode: 0644]
.pc/selinux-role.patch/sshpty.h [new file with mode: 0644]
.pc/shell-path.patch/sshconnect.c [new file with mode: 0644]
.pc/ssh-argv0.patch/ssh.1 [new file with mode: 0644]
.pc/ssh-vulnkey.patch/Makefile.in [new file with mode: 0644]
.pc/ssh-vulnkey.patch/auth-rh-rsa.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/auth-rsa.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/auth.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/auth.h [new file with mode: 0644]
.pc/ssh-vulnkey.patch/auth2-hostbased.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/auth2-pubkey.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/authfile.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/authfile.h [new file with mode: 0644]
.pc/ssh-vulnkey.patch/pathnames.h [new file with mode: 0644]
.pc/ssh-vulnkey.patch/readconf.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/readconf.h [new file with mode: 0644]
.pc/ssh-vulnkey.patch/servconf.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/servconf.h [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh-add.1 [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh-add.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh-keygen.1 [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh-vulnkey.1 [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh-vulnkey.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh.1 [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/ssh_config.5 [new file with mode: 0644]
.pc/ssh-vulnkey.patch/sshconnect2.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/sshd.8 [new file with mode: 0644]
.pc/ssh-vulnkey.patch/sshd.c [new file with mode: 0644]
.pc/ssh-vulnkey.patch/sshd_config.5 [new file with mode: 0644]
.pc/ssh1-keepalive.patch/clientloop.c [new file with mode: 0644]
.pc/ssh1-keepalive.patch/ssh_config.5 [new file with mode: 0644]
.pc/syslog-level-silent.patch/log.c [new file with mode: 0644]
.pc/syslog-level-silent.patch/ssh.c [new file with mode: 0644]
.pc/user-group-modes.patch/auth-rhosts.c [new file with mode: 0644]
.pc/user-group-modes.patch/auth.c [new file with mode: 0644]
.pc/user-group-modes.patch/misc.c [new file with mode: 0644]
.pc/user-group-modes.patch/misc.h [new file with mode: 0644]
.pc/user-group-modes.patch/readconf.c [new file with mode: 0644]
.pc/user-group-modes.patch/ssh.1 [new file with mode: 0644]
.pc/user-group-modes.patch/ssh_config.5 [new file with mode: 0644]
ChangeLog.gssapi [new file with mode: 0644]
Makefile.in
auth-krb5.c
auth-options.c
auth-options.h
auth-rh-rsa.c
auth-rhosts.c
auth-rsa.c
auth.c
auth.h
auth1.c
auth2-gss.c
auth2-hostbased.c
auth2-pubkey.c
auth2.c
authfile.c
authfile.h
clientloop.c
config.h.in
configure
configure.ac
contrib/gnome-ssh-askpass2.c
debian/NEWS [new file with mode: 0644]
debian/README.Debian [new file with mode: 0644]
debian/README.compromised-keys [new file with mode: 0644]
debian/README.source [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/clean [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/copyright.head [new file with mode: 0644]
debian/faq.html [new file with mode: 0644]
debian/gnome-ssh-askpass.1 [new file with mode: 0644]
debian/openssh-client-udeb.dirs [new file with mode: 0644]
debian/openssh-client-udeb.install [new file with mode: 0644]
debian/openssh-client.config [new file with mode: 0644]
debian/openssh-client.dirs [new file with mode: 0644]
debian/openssh-client.docs [new file with mode: 0644]
debian/openssh-client.install [new file with mode: 0644]
debian/openssh-client.lintian-overrides [new file with mode: 0644]
debian/openssh-client.manpages [new file with mode: 0644]
debian/openssh-client.postinst [new file with mode: 0644]
debian/openssh-client.postrm [new file with mode: 0644]
debian/openssh-client.preinst [new file with mode: 0644]
debian/openssh-client.prerm [new file with mode: 0644]
debian/openssh-server-udeb.dirs [new file with mode: 0644]
debian/openssh-server-udeb.install [new file with mode: 0644]
debian/openssh-server.config [new file with mode: 0644]
debian/openssh-server.dirs [new file with mode: 0644]
debian/openssh-server.examples [new file with mode: 0644]
debian/openssh-server.if-up [new file with mode: 0644]
debian/openssh-server.install [new file with mode: 0644]
debian/openssh-server.links [new file with mode: 0644]
debian/openssh-server.lintian-overrides [new file with mode: 0644]
debian/openssh-server.postinst [new file with mode: 0644]
debian/openssh-server.postrm [new file with mode: 0644]
debian/openssh-server.preinst [new file with mode: 0644]
debian/openssh-server.prerm [new file with mode: 0644]
debian/openssh-server.ssh.default [new file with mode: 0644]
debian/openssh-server.ssh.init [new file with mode: 0644]
debian/openssh-server.sshd.pam [new file with mode: 0644]
debian/openssh-server.templates [new file with mode: 0644]
debian/openssh-server.ufw.profile [new file with mode: 0644]
debian/patches/auth-log-verbosity.patch [new file with mode: 0644]
debian/patches/authorized-keys-man-symlink.patch [new file with mode: 0644]
debian/patches/debian-banner.patch [new file with mode: 0644]
debian/patches/debian-config.patch [new file with mode: 0644]
debian/patches/dnssec-sshfp.patch [new file with mode: 0644]
debian/patches/doc-hash-tab-completion.patch [new file with mode: 0644]
debian/patches/gnome-ssh-askpass2-icon.patch [new file with mode: 0644]
debian/patches/gssapi.patch [new file with mode: 0644]
debian/patches/helpful-wait-terminate.patch [new file with mode: 0644]
debian/patches/keepalive-extensions.patch [new file with mode: 0644]
debian/patches/lintian-symlink-pickiness.patch [new file with mode: 0644]
debian/patches/openbsd-docs.patch [new file with mode: 0644]
debian/patches/package-versioning.patch [new file with mode: 0644]
debian/patches/quieter-signals.patch [new file with mode: 0644]
debian/patches/scp-quoting.patch [new file with mode: 0644]
debian/patches/selinux-role.patch [new file with mode: 0644]
debian/patches/series [new file with mode: 0644]
debian/patches/shell-path.patch [new file with mode: 0644]
debian/patches/ssh-argv0.patch [new file with mode: 0644]
debian/patches/ssh-vulnkey.patch [new file with mode: 0644]
debian/patches/ssh1-keepalive.patch [new file with mode: 0644]
debian/patches/syslog-level-silent.patch [new file with mode: 0644]
debian/patches/user-group-modes.patch [new file with mode: 0644]
debian/po/POTFILES.in [new file with mode: 0644]
debian/po/bg.po [new file with mode: 0644]
debian/po/ca.po [new file with mode: 0644]
debian/po/cs.po [new file with mode: 0644]
debian/po/da.po [new file with mode: 0644]
debian/po/de.po [new file with mode: 0644]
debian/po/el.po [new file with mode: 0644]
debian/po/es.po [new file with mode: 0644]
debian/po/eu.po [new file with mode: 0644]
debian/po/fi.po [new file with mode: 0644]
debian/po/fr.po [new file with mode: 0644]
debian/po/gl.po [new file with mode: 0644]
debian/po/it.po [new file with mode: 0644]
debian/po/ja.po [new file with mode: 0644]
debian/po/ko.po [new file with mode: 0644]
debian/po/nb.po [new file with mode: 0644]
debian/po/nl.po [new file with mode: 0644]
debian/po/pl.po [new file with mode: 0644]
debian/po/pt.po [new file with mode: 0644]
debian/po/pt_BR.po [new file with mode: 0644]
debian/po/ro.po [new file with mode: 0644]
debian/po/ru.po [new file with mode: 0644]
debian/po/sk.po [new file with mode: 0644]
debian/po/sv.po [new file with mode: 0644]
debian/po/ta.po [new file with mode: 0644]
debian/po/templates.pot [new file with mode: 0644]
debian/po/tr.po [new file with mode: 0644]
debian/po/uk.po [new file with mode: 0644]
debian/po/vi.po [new file with mode: 0644]
debian/po/zh_CN.po [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/source/format [new file with mode: 0644]
debian/source/include-binaries [new file with mode: 0644]
debian/ssh-argv0 [new file with mode: 0644]
debian/ssh-argv0.1 [new file with mode: 0644]
debian/ssh-askpass-gnome.copyright [new file with mode: 0644]
debian/ssh-askpass-gnome.desktop [new file with mode: 0644]
debian/ssh-askpass-gnome.dirs [new file with mode: 0644]
debian/ssh-askpass-gnome.examples [new file with mode: 0644]
debian/ssh-askpass-gnome.install [new file with mode: 0644]
debian/ssh-askpass-gnome.manpages [new file with mode: 0644]
debian/ssh-askpass-gnome.png [new file with mode: 0644]
debian/ssh-askpass-gnome.postinst [new file with mode: 0644]
debian/ssh-askpass-gnome.prerm [new file with mode: 0644]
debian/ssh-krb5.NEWS [new file with mode: 0644]
debian/ssh-krb5.postinst [new file with mode: 0644]
debian/ssh.dirs [new file with mode: 0644]
debian/ssh.lintian-overrides [new file with mode: 0644]
debian/ssh.postinst [new file with mode: 0644]
debian/ssh.prerm [new file with mode: 0644]
debian/substitute-conffile.pl [new file with mode: 0644]
debian/tests/Makefile [new file with mode: 0644]
debian/tests/getpid.c [new file with mode: 0644]
debian/tests/keygen-test [new file with mode: 0755]
debian/watch [new file with mode: 0644]
dns.c
gss-genr.c
gss-serv-krb5.c
gss-serv.c
kex.c
kex.h
kexgssc.c [new file with mode: 0644]
kexgsss.c [new file with mode: 0644]
key.c
key.h
log.c
misc.c
misc.h
moduli.5
monitor.c
monitor.h
monitor_wrap.c
monitor_wrap.h
openbsd-compat/getrrsetbyname.c
openbsd-compat/getrrsetbyname.h
openbsd-compat/port-linux.c
openbsd-compat/port-linux.h
pathnames.h
platform.c
platform.h
readconf.c
readconf.h
scp.c
servconf.c
servconf.h
serverloop.c
session.c
session.h
ssh-add.1
ssh-add.c
ssh-gss.h
ssh-keygen.1
ssh-vulnkey.1 [new file with mode: 0644]
ssh-vulnkey.c [new file with mode: 0644]
ssh.1
ssh.c
ssh_config
ssh_config.5
sshconnect.c
sshconnect2.c
sshd.8
sshd.c
sshd_config
sshd_config.5
sshpty.c
sshpty.h
version.h

diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644 (file)
index 0000000..6857a8d
--- /dev/null
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644 (file)
index 0000000..c206706
--- /dev/null
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644 (file)
index 0000000..0cfbf08
--- /dev/null
@@ -0,0 +1 @@
+2
diff --git a/.pc/applied-patches b/.pc/applied-patches
new file mode 100644 (file)
index 0000000..77b03a8
--- /dev/null
@@ -0,0 +1,22 @@
+gssapi.patch
+selinux-role.patch
+ssh-vulnkey.patch
+ssh1-keepalive.patch
+keepalive-extensions.patch
+syslog-level-silent.patch
+quieter-signals.patch
+helpful-wait-terminate.patch
+user-group-modes.patch
+scp-quoting.patch
+shell-path.patch
+dnssec-sshfp.patch
+package-versioning.patch
+debian-banner.patch
+authorized-keys-man-symlink.patch
+lintian-symlink-pickiness.patch
+openbsd-docs.patch
+ssh-argv0.patch
+doc-hash-tab-completion.patch
+auth-log-verbosity.patch
+gnome-ssh-askpass2-icon.patch
+debian-config.patch
diff --git a/.pc/auth-log-verbosity.patch/auth-options.c b/.pc/auth-log-verbosity.patch/auth-options.c
new file mode 100644 (file)
index 0000000..eae45cf
--- /dev/null
@@ -0,0 +1,649 @@
+/* $OpenBSD: auth-options.c,v 1.54 2010/12/24 21:41:48 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".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <netdb.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "match.h"
+#include "log.h"
+#include "canohost.h"
+#include "buffer.h"
+#include "channels.h"
+#include "servconf.h"
+#include "misc.h"
+#include "key.h"
+#include "auth-options.h"
+#include "hostfile.h"
+#include "auth.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+
+/* Flags set authorized_keys flags */
+int no_port_forwarding_flag = 0;
+int no_agent_forwarding_flag = 0;
+int no_x11_forwarding_flag = 0;
+int no_pty_flag = 0;
+int no_user_rc = 0;
+int key_is_cert_authority = 0;
+
+/* "command=" option. */
+char *forced_command = NULL;
+
+/* "environment=" options. */
+struct envstring *custom_environment = NULL;
+
+/* "tunnel=" option. */
+int forced_tun_device = -1;
+
+/* "principals=" option. */
+char *authorized_principals = NULL;
+
+extern ServerOptions options;
+
+void
+auth_clear_options(void)
+{
+       no_agent_forwarding_flag = 0;
+       no_port_forwarding_flag = 0;
+       no_pty_flag = 0;
+       no_x11_forwarding_flag = 0;
+       no_user_rc = 0;
+       key_is_cert_authority = 0;
+       while (custom_environment) {
+               struct envstring *ce = custom_environment;
+               custom_environment = ce->next;
+               xfree(ce->s);
+               xfree(ce);
+       }
+       if (forced_command) {
+               xfree(forced_command);
+               forced_command = NULL;
+       }
+       if (authorized_principals) {
+               xfree(authorized_principals);
+               authorized_principals = NULL;
+       }
+       forced_tun_device = -1;
+       channel_clear_permitted_opens();
+}
+
+/*
+ * return 1 if access is granted, 0 if not.
+ * side effect: sets key option flags
+ */
+int
+auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
+{
+       const char *cp;
+       int i;
+
+       /* reset options */
+       auth_clear_options();
+
+       if (!opts)
+               return 1;
+
+       while (*opts && *opts != ' ' && *opts != '\t') {
+               cp = "cert-authority";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       key_is_cert_authority = 1;
+                       opts += strlen(cp);
+                       goto next_option;
+               }
+               cp = "no-port-forwarding";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       auth_debug_add("Port forwarding disabled.");
+                       no_port_forwarding_flag = 1;
+                       opts += strlen(cp);
+                       goto next_option;
+               }
+               cp = "no-agent-forwarding";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       auth_debug_add("Agent forwarding disabled.");
+                       no_agent_forwarding_flag = 1;
+                       opts += strlen(cp);
+                       goto next_option;
+               }
+               cp = "no-X11-forwarding";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       auth_debug_add("X11 forwarding disabled.");
+                       no_x11_forwarding_flag = 1;
+                       opts += strlen(cp);
+                       goto next_option;
+               }
+               cp = "no-pty";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       auth_debug_add("Pty allocation disabled.");
+                       no_pty_flag = 1;
+                       opts += strlen(cp);
+                       goto next_option;
+               }
+               cp = "no-user-rc";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       auth_debug_add("User rc file execution disabled.");
+                       no_user_rc = 1;
+                       opts += strlen(cp);
+                       goto next_option;
+               }
+               cp = "command=\"";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       opts += strlen(cp);
+                       if (forced_command != NULL)
+                               xfree(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);
+                               xfree(forced_command);
+                               forced_command = NULL;
+                               goto bad_option;
+                       }
+                       forced_command[i] = '\0';
+                       auth_debug_add("Forced command.");
+                       opts++;
+                       goto next_option;
+               }
+               cp = "principals=\"";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       opts += strlen(cp);
+                       if (authorized_principals != NULL)
+                               xfree(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);
+                               xfree(authorized_principals);
+                               authorized_principals = NULL;
+                               goto bad_option;
+                       }
+                       authorized_principals[i] = '\0';
+                       auth_debug_add("principals: %.900s",
+                           authorized_principals);
+                       opts++;
+                       goto next_option;
+               }
+               cp = "environment=\"";
+               if (options.permit_user_env &&
+                   strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       char *s;
+                       struct envstring *new_envstring;
+
+                       opts += strlen(cp);
+                       s = xmalloc(strlen(opts) + 1);
+                       i = 0;
+                       while (*opts) {
+                               if (*opts == '"')
+                                       break;
+                               if (*opts == '\\' && opts[1] == '"') {
+                                       opts += 2;
+                                       s[i++] = '"';
+                                       continue;
+                               }
+                               s[i++] = *opts++;
+                       }
+                       if (!*opts) {
+                               debug("%.100s, line %lu: missing end quote",
+                                   file, linenum);
+                               auth_debug_add("%.100s, line %lu: missing end quote",
+                                   file, linenum);
+                               xfree(s);
+                               goto bad_option;
+                       }
+                       s[i] = '\0';
+                       auth_debug_add("Adding to environment: %.900s", s);
+                       debug("Adding to environment: %.900s", s);
+                       opts++;
+                       new_envstring = xmalloc(sizeof(struct envstring));
+                       new_envstring->s = s;
+                       new_envstring->next = custom_environment;
+                       custom_environment = new_envstring;
+                       goto next_option;
+               }
+               cp = "from=\"";
+               if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+                       const char *remote_ip = get_remote_ipaddr();
+                       const char *remote_host = get_canonical_hostname(
+                           options.use_dns);
+                       char *patterns = xmalloc(strlen(opts) + 1);
+
+                       opts += strlen(cp);
+                       i = 0;
+                       while (*opts) {
+                               if (*opts == '"')
+                                       break;
+                               if (*opts == '\\' && opts[1] == '"') {
+                                       opts += 2;
+                                       patterns[i++] = '"';
+                                       continue;
+                               }
+                               patterns[i++] = *opts++;
+                       }
+                       if (!*opts) {
+                               debug("%.100s, line %lu: missing end quote",
+                                   file, linenum);
+                               auth_debug_add("%.100s, line %lu: missing end quote",
+                                   file, linenum);
+                               xfree(patterns);
+                               goto bad_option;
+                       }
+                       patterns[i] = '\0';
+                       opts++;
+                       switch (match_host_and_ip(remote_host, remote_ip,
+                           patterns)) {
+                       case 1:
+                               xfree(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:
+                               xfree(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);
+                               xfree(patterns);
+                               goto bad_option;
+                       }
+                       patterns[i] = '\0';
+                       opts++;
+                       p = patterns;
+                       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);
+                               xfree(patterns);
+                               goto bad_option;
+                       }
+                       host = cleanhostname(host);
+                       if (p == NULL || (port = a2port(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);
+                               xfree(patterns);
+                               goto bad_option;
+                       }
+                       if (options.allow_tcp_forwarding)
+                               channel_add_permitted_opens(host, port);
+                       xfree(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);
+                               xfree(tun);
+                               forced_tun_device = -1;
+                               goto bad_option;
+                       }
+                       tun[i] = '\0';
+                       forced_tun_device = a2tun(tun, NULL);
+                       xfree(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(u_char *optblob, size_t optblob_len, 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)
+{
+       char *command, *allowed;
+       const char *remote_ip;
+       u_char *name = NULL, *data_blob = NULL;
+       u_int nlen, dlen, clen;
+       Buffer c, data;
+       int ret = -1, found;
+
+       buffer_init(&data);
+
+       /* Make copy to avoid altering original */
+       buffer_init(&c);
+       buffer_append(&c, optblob, optblob_len);
+
+       while (buffer_len(&c) > 0) {
+               if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL ||
+                   (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
+                       error("Certificate options corrupt");
+                       goto out;
+               }
+               buffer_append(&data, data_blob, dlen);
+               debug3("found certificate option \"%.100s\" len %u",
+                   name, dlen);
+               if (strlen(name) != nlen) {
+                       error("Certificate constraint name contains \\0");
+                       goto out;
+               }
+               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 ((command = buffer_get_cstring_ret(&data,
+                                   &clen)) == NULL) {
+                                       error("Certificate constraint \"%s\" "
+                                           "corrupt", name);
+                                       goto out;
+                               }
+                               if (strlen(command) != clen) {
+                                       error("force-command constraint "
+                                           "contains \\0");
+                                       goto out;
+                               }
+                               if (*cert_forced_command != NULL) {
+                                       error("Certificate has multiple "
+                                           "force-command options");
+                                       xfree(command);
+                                       goto out;
+                               }
+                               *cert_forced_command = command;
+                               found = 1;
+                       }
+                       if (strcmp(name, "source-address") == 0) {
+                               if ((allowed = buffer_get_cstring_ret(&data,
+                                   &clen)) == NULL) {
+                                       error("Certificate constraint "
+                                           "\"%s\" corrupt", name);
+                                       goto out;
+                               }
+                               if (strlen(allowed) != clen) {
+                                       error("source-address constraint "
+                                           "contains \\0");
+                                       goto out;
+                               }
+                               if ((*cert_source_address_done)++) {
+                                       error("Certificate has multiple "
+                                           "source-address options");
+                                       xfree(allowed);
+                                       goto out;
+                               }
+                               remote_ip = get_remote_ipaddr();
+                               switch (addr_match_cidr_list(remote_ip,
+                                   allowed)) {
+                               case 1:
+                                       /* accepted */
+                                       xfree(allowed);
+                                       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);
+                                       xfree(allowed);
+                                       goto out;
+                               case -1:
+                                       error("Certificate source-address "
+                                           "contents invalid");
+                                       xfree(allowed);
+                                       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 (buffer_len(&data) != 0) {
+                       error("Certificate option \"%s\" corrupt "
+                           "(extra data)", name);
+                       goto out;
+               }
+               buffer_clear(&data);
+               xfree(name);
+               xfree(data_blob);
+               name = data_blob = NULL;
+       }
+       /* successfully parsed all options */
+       ret = 0;
+
+ out:
+       if (ret != 0 &&
+           cert_forced_command != NULL &&
+           *cert_forced_command != NULL) {
+               xfree(*cert_forced_command);
+               *cert_forced_command = NULL;
+       }
+       if (name != NULL)
+               xfree(name);
+       if (data_blob != NULL)
+               xfree(data_blob);
+       buffer_free(&data);
+       buffer_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(Key *k, struct passwd *pw)
+{
+       int cert_no_port_forwarding_flag = 1;
+       int cert_no_agent_forwarding_flag = 1;
+       int cert_no_x11_forwarding_flag = 1;
+       int cert_no_pty_flag = 1;
+       int cert_no_user_rc = 1;
+       char *cert_forced_command = NULL;
+       int cert_source_address_done = 0;
+
+       if (key_cert_is_legacy(k)) {
+               /* All options are in the one field for v00 certs */
+               if (parse_option_list(buffer_ptr(&k->cert->critical),
+                   buffer_len(&k->cert->critical), pw,
+                   OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
+                   &cert_no_port_forwarding_flag,
+                   &cert_no_agent_forwarding_flag,
+                   &cert_no_x11_forwarding_flag,
+                   &cert_no_pty_flag,
+                   &cert_no_user_rc,
+                   &cert_forced_command,
+                   &cert_source_address_done) == -1)
+                       return -1;
+       } else {
+               /* Separate options and extensions for v01 certs */
+               if (parse_option_list(buffer_ptr(&k->cert->critical),
+                   buffer_len(&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(buffer_ptr(&k->cert->extensions),
+                   buffer_len(&k->cert->extensions), pw,
+                   OPTIONS_EXTENSIONS, 1,
+                   &cert_no_port_forwarding_flag,
+                   &cert_no_agent_forwarding_flag,
+                   &cert_no_x11_forwarding_flag,
+                   &cert_no_pty_flag,
+                   &cert_no_user_rc,
+                   NULL, NULL) == -1)
+                       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;
+       /* CA-specified forced command supersedes key option */
+       if (cert_forced_command != NULL) {
+               if (forced_command != NULL)
+                       xfree(forced_command);
+               forced_command = cert_forced_command;
+       }
+       return 0;
+}
+
diff --git a/.pc/auth-log-verbosity.patch/auth-options.h b/.pc/auth-log-verbosity.patch/auth-options.h
new file mode 100644 (file)
index 0000000..7455c94
--- /dev/null
@@ -0,0 +1,40 @@
+/* $OpenBSD: auth-options.h,v 1.20 2010/05/07 11:30:29 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".
+ */
+
+#ifndef AUTH_OPTIONS_H
+#define AUTH_OPTIONS_H
+
+/* 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 *, char *, u_long);
+void   auth_clear_options(void);
+int    auth_cert_options(Key *, struct passwd *);
+
+#endif
diff --git a/.pc/auth-log-verbosity.patch/auth-rsa.c b/.pc/auth-log-verbosity.patch/auth-rsa.c
new file mode 100644 (file)
index 0000000..b8327c9
--- /dev/null
@@ -0,0 +1,337 @@
+/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * RSA-based authentication.  This code determines whether to admit a login
+ * based on RSA authentication.  This file also contains functions to check
+ * validity of the host key.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <openssl/rsa.h>
+#include <openssl/md5.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "xmalloc.h"
+#include "rsa.h"
+#include "packet.h"
+#include "ssh1.h"
+#include "uidswap.h"
+#include "match.h"
+#include "buffer.h"
+#include "pathnames.h"
+#include "log.h"
+#include "servconf.h"
+#include "key.h"
+#include "auth-options.h"
+#include "hostfile.h"
+#include "auth.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "ssh.h"
+#include "misc.h"
+
+/* import */
+extern ServerOptions options;
+
+/*
+ * Session identifier that is used to bind key exchange and authentication
+ * responses to a particular session.
+ */
+extern u_char session_id[16];
+
+/*
+ * The .ssh/authorized_keys file contains public keys, one per line, in the
+ * following format:
+ *   options bits e n comment
+ * where bits, e and n are decimal numbers,
+ * and comment is any string of characters up to newline.  The maximum
+ * length of a line is SSH_MAX_PUBKEY_BYTES characters.  See sshd(8) for a
+ * description of the options.
+ */
+
+BIGNUM *
+auth_rsa_generate_challenge(Key *key)
+{
+       BIGNUM *challenge;
+       BN_CTX *ctx;
+
+       if ((challenge = BN_new()) == NULL)
+               fatal("auth_rsa_generate_challenge: BN_new() failed");
+       /* Generate a random challenge. */
+       if (BN_rand(challenge, 256, 0, 0) == 0)
+               fatal("auth_rsa_generate_challenge: BN_rand failed");
+       if ((ctx = BN_CTX_new()) == NULL)
+               fatal("auth_rsa_generate_challenge: BN_CTX_new failed");
+       if (BN_mod(challenge, challenge, key->rsa->n, ctx) == 0)
+               fatal("auth_rsa_generate_challenge: BN_mod failed");
+       BN_CTX_free(ctx);
+
+       return challenge;
+}
+
+int
+auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
+{
+       u_char buf[32], mdbuf[16];
+       MD5_CTX md;
+       int len;
+
+       /* don't allow short keys */
+       if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+               error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
+                   BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
+               return (0);
+       }
+
+       /* The response is MD5 of decrypted challenge plus session id. */
+       len = BN_num_bytes(challenge);
+       if (len <= 0 || len > 32)
+               fatal("auth_rsa_verify_response: bad challenge length %d", len);
+       memset(buf, 0, 32);
+       BN_bn2bin(challenge, buf + 32 - len);
+       MD5_Init(&md);
+       MD5_Update(&md, buf, 32);
+       MD5_Update(&md, session_id, 16);
+       MD5_Final(mdbuf, &md);
+
+       /* Verify that the response is the original challenge. */
+       if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
+               /* Wrong answer. */
+               return (0);
+       }
+       /* Correct answer. */
+       return (1);
+}
+
+/*
+ * Performs the RSA authentication challenge-response dialog with the client,
+ * and returns true (non-zero) if the client gave the correct answer to
+ * our challenge; returns zero if the client gives a wrong answer.
+ */
+
+int
+auth_rsa_challenge_dialog(Key *key)
+{
+       BIGNUM *challenge, *encrypted_challenge;
+       u_char response[16];
+       int i, success;
+
+       if ((encrypted_challenge = BN_new()) == NULL)
+               fatal("auth_rsa_challenge_dialog: BN_new() failed");
+
+       challenge = PRIVSEP(auth_rsa_generate_challenge(key));
+
+       /* Encrypt the challenge with the public key. */
+       rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
+
+       /* Send the encrypted challenge to the client. */
+       packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
+       packet_put_bignum(encrypted_challenge);
+       packet_send();
+       BN_clear_free(encrypted_challenge);
+       packet_write_wait();
+
+       /* Wait for a response. */
+       packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
+       for (i = 0; i < 16; i++)
+               response[i] = (u_char)packet_get_char();
+       packet_check_eom();
+
+       success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
+       BN_clear_free(challenge);
+       return (success);
+}
+
+static int
+rsa_key_allowed_in_file(struct passwd *pw, char *file,
+    const BIGNUM *client_n, Key **rkey)
+{
+       char line[SSH_MAX_PUBKEY_BYTES];
+       int allowed = 0;
+       u_int bits;
+       FILE *f;
+       u_long linenum = 0;
+       Key *key;
+
+       debug("trying public RSA key file %s", file);
+       if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
+               return 0;
+
+       /*
+        * Go though the accepted keys, looking for the current key.  If
+        * found, perform a challenge-response dialog to verify that the
+        * user really has the corresponding private key.
+        */
+       key = key_new(KEY_RSA1);
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               char *cp;
+               char *key_options;
+               int keybits;
+
+               /* Skip leading whitespace, empty and comment lines. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               if (!*cp || *cp == '\n' || *cp == '#')
+                       continue;
+
+               /*
+                * Check if there are options for this key, and if so,
+                * save their starting address and skip the option part
+                * for now.  If there are no options, set the starting
+                * address to NULL.
+                */
+               if (*cp < '0' || *cp > '9') {
+                       int quoted = 0;
+                       key_options = cp;
+                       for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
+                               if (*cp == '\\' && cp[1] == '"')
+                                       cp++;   /* Skip both */
+                               else if (*cp == '"')
+                                       quoted = !quoted;
+                       }
+               } else
+                       key_options = NULL;
+
+               /* Parse the key from the line. */
+               if (hostfile_read_key(&cp, &bits, key) == 0) {
+                       debug("%.100s, line %lu: non ssh1 key syntax",
+                           file, linenum);
+                       continue;
+               }
+               /* cp now points to the comment part. */
+
+               /*
+                * Check if the we have found the desired key (identified
+                * by its modulus).
+                */
+               if (BN_cmp(key->rsa->n, client_n) != 0)
+                       continue;
+
+               /* check the real bits  */
+               keybits = BN_num_bits(key->rsa->n);
+               if (keybits < 0 || bits != (u_int)keybits)
+                       logit("Warning: %s, line %lu: keysize mismatch: "
+                           "actual %d vs. announced %d.",
+                           file, linenum, BN_num_bits(key->rsa->n), bits);
+
+               /* Never accept a revoked key */
+               if (auth_key_is_revoked(key, 0))
+                       break;
+
+               /* We have found the desired key. */
+               /*
+                * If our options do not allow this key to be used,
+                * do not send challenge.
+                */
+               if (!auth_parse_options(pw, key_options, file, linenum))
+                       continue;
+               if (key_is_cert_authority)
+                       continue;
+               /* break out, this key is allowed */
+               allowed = 1;
+               break;
+       }
+
+       /* Close the file. */
+       fclose(f);
+
+       /* return key if allowed */
+       if (allowed && rkey != NULL)
+               *rkey = key;
+       else
+               key_free(key);
+
+       return allowed;
+}
+
+/*
+ * check if there's user key matching client_n,
+ * return key if login is allowed, NULL otherwise
+ */
+
+int
+auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+{
+       char *file;
+       u_int i, allowed = 0;
+
+       temporarily_use_uid(pw);
+
+       for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
+               file = expand_authorized_keys(
+                   options.authorized_keys_files[i], pw);
+               allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
+               xfree(file);
+       }
+
+       restore_uid();
+
+       return allowed;
+}
+
+/*
+ * Performs the RSA authentication dialog with the client.  This returns
+ * 0 if the client could not be authenticated, and 1 if authentication was
+ * successful.  This may exit if there is a serious protocol violation.
+ */
+int
+auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
+{
+       Key *key;
+       char *fp;
+       struct passwd *pw = authctxt->pw;
+
+       /* no user given */
+       if (!authctxt->valid)
+               return 0;
+
+       if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
+               auth_clear_options();
+               return (0);
+       }
+
+       /* Perform the challenge-response dialog for this key. */
+       if (!auth_rsa_challenge_dialog(key)) {
+               /* Wrong response. */
+               verbose("Wrong response to RSA authentication challenge.");
+               packet_send_debug("Wrong response to RSA authentication challenge.");
+               /*
+                * Break out of the loop. Otherwise we might send
+                * another challenge and break the protocol.
+                */
+               key_free(key);
+               return (0);
+       }
+       /*
+        * Correct response.  The client has been successfully
+        * authenticated. Note that we have not yet processed the
+        * options; this will be reset if the options cause the
+        * authentication to be rejected.
+        */
+       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+       verbose("Found matching %s key: %s",
+           key_type(key), fp);
+       xfree(fp);
+       key_free(key);
+
+       packet_send_debug("RSA authentication accepted.");
+       return (1);
+}
diff --git a/.pc/auth-log-verbosity.patch/auth2-pubkey.c b/.pc/auth-log-verbosity.patch/auth2-pubkey.c
new file mode 100644 (file)
index 0000000..fea74aa
--- /dev/null
@@ -0,0 +1,466 @@
+/* $OpenBSD: auth2-pubkey.c,v 1.29 2011/05/23 03:30:07 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "pathnames.h"
+#include "uidswap.h"
+#include "auth-options.h"
+#include "canohost.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "misc.h"
+#include "authfile.h"
+#include "match.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern u_int session_id2_len;
+
+static int
+userauth_pubkey(Authctxt *authctxt)
+{
+       Buffer b;
+       Key *key = NULL;
+       char *pkalg;
+       u_char *pkblob, *sig;
+       u_int alen, blen, slen;
+       int have_sig, pktype;
+       int authenticated = 0;
+
+       if (!authctxt->valid) {
+               debug2("userauth_pubkey: disabled because of invalid user");
+               return 0;
+       }
+       have_sig = packet_get_char();
+       if (datafellows & SSH_BUG_PKAUTH) {
+               debug2("userauth_pubkey: SSH_BUG_PKAUTH");
+               /* no explicit pkalg given */
+               pkblob = packet_get_string(&blen);
+               buffer_init(&b);
+               buffer_append(&b, pkblob, blen);
+               /* so we have to extract the pkalg from the pkblob */
+               pkalg = buffer_get_string(&b, &alen);
+               buffer_free(&b);
+       } else {
+               pkalg = packet_get_string(&alen);
+               pkblob = packet_get_string(&blen);
+       }
+       pktype = key_type_from_name(pkalg);
+       if (pktype == KEY_UNSPEC) {
+               /* this is perfectly legal */
+               logit("userauth_pubkey: unsupported public key algorithm: %s",
+                   pkalg);
+               goto done;
+       }
+       key = key_from_blob(pkblob, blen);
+       if (key == NULL) {
+               error("userauth_pubkey: cannot decode key: %s", pkalg);
+               goto done;
+       }
+       if (key->type != pktype) {
+               error("userauth_pubkey: type mismatch for decoded key "
+                   "(received %d, expected %d)", key->type, pktype);
+               goto done;
+       }
+       if (have_sig) {
+               sig = packet_get_string(&slen);
+               packet_check_eom();
+               buffer_init(&b);
+               if (datafellows & SSH_OLD_SESSIONID) {
+                       buffer_append(&b, session_id2, session_id2_len);
+               } else {
+                       buffer_put_string(&b, session_id2, session_id2_len);
+               }
+               /* reconstruct packet */
+               buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+               buffer_put_cstring(&b, authctxt->user);
+               buffer_put_cstring(&b,
+                   datafellows & SSH_BUG_PKSERVICE ?
+                   "ssh-userauth" :
+                   authctxt->service);
+               if (datafellows & SSH_BUG_PKAUTH) {
+                       buffer_put_char(&b, have_sig);
+               } else {
+                       buffer_put_cstring(&b, "publickey");
+                       buffer_put_char(&b, have_sig);
+                       buffer_put_cstring(&b, pkalg);
+               }
+               buffer_put_string(&b, pkblob, blen);
+#ifdef DEBUG_PK
+               buffer_dump(&b);
+#endif
+               /* test for correct signature */
+               authenticated = 0;
+               if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
+                   PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+                   buffer_len(&b))) == 1)
+                       authenticated = 1;
+               buffer_free(&b);
+               xfree(sig);
+       } else {
+               debug("test whether pkalg/pkblob are acceptable");
+               packet_check_eom();
+
+               /* XXX fake reply and always send PK_OK ? */
+               /*
+                * XXX this allows testing whether a user is allowed
+                * to login: if you happen to have a valid pubkey this
+                * message is sent. the message is NEVER sent at all
+                * if a user is not allowed to login. is this an
+                * issue? -markus
+                */
+               if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
+                       packet_start(SSH2_MSG_USERAUTH_PK_OK);
+                       packet_put_string(pkalg, alen);
+                       packet_put_string(pkblob, blen);
+                       packet_send();
+                       packet_write_wait();
+                       authctxt->postponed = 1;
+               }
+       }
+       if (authenticated != 1)
+               auth_clear_options();
+done:
+       debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
+       if (key != NULL)
+               key_free(key);
+       xfree(pkalg);
+       xfree(pkblob);
+       return authenticated;
+}
+
+static int
+match_principals_option(const char *principal_list, struct KeyCert *cert)
+{
+       char *result;
+       u_int i;
+
+       /* XXX percent_expand() sequences for authorized_principals? */
+
+       for (i = 0; i < cert->nprincipals; i++) {
+               if ((result = match_list(cert->principals[i],
+                   principal_list, NULL)) != NULL) {
+                       debug3("matched principal from key options \"%.100s\"",
+                           result);
+                       xfree(result);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int
+match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
+{
+       FILE *f;
+       char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
+       u_long linenum = 0;
+       u_int i;
+
+       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;
+       }
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               /* Skip leading whitespace. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               /* Skip blank and comment lines. */
+               if ((ep = strchr(cp, '#')) != NULL)
+                       *ep = '\0';
+               if (!*cp || *cp == '\n')
+                       continue;
+               /* Trim trailing whitespace. */
+               ep = cp + strlen(cp) - 1;
+               while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
+                       *ep-- = '\0';
+               /*
+                * If the line has internal whitespace then assume it has
+                * key options.
+                */
+               line_opts = NULL;
+               if ((ep = strrchr(cp, ' ')) != NULL ||
+                   (ep = strrchr(cp, '\t')) != NULL) {
+                       for (; *ep == ' ' || *ep == '\t'; ep++)
+                               ;
+                       line_opts = cp;
+                       cp = ep;
+               }
+               for (i = 0; i < cert->nprincipals; i++) {
+                       if (strcmp(cp, cert->principals[i]) == 0) {
+                               debug3("matched principal from file \"%.100s\"",
+                                   cert->principals[i]);
+                               if (auth_parse_options(pw, line_opts,
+                                   file, linenum) != 1)
+                                       continue;
+                               fclose(f);
+                               restore_uid();
+                               return 1;
+                       }
+               }
+       }
+       fclose(f);
+       restore_uid();
+       return 0;
+}      
+
+/* return 1 if user allows given key */
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
+{
+       char line[SSH_MAX_PUBKEY_BYTES];
+       const char *reason;
+       int found_key = 0;
+       FILE *f;
+       u_long linenum = 0;
+       Key *found;
+       char *fp;
+
+       /* Temporarily use the user's uid. */
+       temporarily_use_uid(pw);
+
+       debug("trying public key file %s", file);
+       f = auth_openkeyfile(file, pw, options.strict_modes);
+
+       if (!f) {
+               restore_uid();
+               return 0;
+       }
+
+       found_key = 0;
+       found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
+
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               char *cp, *key_options = NULL;
+
+               auth_clear_options();
+
+               /* Skip leading whitespace, empty and comment lines. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               if (!*cp || *cp == '\n' || *cp == '#')
+                       continue;
+
+               if (key_read(found, &cp) != 1) {
+                       /* no key?  check if there are options for this key */
+                       int quoted = 0;
+                       debug2("user_key_allowed: check options: '%s'", cp);
+                       key_options = cp;
+                       for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
+                               if (*cp == '\\' && cp[1] == '"')
+                                       cp++;   /* Skip both */
+                               else if (*cp == '"')
+                                       quoted = !quoted;
+                       }
+                       /* Skip remaining whitespace. */
+                       for (; *cp == ' ' || *cp == '\t'; cp++)
+                               ;
+                       if (key_read(found, &cp) != 1) {
+                               debug2("user_key_allowed: advance: '%s'", cp);
+                               /* still no key?  advance to next line*/
+                               continue;
+                       }
+               }
+               if (key_is_cert(key)) {
+                       if (!key_equal(found, key->cert->signature_key))
+                               continue;
+                       if (auth_parse_options(pw, key_options, file,
+                           linenum) != 1)
+                               continue;
+                       if (!key_is_cert_authority)
+                               continue;
+                       fp = key_fingerprint(found, SSH_FP_MD5,
+                           SSH_FP_HEX);
+                       debug("matching CA found: file %s, line %lu, %s %s",
+                           file, linenum, key_type(found), fp);
+                       /*
+                        * If the user has specified a list of principals as
+                        * a key option, then prefer that list to matching
+                        * their username in the certificate principals list.
+                        */
+                       if (authorized_principals != NULL &&
+                           !match_principals_option(authorized_principals,
+                           key->cert)) {
+                               reason = "Certificate does not contain an "
+                                   "authorized principal";
+ fail_reason:
+                               xfree(fp);
+                               error("%s", reason);
+                               auth_debug_add("%s", reason);
+                               continue;
+                       }
+                       if (key_cert_check_authority(key, 0, 0,
+                           authorized_principals == NULL ? pw->pw_name : NULL,
+                           &reason) != 0)
+                               goto fail_reason;
+                       if (auth_cert_options(key, pw) != 0) {
+                               xfree(fp);
+                               continue;
+                       }
+                       verbose("Accepted certificate ID \"%s\" "
+                           "signed by %s CA %s via %s", key->cert->key_id,
+                           key_type(found), fp, file);
+                       xfree(fp);
+                       found_key = 1;
+                       break;
+               } else if (key_equal(found, key)) {
+                       if (auth_parse_options(pw, key_options, file,
+                           linenum) != 1)
+                               continue;
+                       if (key_is_cert_authority)
+                               continue;
+                       found_key = 1;
+                       debug("matching key found: file %s, line %lu",
+                           file, linenum);
+                       fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+                       verbose("Found matching %s key: %s",
+                           key_type(found), fp);
+                       xfree(fp);
+                       break;
+               }
+       }
+       restore_uid();
+       fclose(f);
+       key_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, Key *key)
+{
+       char *ca_fp, *principals_file = NULL;
+       const char *reason;
+       int ret = 0;
+
+       if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
+               return 0;
+
+       ca_fp = key_fingerprint(key->cert->signature_key,
+           SSH_FP_MD5, SSH_FP_HEX);
+
+       if (key_in_file(key->cert->signature_key,
+           options.trusted_user_ca_keys, 1) != 1) {
+               debug2("%s: CA %s %s is not listed in %s", __func__,
+                   key_type(key->cert->signature_key), ca_fp,
+                   options.trusted_user_ca_keys);
+               goto out;
+       }
+       /*
+        * If AuthorizedPrincipals is in use, then compare the certificate
+        * principals against the names in that file rather than matching
+        * against the username.
+        */
+       if ((principals_file = authorized_principals_file(pw)) != NULL) {
+               if (!match_principals_file(principals_file, pw, key->cert)) {
+                       reason = "Certificate does not contain an "
+                           "authorized principal";
+ fail_reason:
+                       error("%s", reason);
+                       auth_debug_add("%s", reason);
+                       goto out;
+               }
+       }
+       if (key_cert_check_authority(key, 0, 1,
+           principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
+               goto fail_reason;
+       if (auth_cert_options(key, pw) != 0)
+               goto out;
+
+       verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
+           key->cert->key_id, key_type(key->cert->signature_key), ca_fp,
+           options.trusted_user_ca_keys);
+       ret = 1;
+
+ out:
+       if (principals_file != NULL)
+               xfree(principals_file);
+       if (ca_fp != NULL)
+               xfree(ca_fp);
+       return ret;
+}
+
+/* check whether given key is in .ssh/authorized_keys* */
+int
+user_key_allowed(struct passwd *pw, Key *key)
+{
+       u_int success, i;
+       char *file;
+
+       if (auth_key_is_revoked(key, 0))
+               return 0;
+       if (key_is_cert(key) &&
+           auth_key_is_revoked(key->cert->signature_key, 0))
+               return 0;
+
+       success = user_cert_trusted_ca(pw, key);
+       if (success)
+               return success;
+
+       for (i = 0; !success && i < options.num_authkeys_files; i++) {
+               file = expand_authorized_keys(
+                   options.authorized_keys_files[i], pw);
+               success = user_key_allowed2(pw, key, file);
+               xfree(file);
+       }
+
+       return success;
+}
+
+Authmethod method_pubkey = {
+       "publickey",
+       userauth_pubkey,
+       &options.pubkey_authentication
+};
diff --git a/.pc/authorized-keys-man-symlink.patch/Makefile.in b/.pc/authorized-keys-man-symlink.patch/Makefile.in
new file mode 100644 (file)
index 0000000..f3c3a8e
--- /dev/null
@@ -0,0 +1,452 @@
+# $Id: Makefile.in,v 1.325 2011/08/05 20:15:18 djm Exp $
+
+# uncomment if you run a non bourne compatable shell. Ie. csh
+#SHELL = @SH@
+
+AUTORECONF=autoreconf
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+sbindir=@sbindir@
+libexecdir=@libexecdir@
+datadir=@datadir@
+datarootdir=@datarootdir@
+mandir=@mandir@
+mansubdir=@mansubdir@
+sysconfdir=@sysconfdir@
+piddir=@piddir@
+srcdir=@srcdir@
+top_srcdir=@top_srcdir@
+
+DESTDIR=
+VPATH=@srcdir@
+SSH_PROGRAM=@bindir@/ssh
+ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
+SFTP_SERVER=$(libexecdir)/sftp-server
+SSH_KEYSIGN=$(libexecdir)/ssh-keysign
+SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
+SSH_DATADIR=$(datadir)/ssh
+PRIVSEP_PATH=@PRIVSEP_PATH@
+SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
+STRIP_OPT=@STRIP_OPT@
+
+PATHS= -DSSHDIR=\"$(sysconfdir)\" \
+       -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
+       -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
+       -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
+       -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
+       -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
+       -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
+       -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
+       -D_PATH_SSH_DATADIR=\"$(SSH_DATADIR)\" \
+
+CC=@CC@
+LD=@LD@
+CFLAGS=@CFLAGS@
+CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+LIBS=@LIBS@
+SSHLIBS=@SSHLIBS@
+SSHDLIBS=@SSHDLIBS@
+LIBEDIT=@LIBEDIT@
+AR=@AR@
+AWK=@AWK@
+RANLIB=@RANLIB@
+INSTALL=@INSTALL@
+PERL=@PERL@
+SED=@SED@
+ENT=@ENT@
+XAUTH_PATH=@XAUTH_PATH@
+LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
+EXEEXT=@EXEEXT@
+MANFMT=@MANFMT@
+
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-vulnkey$(EXEEXT)
+
+LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
+       canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
+       cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
+       compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
+       log.o match.o md-sha256.o moduli.o nchan.o packet.o \
+       readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
+       atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
+       monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
+       kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
+       kexgssc.o \
+       msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
+       schnorr.o ssh-pkcs11.o
+
+SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
+       sshconnect.o sshconnect1.o sshconnect2.o mux.o \
+       roaming_common.o roaming_client.o
+
+SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
+       audit.o audit-bsm.o audit-linux.o platform.o \
+       sshpty.o sshlogin.o servconf.o serverloop.o \
+       auth.o auth1.o auth2.o auth-options.o session.o \
+       auth-chall.o auth2-chall.o groupaccess.o \
+       auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
+       auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
+       monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
+       auth-krb5.o \
+       auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
+       loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
+       sftp-server.o sftp-common.o \
+       roaming_common.o roaming_serv.o \
+       sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
+
+MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-vulnkey.1.out sshd_config.5.out ssh_config.5.out
+MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-vulnkey.1 sshd_config.5 ssh_config.5
+MANTYPE                = @MANTYPE@
+
+CONFIGFILES=sshd_config.out ssh_config.out moduli.out
+CONFIGFILES_IN=sshd_config ssh_config moduli
+
+PATHSUBS       = \
+       -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
+       -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
+       -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \
+       -e 's|/usr/libexec|$(libexecdir)|g' \
+       -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \
+       -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \
+       -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
+       -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
+       -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \
+       -e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \
+       -e 's|/var/empty|$(PRIVSEP_PATH)|g' \
+       -e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g'
+
+FIXPATHSCMD    = $(SED) $(PATHSUBS)
+
+all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+
+$(LIBSSH_OBJS): Makefile.in config.h
+$(SSHOBJS): Makefile.in config.h
+$(SSHDOBJS): Makefile.in config.h
+
+.c.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
+$(LIBCOMPAT): always
+       (cd openbsd-compat && $(MAKE))
+always:
+
+libssh.a: $(LIBSSH_OBJS)
+       $(AR) rv $@ $(LIBSSH_OBJS)
+       $(RANLIB) $@
+
+ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
+       $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
+
+sshd$(EXEEXT): libssh.a        $(LIBCOMPAT) $(SSHDOBJS)
+       $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
+
+scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
+       $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
+       $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
+       $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
+       $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o
+       $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
+       $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
+       $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
+       $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
+       $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
+
+ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o
+       $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+# test driver for the loginrec code - not built by default
+logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
+       $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
+
+$(MANPAGES): $(MANPAGES_IN)
+       if test "$(MANTYPE)" = "cat"; then \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \
+       else \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \
+       fi; \
+       if test "$(MANTYPE)" = "man"; then \
+               $(FIXPATHSCMD) $${manpage} | $(AWK) -f $(srcdir)/mdoc2man.awk > $@; \
+       else \
+               $(FIXPATHSCMD) $${manpage} > $@; \
+       fi
+
+$(CONFIGFILES): $(CONFIGFILES_IN)
+       conffile=`echo $@ | sed 's/.out$$//'`; \
+       $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@
+
+# fake rule to stop make trying to compile moduli.o into a binary "moduli.o"
+moduli:
+       echo
+
+clean: regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core survey
+       (cd openbsd-compat && $(MAKE) clean)
+
+distclean:     regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core opensshd.init openssh.xml
+       rm -f Makefile buildpkg.sh config.h config.status
+       rm -f survey.sh openbsd-compat/regress/Makefile *~ 
+       rm -rf autom4te.cache
+       (cd openbsd-compat && $(MAKE) distclean)
+       if test -d pkg ; then \
+               rm -fr pkg ; \
+       fi
+
+veryclean: distclean
+       rm -f configure config.h.in *.0
+
+cleandir: veryclean
+
+mrproper: veryclean
+
+realclean: veryclean
+
+catman-do:
+       @for f in $(MANPAGES_IN) ; do \
+               base=`echo $$f | sed 's/\..*$$//'` ; \
+               echo "$$f -> $$base.0" ; \
+               $(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \
+                       >$$base.0 ; \
+       done
+
+distprep: catman-do
+       $(AUTORECONF)
+       -rm -rf autom4te.cache
+
+install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
+install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf
+install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files
+
+check-config:
+       -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
+
+install-files:
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)5
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir)
+       (umask 022 ; $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH))
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey$(EXEEXT) $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
+       $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       $(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       $(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5
+       $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
+       $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
+       $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+       ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+install-sysconf:
+       if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
+               $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \
+               $(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \
+               $(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \
+               if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \
+                       echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \
+                       mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \
+               else \
+                       $(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \
+               fi ; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \
+       fi
+
+host-key: ssh-keygen$(EXEEXT)
+       @if [ -z "$(DESTDIR)" ] ; then \
+               if [ -f "$(sysconfdir)/ssh_host_key" ] ; then \
+                       echo "$(sysconfdir)/ssh_host_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa1 -f $(sysconfdir)/ssh_host_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_dsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t dsa -f $(sysconfdir)/ssh_host_dsa_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_rsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa -f $(sysconfdir)/ssh_host_rsa_key -N "" ; \
+               fi ; \
+               if [ -z "@COMMENT_OUT_ECC@" ] ; then \
+                   if [ -f $(sysconfdir)/ssh_host_ecdsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_ecdsa_key already exists, skipping." ; \
+                   else \
+                       ./ssh-keygen -t ecdsa -f $(sysconfdir)/ssh_host_ecdsa_key -N "" ; \
+                   fi ; \
+               fi ; \
+       fi ;
+
+host-key-force: ssh-keygen$(EXEEXT)
+       ./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
+       ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
+       ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
+       test -z "@COMMENT_OUT_ECC@" && ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""
+
+uninstallall:  uninstall
+       -rm -f $(DESTDIR)$(sysconfdir)/ssh_config
+       -rm -f $(DESTDIR)$(sysconfdir)/sshd_config
+       -rmdir $(DESTDIR)$(sysconfdir)
+       -rmdir $(DESTDIR)$(bindir)
+       -rmdir $(DESTDIR)$(sbindir)
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)1
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)8
+       -rmdir $(DESTDIR)$(mandir)
+       -rmdir $(DESTDIR)$(libexecdir)
+
+uninstall:
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+tests interop-tests:   $(TARGETS)
+       BUILDDIR=`pwd`; \
+       [ -d `pwd`/regress ]  ||  mkdir -p `pwd`/regress; \
+       [ -f `pwd`/regress/Makefile ]  || \
+           ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile ; \
+       TEST_SHELL="@TEST_SHELL@"; \
+       TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
+       TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
+       TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
+       TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
+       TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
+       TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
+       TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
+       TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
+       TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
+       TEST_SSH_PLINK="plink"; \
+       TEST_SSH_PUTTYGEN="puttygen"; \
+       TEST_SSH_CONCH="conch"; \
+       TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
+       TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
+       TEST_SSH_SHA256="@TEST_SSH_SHA256@" ; \
+       cd $(srcdir)/regress || exit $$?; \
+       $(MAKE) \
+               .OBJDIR="$${BUILDDIR}/regress" \
+               .CURDIR="`pwd`" \
+               BUILDDIR="$${BUILDDIR}" \
+               OBJ="$${BUILDDIR}/regress/" \
+               PATH="$${BUILDDIR}:$${PATH}" \
+               TEST_SHELL="$${TEST_SHELL}" \
+               TEST_SSH_SSH="$${TEST_SSH_SSH}" \
+               TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
+               TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
+               TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
+               TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
+               TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
+               TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
+               TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
+               TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
+               TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
+               TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
+               TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
+               TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
+               TEST_SSH_ECC="$${TEST_SSH_ECC}" \
+               TEST_SSH_SHA256="$${TEST_SSH_SHA256}" \
+               EXEEXT="$(EXEEXT)" \
+               $@ && echo all tests passed
+
+compat-tests: $(LIBCOMPAT)
+       (cd openbsd-compat/regress && $(MAKE))
+
+regressclean:
+       if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \
+               (cd regress && $(MAKE) clean) \
+       fi
+
+survey: survey.sh ssh
+       @$(SHELL) ./survey.sh > survey
+       @echo 'The survey results have been placed in the file "survey" in the'
+       @echo 'current directory.  Please review the file then send with'
+       @echo '"make send-survey".'
+
+send-survey:   survey
+       mail portable-survey@mindrot.org <survey
+
+package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+       if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
+               sh buildpkg.sh; \
+       fi
+
diff --git a/.pc/debian-banner.patch/servconf.c b/.pc/debian-banner.patch/servconf.c
new file mode 100644 (file)
index 0000000..3d15c2e
--- /dev/null
@@ -0,0 +1,1843 @@
+/* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */
+/*
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "compat.h"
+#include "pathnames.h"
+#include "misc.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "mac.h"
+#include "match.h"
+#include "channels.h"
+#include "groupaccess.h"
+
+static void add_listen_addr(ServerOptions *, char *, int);
+static void add_one_listen_addr(ServerOptions *, char *, int);
+
+/* Use of privilege separation or not */
+extern int use_privsep;
+extern Buffer cfg;
+
+/* Initializes the server options to their default values. */
+
+void
+initialize_server_options(ServerOptions *options)
+{
+       memset(options, 0, sizeof(*options));
+
+       /* Portable-specific options */
+       options->use_pam = -1;
+
+       /* Standard Options */
+       options->num_ports = 0;
+       options->ports_from_cmdline = 0;
+       options->listen_addrs = NULL;
+       options->address_family = -1;
+       options->num_host_key_files = 0;
+       options->num_host_cert_files = 0;
+       options->pid_file = NULL;
+       options->server_key_bits = -1;
+       options->login_grace_time = -1;
+       options->key_regeneration_time = -1;
+       options->permit_root_login = PERMIT_NOT_SET;
+       options->ignore_rhosts = -1;
+       options->ignore_user_known_hosts = -1;
+       options->print_motd = -1;
+       options->print_lastlog = -1;
+       options->x11_forwarding = -1;
+       options->x11_display_offset = -1;
+       options->x11_use_localhost = -1;
+       options->xauth_location = NULL;
+       options->strict_modes = -1;
+       options->tcp_keep_alive = -1;
+       options->log_facility = SYSLOG_FACILITY_NOT_SET;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->hostbased_uses_name_from_packet_only = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->kerberos_authentication = -1;
+       options->kerberos_or_local_passwd = -1;
+       options->kerberos_ticket_cleanup = -1;
+       options->kerberos_get_afs_token = -1;
+       options->gss_authentication=-1;
+       options->gss_keyex = -1;
+       options->gss_cleanup_creds = -1;
+       options->gss_strict_acceptor = -1;
+       options->gss_store_rekey = -1;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->permit_blacklisted_keys = -1;
+       options->permit_empty_passwd = -1;
+       options->permit_user_env = -1;
+       options->use_login = -1;
+       options->compression = -1;
+       options->allow_tcp_forwarding = -1;
+       options->allow_agent_forwarding = -1;
+       options->num_allow_users = 0;
+       options->num_deny_users = 0;
+       options->num_allow_groups = 0;
+       options->num_deny_groups = 0;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->gateway_ports = -1;
+       options->num_subsystems = 0;
+       options->max_startups_begin = -1;
+       options->max_startups_rate = -1;
+       options->max_startups = -1;
+       options->max_authtries = -1;
+       options->max_sessions = -1;
+       options->banner = NULL;
+       options->use_dns = -1;
+       options->client_alive_interval = -1;
+       options->client_alive_count_max = -1;
+       options->num_authkeys_files = 0;
+       options->num_accept_env = 0;
+       options->permit_tun = -1;
+       options->num_permitted_opens = -1;
+       options->adm_forced_command = NULL;
+       options->chroot_directory = NULL;
+       options->zero_knowledge_password_authentication = -1;
+       options->revoked_keys_file = NULL;
+       options->trusted_user_ca_keys = NULL;
+       options->authorized_principals_file = NULL;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+}
+
+void
+fill_default_server_options(ServerOptions *options)
+{
+       /* Portable-specific options */
+       if (options->use_pam == -1)
+               options->use_pam = 0;
+
+       /* Standard Options */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_host_key_files == 0) {
+               /* fill default hostkeys for protocols */
+               if (options->protocol & SSH_PROTO_1)
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_KEY_FILE;
+               if (options->protocol & SSH_PROTO_2) {
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_RSA_KEY_FILE;
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_DSA_KEY_FILE;
+#ifdef OPENSSL_HAS_ECC
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_ECDSA_KEY_FILE;
+#endif
+               }
+       }
+       /* No certificates by default */
+       if (options->num_ports == 0)
+               options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+       if (options->listen_addrs == NULL)
+               add_listen_addr(options, NULL, 0);
+       if (options->pid_file == NULL)
+               options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
+       if (options->server_key_bits == -1)
+               options->server_key_bits = 1024;
+       if (options->login_grace_time == -1)
+               options->login_grace_time = 120;
+       if (options->key_regeneration_time == -1)
+               options->key_regeneration_time = 3600;
+       if (options->permit_root_login == PERMIT_NOT_SET)
+               options->permit_root_login = PERMIT_YES;
+       if (options->ignore_rhosts == -1)
+               options->ignore_rhosts = 1;
+       if (options->ignore_user_known_hosts == -1)
+               options->ignore_user_known_hosts = 0;
+       if (options->print_motd == -1)
+               options->print_motd = 1;
+       if (options->print_lastlog == -1)
+               options->print_lastlog = 1;
+       if (options->x11_forwarding == -1)
+               options->x11_forwarding = 0;
+       if (options->x11_display_offset == -1)
+               options->x11_display_offset = 10;
+       if (options->x11_use_localhost == -1)
+               options->x11_use_localhost = 1;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->strict_modes == -1)
+               options->strict_modes = 1;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
+               options->log_facility = SYSLOG_FACILITY_AUTH;
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->hostbased_uses_name_from_packet_only == -1)
+               options->hostbased_uses_name_from_packet_only = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->kerberos_authentication == -1)
+               options->kerberos_authentication = 0;
+       if (options->kerberos_or_local_passwd == -1)
+               options->kerberos_or_local_passwd = 1;
+       if (options->kerberos_ticket_cleanup == -1)
+               options->kerberos_ticket_cleanup = 1;
+       if (options->kerberos_get_afs_token == -1)
+               options->kerberos_get_afs_token = 0;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
+       if (options->gss_cleanup_creds == -1)
+               options->gss_cleanup_creds = 1;
+       if (options->gss_strict_acceptor == -1)
+               options->gss_strict_acceptor = 1;
+       if (options->gss_store_rekey == -1)
+               options->gss_store_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 0;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->permit_blacklisted_keys == -1)
+               options->permit_blacklisted_keys = 0;
+       if (options->permit_empty_passwd == -1)
+               options->permit_empty_passwd = 0;
+       if (options->permit_user_env == -1)
+               options->permit_user_env = 0;
+       if (options->use_login == -1)
+               options->use_login = 0;
+       if (options->compression == -1)
+               options->compression = COMP_DELAYED;
+       if (options->allow_tcp_forwarding == -1)
+               options->allow_tcp_forwarding = 1;
+       if (options->allow_agent_forwarding == -1)
+               options->allow_agent_forwarding = 1;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->max_startups == -1)
+               options->max_startups = 10;
+       if (options->max_startups_rate == -1)
+               options->max_startups_rate = 100;               /* 100% */
+       if (options->max_startups_begin == -1)
+               options->max_startups_begin = options->max_startups;
+       if (options->max_authtries == -1)
+               options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
+       if (options->max_sessions == -1)
+               options->max_sessions = DEFAULT_SESSIONS_MAX;
+       if (options->use_dns == -1)
+               options->use_dns = 1;
+       if (options->client_alive_interval == -1)
+               options->client_alive_interval = 0;
+       if (options->client_alive_count_max == -1)
+               options->client_alive_count_max = 3;
+       if (options->num_authkeys_files == 0) {
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
+       }
+       if (options->permit_tun == -1)
+               options->permit_tun = SSH_TUNMODE_NO;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+
+       /* Turn privilege separation on by default */
+       if (use_privsep == -1)
+               use_privsep = PRIVSEP_ON;
+
+#ifndef HAVE_MMAP
+       if (use_privsep && options->compression == 1) {
+               error("This platform does not support both privilege "
+                   "separation and compression");
+               error("Compression disabled");
+               options->compression = 0;
+       }
+#endif
+
+}
+
+/* Keyword tokens. */
+typedef enum {
+       sBadOption,             /* == unknown option */
+       /* Portable-specific options */
+       sUsePAM,
+       /* Standard Options */
+       sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
+       sPermitRootLogin, sLogFacility, sLogLevel,
+       sRhostsRSAAuthentication, sRSAAuthentication,
+       sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
+       sKerberosGetAFSToken,
+       sKerberosTgtPassing, sChallengeResponseAuthentication,
+       sPasswordAuthentication, sKbdInteractiveAuthentication,
+       sListenAddress, sAddressFamily,
+       sPrintMotd, sPrintLastLog, sIgnoreRhosts,
+       sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+       sStrictModes, sPermitBlacklistedKeys, sEmptyPasswd, sTCPKeepAlive,
+       sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
+       sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+       sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
+       sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
+       sMaxStartups, sMaxAuthTries, sMaxSessions,
+       sBanner, sUseDNS, sHostbasedAuthentication,
+       sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
+       sClientAliveCountMax, sAuthorizedKeysFile,
+       sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+       sGssKeyEx, sGssStoreRekey,
+       sAcceptEnv, sPermitTunnel,
+       sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
+       sUsePrivilegeSeparation, sAllowAgentForwarding,
+       sZeroKnowledgePasswordAuthentication, sHostCertificate,
+       sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+       sKexAlgorithms, sIPQoS,
+       sDeprecated, sUnsupported
+} ServerOpCodes;
+
+#define SSHCFG_GLOBAL  0x01    /* allowed in main section of sshd_config */
+#define SSHCFG_MATCH   0x02    /* allowed inside a Match section */
+#define SSHCFG_ALL     (SSHCFG_GLOBAL|SSHCFG_MATCH)
+
+/* Textual representation of the tokens. */
+static struct {
+       const char *name;
+       ServerOpCodes opcode;
+       u_int flags;
+} keywords[] = {
+       /* Portable-specific options */
+#ifdef USE_PAM
+       { "usepam", sUsePAM, SSHCFG_GLOBAL },
+#else
+       { "usepam", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
+       /* Standard Options */
+       { "port", sPort, SSHCFG_GLOBAL },
+       { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
+       { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },          /* alias */
+       { "pidfile", sPidFile, SSHCFG_GLOBAL },
+       { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
+       { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
+       { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
+       { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
+       { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
+       { "loglevel", sLogLevel, SSHCFG_GLOBAL },
+       { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
+       { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
+       { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
+       { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
+       { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
+       { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
+       { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
+#ifdef KRB5
+       { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
+       { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
+       { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
+#ifdef USE_AFS
+       { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
+#else
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+#endif
+#else
+       { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
+       { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
+       { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
+#ifdef GSSAPI
+       { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+       { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL },
+       { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
+#else
+       { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
+       { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
+       { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
+       { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
+       { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
+#else
+       { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
+#endif
+       { "checkmail", sDeprecated, SSHCFG_GLOBAL },
+       { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
+       { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
+       { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
+       { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
+       { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
+       { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
+       { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
+       { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
+       { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
+       { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
+       { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
+       { "permitblacklistedkeys", sPermitBlacklistedKeys, SSHCFG_GLOBAL },
+       { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
+       { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
+       { "uselogin", sUseLogin, SSHCFG_GLOBAL },
+       { "compression", sCompression, SSHCFG_GLOBAL },
+       { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
+       { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },  /* obsolete alias */
+       { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
+       { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
+       { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
+       { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
+       { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
+       { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
+       { "ciphers", sCiphers, SSHCFG_GLOBAL },
+       { "macs", sMacs, SSHCFG_GLOBAL },
+       { "protocol", sProtocol, SSHCFG_GLOBAL },
+       { "gatewayports", sGatewayPorts, SSHCFG_ALL },
+       { "subsystem", sSubsystem, SSHCFG_GLOBAL },
+       { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
+       { "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
+       { "maxsessions", sMaxSessions, SSHCFG_ALL },
+       { "banner", sBanner, SSHCFG_ALL },
+       { "usedns", sUseDNS, SSHCFG_GLOBAL },
+       { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
+       { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
+       { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
+       { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
+       { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
+       { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
+       { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
+       { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
+       { "permittunnel", sPermitTunnel, SSHCFG_ALL },
+       { "match", sMatch, SSHCFG_ALL },
+       { "permitopen", sPermitOpen, SSHCFG_ALL },
+       { "forcecommand", sForceCommand, SSHCFG_ALL },
+       { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+       { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
+       { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
+       { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
+       { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
+       { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+       { "ipqos", sIPQoS, SSHCFG_ALL },
+       { NULL, sBadOption, 0 }
+};
+
+static struct {
+       int val;
+       char *text;
+} tunmode_desc[] = {
+       { SSH_TUNMODE_NO, "no" },
+       { SSH_TUNMODE_POINTOPOINT, "point-to-point" },
+       { SSH_TUNMODE_ETHERNET, "ethernet" },
+       { SSH_TUNMODE_YES, "yes" },
+       { -1, NULL }
+};
+
+/*
+ * Returns the number of the token pointed to by cp or sBadOption.
+ */
+
+static ServerOpCodes
+parse_token(const char *cp, const char *filename,
+           int linenum, u_int *flags)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0) {
+                       *flags = keywords[i].flags;
+                       return keywords[i].opcode;
+               }
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return sBadOption;
+}
+
+char *
+derelativise_path(const char *path)
+{
+       char *expanded, *ret, cwd[MAXPATHLEN];
+
+       expanded = tilde_expand_filename(path, getuid());
+       if (*expanded == '/')
+               return expanded;
+       if (getcwd(cwd, sizeof(cwd)) == NULL)
+               fatal("%s: getcwd: %s", __func__, strerror(errno));
+       xasprintf(&ret, "%s/%s", cwd, expanded);
+       xfree(expanded);
+       return ret;
+}
+
+static void
+add_listen_addr(ServerOptions *options, char *addr, int port)
+{
+       u_int i;
+
+       if (options->num_ports == 0)
+               options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (port == 0)
+               for (i = 0; i < options->num_ports; i++)
+                       add_one_listen_addr(options, addr, options->ports[i]);
+       else
+               add_one_listen_addr(options, addr, port);
+}
+
+static void
+add_one_listen_addr(ServerOptions *options, char *addr, int port)
+{
+       struct addrinfo hints, *ai, *aitop;
+       char strport[NI_MAXSERV];
+       int gaierr;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = options->address_family;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
+       snprintf(strport, sizeof strport, "%d", port);
+       if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
+               fatal("bad addr or host: %s (%s)",
+                   addr ? addr : "<NULL>",
+                   ssh_gai_strerror(gaierr));
+       for (ai = aitop; ai->ai_next; ai = ai->ai_next)
+               ;
+       ai->ai_next = options->listen_addrs;
+       options->listen_addrs = aitop;
+}
+
+/*
+ * The strategy for the Match blocks is that the config file is parsed twice.
+ *
+ * The first time is at startup.  activep is initialized to 1 and the
+ * directives in the global context are processed and acted on.  Hitting a
+ * Match directive unsets activep and the directives inside the block are
+ * checked for syntax only.
+ *
+ * The second time is after a connection has been established but before
+ * authentication.  activep is initialized to 2 and global config directives
+ * are ignored since they have already been processed.  If the criteria in a
+ * Match block is met, activep is set and the subsequent directives
+ * processed and actioned until EOF or another Match block unsets it.  Any
+ * options set are copied into the main server config.
+ *
+ * Potential additions/improvements:
+ *  - Add Match support for pre-kex directives, eg Protocol, Ciphers.
+ *
+ *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
+ *     Match Address 192.168.0.*
+ *             Tag trusted
+ *     Match Group wheel
+ *             Tag trusted
+ *     Match Tag trusted
+ *             AllowTcpForwarding yes
+ *             GatewayPorts clientspecified
+ *             [...]
+ *
+ *  - Add a PermittedChannelRequests directive
+ *     Match Group shell
+ *             PermittedChannelRequests session,forwarded-tcpip
+ */
+
+static int
+match_cfg_line_group(const char *grps, int line, const char *user)
+{
+       int result = 0;
+       struct passwd *pw;
+
+       if (user == NULL)
+               goto out;
+
+       if ((pw = getpwnam(user)) == NULL) {
+               debug("Can't match group at line %d because user %.100s does "
+                   "not exist", line, user);
+       } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+               debug("Can't Match group because user %.100s not in any group "
+                   "at line %d", user, line);
+       } else if (ga_match_pattern_list(grps) != 1) {
+               debug("user %.100s does not match group list %.100s at line %d",
+                   user, grps, line);
+       } else {
+               debug("user %.100s matched group list %.100s at line %d", user,
+                   grps, line);
+               result = 1;
+       }
+out:
+       ga_free();
+       return result;
+}
+
+static int
+match_cfg_line(char **condition, int line, const char *user, const char *host,
+    const char *address)
+{
+       int result = 1;
+       char *arg, *attrib, *cp = *condition;
+       size_t len;
+
+       if (user == NULL)
+               debug3("checking syntax for 'Match %s'", cp);
+       else
+               debug3("checking match for '%s' user %s host %s addr %s", cp,
+                   user ? user : "(null)", host ? host : "(null)",
+                   address ? address : "(null)");
+
+       while ((attrib = strdelim(&cp)) && *attrib != '\0') {
+               if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
+                       error("Missing Match criteria for %s", attrib);
+                       return -1;
+               }
+               len = strlen(arg);
+               if (strcasecmp(attrib, "user") == 0) {
+                       if (!user) {
+                               result = 0;
+                               continue;
+                       }
+                       if (match_pattern_list(user, arg, len, 0) != 1)
+                               result = 0;
+                       else
+                               debug("user %.100s matched 'User %.100s' at "
+                                   "line %d", user, arg, line);
+               } else if (strcasecmp(attrib, "group") == 0) {
+                       switch (match_cfg_line_group(arg, line, user)) {
+                       case -1:
+                               return -1;
+                       case 0:
+                               result = 0;
+                       }
+               } else if (strcasecmp(attrib, "host") == 0) {
+                       if (!host) {
+                               result = 0;
+                               continue;
+                       }
+                       if (match_hostname(host, arg, len) != 1)
+                               result = 0;
+                       else
+                               debug("connection from %.100s matched 'Host "
+                                   "%.100s' at line %d", host, arg, line);
+               } else if (strcasecmp(attrib, "address") == 0) {
+                       switch (addr_match_list(address, arg)) {
+                       case 1:
+                               debug("connection from %.100s matched 'Address "
+                                   "%.100s' at line %d", address, arg, line);
+                               break;
+                       case 0:
+                       case -1:
+                               result = 0;
+                               break;
+                       case -2:
+                               return -1;
+                       }
+               } else {
+                       error("Unsupported Match attribute %s", attrib);
+                       return -1;
+               }
+       }
+       if (user != NULL)
+               debug3("match %sfound", result ? "" : "not ");
+       *condition = cp;
+       return result;
+}
+
+#define WHITESPACE " \t\r\n"
+
+/* Multistate option parsing */
+struct multistate {
+       char *key;
+       int value;
+};
+static const struct multistate multistate_addressfamily[] = {
+       { "inet",                       AF_INET },
+       { "inet6",                      AF_INET6 },
+       { "any",                        AF_UNSPEC },
+       { NULL, -1 }
+};
+static const struct multistate multistate_permitrootlogin[] = {
+       { "without-password",           PERMIT_NO_PASSWD },
+       { "forced-commands-only",       PERMIT_FORCED_ONLY },
+       { "yes",                        PERMIT_YES },
+       { "no",                         PERMIT_NO },
+       { NULL, -1 }
+};
+static const struct multistate multistate_compression[] = {
+       { "delayed",                    COMP_DELAYED },
+       { "yes",                        COMP_ZLIB },
+       { "no",                         COMP_NONE },
+       { NULL, -1 }
+};
+static const struct multistate multistate_gatewayports[] = {
+       { "clientspecified",            2 },
+       { "yes",                        1 },
+       { "no",                         0 },
+       { NULL, -1 }
+};
+static const struct multistate multistate_privsep[] = {
+       { "sandbox",                    PRIVSEP_SANDBOX },
+       { "yes",                        PRIVSEP_ON },
+       { "no",                         PRIVSEP_OFF },
+       { NULL, -1 }
+};
+
+int
+process_server_config_line(ServerOptions *options, char *line,
+    const char *filename, int linenum, int *activep, const char *user,
+    const char *host, const char *address)
+{
+       char *cp, **charptr, *arg, *p;
+       int cmdline = 0, *intptr, value, value2, n;
+       SyslogFacility *log_facility_ptr;
+       LogLevel *log_level_ptr;
+       ServerOpCodes opcode;
+       int port;
+       u_int i, flags = 0;
+       size_t len;
+       const struct multistate *multistate_ptr;
+
+       cp = line;
+       if ((arg = strdelim(&cp)) == NULL)
+               return 0;
+       /* Ignore leading whitespace */
+       if (*arg == '\0')
+               arg = strdelim(&cp);
+       if (!arg || !*arg || *arg == '#')
+               return 0;
+       intptr = NULL;
+       charptr = NULL;
+       opcode = parse_token(arg, filename, linenum, &flags);
+
+       if (activep == NULL) { /* We are processing a command line directive */
+               cmdline = 1;
+               activep = &cmdline;
+       }
+       if (*activep && opcode != sMatch)
+               debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
+       if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
+               if (user == NULL) {
+                       fatal("%s line %d: Directive '%s' is not allowed "
+                           "within a Match block", filename, linenum, arg);
+               } else { /* this is a directive we have already processed */
+                       while (arg)
+                               arg = strdelim(&cp);
+                       return 0;
+               }
+       }
+
+       switch (opcode) {
+       /* Portable-specific options */
+       case sUsePAM:
+               intptr = &options->use_pam;
+               goto parse_flag;
+
+       /* Standard Options */
+       case sBadOption:
+               return -1;
+       case sPort:
+               /* ignore ports from configfile if cmdline specifies ports */
+               if (options->ports_from_cmdline)
+                       return 0;
+               if (options->listen_addrs != NULL)
+                       fatal("%s line %d: ports must be specified before "
+                           "ListenAddress.", filename, linenum);
+               if (options->num_ports >= MAX_PORTS)
+                       fatal("%s line %d: too many ports.",
+                           filename, linenum);
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing port number.",
+                           filename, linenum);
+               options->ports[options->num_ports++] = a2port(arg);
+               if (options->ports[options->num_ports-1] <= 0)
+                       fatal("%s line %d: Badly formatted port number.",
+                           filename, linenum);
+               break;
+
+       case sServerKeyBits:
+               intptr = &options->server_key_bits;
+ parse_int:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing integer value.",
+                           filename, linenum);
+               value = atoi(arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sLoginGraceTime:
+               intptr = &options->login_grace_time;
+ parse_time:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sKeyRegenerationTime:
+               intptr = &options->key_regeneration_time;
+               goto parse_time;
+
+       case sListenAddress:
+               arg = strdelim(&cp);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%s line %d: missing address",
+                           filename, linenum);
+               /* check for bare IPv6 address: no "[]" and 2 or more ":" */
+               if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
+                   && strchr(p+1, ':') != NULL) {
+                       add_listen_addr(options, arg, 0);
+                       break;
+               }
+               p = hpdelim(&arg);
+               if (p == NULL)
+                       fatal("%s line %d: bad address:port usage",
+                           filename, linenum);
+               p = cleanhostname(p);
+               if (arg == NULL)
+                       port = 0;
+               else if ((port = a2port(arg)) <= 0)
+                       fatal("%s line %d: bad port number", filename, linenum);
+
+               add_listen_addr(options, p, port);
+
+               break;
+
+       case sAddressFamily:
+               intptr = &options->address_family;
+               multistate_ptr = multistate_addressfamily;
+               if (options->listen_addrs != NULL)
+                       fatal("%s line %d: address family must be specified "
+                           "before ListenAddress.", filename, linenum);
+ parse_multistate:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               value = -1;
+               for (i = 0; multistate_ptr[i].key != NULL; i++) {
+                       if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
+                               value = multistate_ptr[i].value;
+                               break;
+                       }
+               }
+               if (value == -1)
+                       fatal("%s line %d: unsupported option \"%s\".",
+                           filename, linenum, arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sHostKeyFile:
+               intptr = &options->num_host_key_files;
+               if (*intptr >= MAX_HOSTKEYS)
+                       fatal("%s line %d: too many host keys specified (max %d).",
+                           filename, linenum, MAX_HOSTKEYS);
+               charptr = &options->host_key_files[*intptr];
+ parse_filename:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL) {
+                       *charptr = derelativise_path(arg);
+                       /* increase optional counter */
+                       if (intptr != NULL)
+                               *intptr = *intptr + 1;
+               }
+               break;
+
+       case sHostCertificate:
+               intptr = &options->num_host_cert_files;
+               if (*intptr >= MAX_HOSTKEYS)
+                       fatal("%s line %d: too many host certificates "
+                           "specified (max %d).", filename, linenum,
+                           MAX_HOSTCERTS);
+               charptr = &options->host_cert_files[*intptr];
+               goto parse_filename;
+               break;
+
+       case sPidFile:
+               charptr = &options->pid_file;
+               goto parse_filename;
+
+       case sPermitRootLogin:
+               intptr = &options->permit_root_login;
+               multistate_ptr = multistate_permitrootlogin;
+               goto parse_multistate;
+
+       case sIgnoreRhosts:
+               intptr = &options->ignore_rhosts;
+ parse_flag:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing yes/no argument.",
+                           filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcmp(arg, "yes") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0)
+                       value = 0;
+               else
+                       fatal("%s line %d: Bad yes/no argument: %s",
+                               filename, linenum, arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sIgnoreUserKnownHosts:
+               intptr = &options->ignore_user_known_hosts;
+               goto parse_flag;
+
+       case sRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case sHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case sHostbasedUsesNameFromPacketOnly:
+               intptr = &options->hostbased_uses_name_from_packet_only;
+               goto parse_flag;
+
+       case sRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case sPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case sKerberosAuthentication:
+               intptr = &options->kerberos_authentication;
+               goto parse_flag;
+
+       case sKerberosOrLocalPasswd:
+               intptr = &options->kerberos_or_local_passwd;
+               goto parse_flag;
+
+       case sKerberosTicketCleanup:
+               intptr = &options->kerberos_ticket_cleanup;
+               goto parse_flag;
+
+       case sKerberosGetAFSToken:
+               intptr = &options->kerberos_get_afs_token;
+               goto parse_flag;
+
+       case sGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case sGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
+       case sGssCleanupCreds:
+               intptr = &options->gss_cleanup_creds;
+               goto parse_flag;
+
+       case sGssStrictAcceptor:
+               intptr = &options->gss_strict_acceptor;
+               goto parse_flag;
+
+       case sGssStoreRekey:
+               intptr = &options->gss_store_rekey;
+               goto parse_flag;
+
+       case sPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case sZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case sKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case sChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case sPrintMotd:
+               intptr = &options->print_motd;
+               goto parse_flag;
+
+       case sPrintLastLog:
+               intptr = &options->print_lastlog;
+               goto parse_flag;
+
+       case sX11Forwarding:
+               intptr = &options->x11_forwarding;
+               goto parse_flag;
+
+       case sX11DisplayOffset:
+               intptr = &options->x11_display_offset;
+               goto parse_int;
+
+       case sX11UseLocalhost:
+               intptr = &options->x11_use_localhost;
+               goto parse_flag;
+
+       case sXAuthLocation:
+               charptr = &options->xauth_location;
+               goto parse_filename;
+
+       case sStrictModes:
+               intptr = &options->strict_modes;
+               goto parse_flag;
+
+       case sTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case sPermitBlacklistedKeys:
+               intptr = &options->permit_blacklisted_keys;
+               goto parse_flag;
+
+       case sEmptyPasswd:
+               intptr = &options->permit_empty_passwd;
+               goto parse_flag;
+
+       case sPermitUserEnvironment:
+               intptr = &options->permit_user_env;
+               goto parse_flag;
+
+       case sUseLogin:
+               intptr = &options->use_login;
+               goto parse_flag;
+
+       case sCompression:
+               intptr = &options->compression;
+               multistate_ptr = multistate_compression;
+               goto parse_multistate;
+
+       case sGatewayPorts:
+               intptr = &options->gateway_ports;
+               multistate_ptr = multistate_gatewayports;
+               goto parse_multistate;
+
+       case sUseDNS:
+               intptr = &options->use_dns;
+               goto parse_flag;
+
+       case sLogFacility:
+               log_facility_ptr = &options->log_facility;
+               arg = strdelim(&cp);
+               value = log_facility_number(arg);
+               if (value == SYSLOG_FACILITY_NOT_SET)
+                       fatal("%.200s line %d: unsupported log facility '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*log_facility_ptr == -1)
+                       *log_facility_ptr = (SyslogFacility) value;
+               break;
+
+       case sLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&cp);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*log_level_ptr == -1)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case sAllowTcpForwarding:
+               intptr = &options->allow_tcp_forwarding;
+               goto parse_flag;
+
+       case sAllowAgentForwarding:
+               intptr = &options->allow_agent_forwarding;
+               goto parse_flag;
+
+       case sUsePrivilegeSeparation:
+               intptr = &use_privsep;
+               multistate_ptr = multistate_privsep;
+               goto parse_multistate;
+
+       case sAllowUsers:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_allow_users >= MAX_ALLOW_USERS)
+                               fatal("%s line %d: too many allow users.",
+                                   filename, linenum);
+                       options->allow_users[options->num_allow_users++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sDenyUsers:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_deny_users >= MAX_DENY_USERS)
+                               fatal("%s line %d: too many deny users.",
+                                   filename, linenum);
+                       options->deny_users[options->num_deny_users++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sAllowGroups:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
+                               fatal("%s line %d: too many allow groups.",
+                                   filename, linenum);
+                       options->allow_groups[options->num_allow_groups++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sDenyGroups:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_deny_groups >= MAX_DENY_GROUPS)
+                               fatal("%s line %d: too many deny groups.",
+                                   filename, linenum);
+                       options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
+               }
+               break;
+
+       case sCiphers:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case sMacs:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%s line %d: Bad SSH2 mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case sKexAlgorithms:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case sProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case sSubsystem:
+               if (options->num_subsystems >= MAX_SUBSYSTEMS) {
+                       fatal("%s line %d: too many subsystems defined.",
+                           filename, linenum);
+               }
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing subsystem name.",
+                           filename, linenum);
+               if (!*activep) {
+                       arg = strdelim(&cp);
+                       break;
+               }
+               for (i = 0; i < options->num_subsystems; i++)
+                       if (strcmp(arg, options->subsystem_name[i]) == 0)
+                               fatal("%s line %d: Subsystem '%s' already defined.",
+                                   filename, linenum, arg);
+               options->subsystem_name[options->num_subsystems] = xstrdup(arg);
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing subsystem command.",
+                           filename, linenum);
+               options->subsystem_command[options->num_subsystems] = xstrdup(arg);
+
+               /* Collect arguments (separate to executable) */
+               p = xstrdup(arg);
+               len = strlen(p) + 1;
+               while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
+                       len += 1 + strlen(arg);
+                       p = xrealloc(p, 1, len);
+                       strlcat(p, " ", len);
+                       strlcat(p, arg, len);
+               }
+               options->subsystem_args[options->num_subsystems] = p;
+               options->num_subsystems++;
+               break;
+
+       case sMaxStartups:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing MaxStartups spec.",
+                           filename, linenum);
+               if ((n = sscanf(arg, "%d:%d:%d",
+                   &options->max_startups_begin,
+                   &options->max_startups_rate,
+                   &options->max_startups)) == 3) {
+                       if (options->max_startups_begin >
+                           options->max_startups ||
+                           options->max_startups_rate > 100 ||
+                           options->max_startups_rate < 1)
+                               fatal("%s line %d: Illegal MaxStartups spec.",
+                                   filename, linenum);
+               } else if (n != 1)
+                       fatal("%s line %d: Illegal MaxStartups spec.",
+                           filename, linenum);
+               else
+                       options->max_startups = options->max_startups_begin;
+               break;
+
+       case sMaxAuthTries:
+               intptr = &options->max_authtries;
+               goto parse_int;
+
+       case sMaxSessions:
+               intptr = &options->max_sessions;
+               goto parse_int;
+
+       case sBanner:
+               charptr = &options->banner;
+               goto parse_filename;
+
+       /*
+        * These options can contain %X options expanded at
+        * connect time, so that you can specify paths like:
+        *
+        * AuthorizedKeysFile   /etc/ssh_keys/%u
+        */
+       case sAuthorizedKeysFile:
+               if (*activep && options->num_authkeys_files == 0) {
+                       while ((arg = strdelim(&cp)) && *arg != '\0') {
+                               if (options->num_authkeys_files >=
+                                   MAX_AUTHKEYS_FILES)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               options->authorized_keys_files[
+                                   options->num_authkeys_files++] =
+                                   tilde_expand_filename(arg, getuid());
+                       }
+               }
+               return 0;
+
+       case sAuthorizedPrincipalsFile:
+               charptr = &options->authorized_principals_file;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL) {
+                       *charptr = tilde_expand_filename(arg, getuid());
+                       /* increase optional counter */
+                       if (intptr != NULL)
+                               *intptr = *intptr + 1;
+               }
+               break;
+
+       case sClientAliveInterval:
+               intptr = &options->client_alive_interval;
+               goto parse_time;
+
+       case sClientAliveCountMax:
+               intptr = &options->client_alive_count_max;
+               goto parse_int;
+
+       case sAcceptEnv:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (options->num_accept_env >= MAX_ACCEPT_ENV)
+                               fatal("%s line %d: too many allow env.",
+                                   filename, linenum);
+                       if (!*activep)
+                               break;
+                       options->accept_env[options->num_accept_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sPermitTunnel:
+               intptr = &options->permit_tun;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = -1;
+               for (i = 0; tunmode_desc[i].val != -1; i++)
+                       if (strcmp(tunmode_desc[i].text, arg) == 0) {
+                               value = tunmode_desc[i].val;
+                               break;
+                       }
+               if (value == -1)
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sMatch:
+               if (cmdline)
+                       fatal("Match directive not supported as a command-line "
+                          "option");
+               value = match_cfg_line(&cp, linenum, user, host, address);
+               if (value < 0)
+                       fatal("%s line %d: Bad Match condition", filename,
+                           linenum);
+               *activep = value;
+               break;
+
+       case sPermitOpen:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing PermitOpen specification",
+                           filename, linenum);
+               n = options->num_permitted_opens;       /* modified later */
+               if (strcmp(arg, "any") == 0) {
+                       if (*activep && n == -1) {
+                               channel_clear_adm_permitted_opens();
+                               options->num_permitted_opens = 0;
+                       }
+                       break;
+               }
+               if (*activep && n == -1)
+                       channel_clear_adm_permitted_opens();
+               for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
+                       p = hpdelim(&arg);
+                       if (p == NULL)
+                               fatal("%s line %d: missing host in PermitOpen",
+                                   filename, linenum);
+                       p = cleanhostname(p);
+                       if (arg == NULL || (port = a2port(arg)) <= 0)
+                               fatal("%s line %d: bad port number in "
+                                   "PermitOpen", filename, linenum);
+                       if (*activep && n == -1)
+                               options->num_permitted_opens =
+                                   channel_add_adm_permitted_opens(p, port);
+               }
+               break;
+
+       case sForceCommand:
+               if (cp == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename,
+                           linenum);
+               len = strspn(cp, WHITESPACE);
+               if (*activep && options->adm_forced_command == NULL)
+                       options->adm_forced_command = xstrdup(cp + len);
+               return 0;
+
+       case sChrootDirectory:
+               charptr = &options->chroot_directory;
+
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case sTrustedUserCAKeys:
+               charptr = &options->trusted_user_ca_keys;
+               goto parse_filename;
+
+       case sRevokedKeys:
+               charptr = &options->revoked_keys_file;
+               goto parse_filename;
+
+       case sIPQoS:
+               arg = strdelim(&cp);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&cp);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case sDeprecated:
+               logit("%s line %d: Deprecated option %s",
+                   filename, linenum, arg);
+               while (arg)
+                   arg = strdelim(&cp);
+               break;
+
+       case sUnsupported:
+               logit("%s line %d: Unsupported option %s",
+                   filename, linenum, arg);
+               while (arg)
+                   arg = strdelim(&cp);
+               break;
+
+       default:
+               fatal("%s line %d: Missing handler for opcode %s (%d)",
+                   filename, linenum, arg, opcode);
+       }
+       if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
+               fatal("%s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       return 0;
+}
+
+/* Reads the server configuration file. */
+
+void
+load_server_config(const char *filename, Buffer *conf)
+{
+       char line[1024], *cp;
+       FILE *f;
+
+       debug2("%s: filename %s", __func__, filename);
+       if ((f = fopen(filename, "r")) == NULL) {
+               perror(filename);
+               exit(1);
+       }
+       buffer_clear(conf);
+       while (fgets(line, sizeof(line), f)) {
+               /*
+                * Trim out comments and strip whitespace
+                * NB - preserve newlines, they are needed to reproduce
+                * line numbers later for error messages
+                */
+               if ((cp = strchr(line, '#')) != NULL)
+                       memcpy(cp, "\n", 2);
+               cp = line + strspn(line, " \t\r");
+
+               buffer_append(conf, cp, strlen(cp));
+       }
+       buffer_append(conf, "\0", 1);
+       fclose(f);
+       debug2("%s: done config len = %d", __func__, buffer_len(conf));
+}
+
+void
+parse_server_match_config(ServerOptions *options, const char *user,
+    const char *host, const char *address)
+{
+       ServerOptions mo;
+
+       initialize_server_options(&mo);
+       parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
+       copy_set_server_options(options, &mo, 0);
+}
+
+/* Helper macros */
+#define M_CP_INTOPT(n) do {\
+       if (src->n != -1) \
+               dst->n = src->n; \
+} while (0)
+#define M_CP_STROPT(n) do {\
+       if (src->n != NULL) { \
+               if (dst->n != NULL) \
+                       xfree(dst->n); \
+               dst->n = src->n; \
+       } \
+} while(0)
+#define M_CP_STRARRAYOPT(n, num_n) do {\
+       if (src->num_n != 0) { \
+               for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
+                       dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
+       } \
+} while(0)
+
+/*
+ * Copy any supported values that are set.
+ *
+ * If the preauth flag is set, we do not bother copying the string or
+ * array values that are not used pre-authentication, because any that we
+ * do use must be explictly sent in mm_getpwnamallow().
+ */
+void
+copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
+{
+       M_CP_INTOPT(password_authentication);
+       M_CP_INTOPT(gss_authentication);
+       M_CP_INTOPT(rsa_authentication);
+       M_CP_INTOPT(pubkey_authentication);
+       M_CP_INTOPT(kerberos_authentication);
+       M_CP_INTOPT(hostbased_authentication);
+       M_CP_INTOPT(hostbased_uses_name_from_packet_only);
+       M_CP_INTOPT(kbd_interactive_authentication);
+       M_CP_INTOPT(zero_knowledge_password_authentication);
+       M_CP_INTOPT(permit_root_login);
+       M_CP_INTOPT(permit_empty_passwd);
+
+       M_CP_INTOPT(allow_tcp_forwarding);
+       M_CP_INTOPT(allow_agent_forwarding);
+       M_CP_INTOPT(permit_tun);
+       M_CP_INTOPT(gateway_ports);
+       M_CP_INTOPT(x11_display_offset);
+       M_CP_INTOPT(x11_forwarding);
+       M_CP_INTOPT(x11_use_localhost);
+       M_CP_INTOPT(max_sessions);
+       M_CP_INTOPT(max_authtries);
+       M_CP_INTOPT(ip_qos_interactive);
+       M_CP_INTOPT(ip_qos_bulk);
+
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+
+       /*
+        * The only things that should be below this point are string options
+        * which are only used after authentication.
+        */
+       if (preauth)
+               return;
+
+       M_CP_STROPT(adm_forced_command);
+       M_CP_STROPT(chroot_directory);
+}
+
+#undef M_CP_INTOPT
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+
+void
+parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
+    const char *user, const char *host, const char *address)
+{
+       int active, linenum, bad_options = 0;
+       char *cp, *obuf, *cbuf;
+
+       debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
+
+       obuf = cbuf = xstrdup(buffer_ptr(conf));
+       active = user ? 0 : 1;
+       linenum = 1;
+       while ((cp = strsep(&cbuf, "\n")) != NULL) {
+               if (process_server_config_line(options, cp, filename,
+                   linenum++, &active, user, host, address) != 0)
+                       bad_options++;
+       }
+       xfree(obuf);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+}
+
+static const char *
+fmt_multistate_int(int val, const struct multistate *m)
+{
+       u_int i;
+
+       for (i = 0; m[i].key != NULL; i++) {
+               if (m[i].value == val)
+                       return m[i].key;
+       }
+       return "UNKNOWN";
+}
+
+static const char *
+fmt_intarg(ServerOpCodes code, int val)
+{
+       if (val == -1)
+               return "unset";
+       switch (code) {
+       case sAddressFamily:
+               return fmt_multistate_int(val, multistate_addressfamily);
+       case sPermitRootLogin:
+               return fmt_multistate_int(val, multistate_permitrootlogin);
+       case sGatewayPorts:
+               return fmt_multistate_int(val, multistate_gatewayports);
+       case sCompression:
+               return fmt_multistate_int(val, multistate_compression);
+       case sUsePrivilegeSeparation:
+               return fmt_multistate_int(val, multistate_privsep);
+       case sProtocol:
+               switch (val) {
+               case SSH_PROTO_1:
+                       return "1";
+               case SSH_PROTO_2:
+                       return "2";
+               case (SSH_PROTO_1|SSH_PROTO_2):
+                       return "2,1";
+               default:
+                       return "UNKNOWN";
+               }
+       default:
+               switch (val) {
+               case 0:
+                       return "no";
+               case 1:
+                       return "yes";
+               default:
+                       return "UNKNOWN";
+               }
+       }
+}
+
+static const char *
+lookup_opcode_name(ServerOpCodes code)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name != NULL; i++)
+               if (keywords[i].opcode == code)
+                       return(keywords[i].name);
+       return "UNKNOWN";
+}
+
+static void
+dump_cfg_int(ServerOpCodes code, int val)
+{
+       printf("%s %d\n", lookup_opcode_name(code), val);
+}
+
+static void
+dump_cfg_fmtint(ServerOpCodes code, int val)
+{
+       printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
+}
+
+static void
+dump_cfg_string(ServerOpCodes code, const char *val)
+{
+       if (val == NULL)
+               return;
+       printf("%s %s\n", lookup_opcode_name(code), val);
+}
+
+static void
+dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
+{
+       u_int i;
+
+       for (i = 0; i < count; i++)
+               printf("%s %s\n", lookup_opcode_name(code), vals[i]);
+}
+
+static void
+dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
+{
+       u_int i;
+
+       printf("%s", lookup_opcode_name(code));
+       for (i = 0; i < count; i++)
+               printf(" %s",  vals[i]);
+       printf("\n");
+}
+
+void
+dump_config(ServerOptions *o)
+{
+       u_int i;
+       int ret;
+       struct addrinfo *ai;
+       char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
+
+       /* these are usually at the top of the config */
+       for (i = 0; i < o->num_ports; i++)
+               printf("port %d\n", o->ports[i]);
+       dump_cfg_fmtint(sProtocol, o->protocol);
+       dump_cfg_fmtint(sAddressFamily, o->address_family);
+
+       /* ListenAddress must be after Port */
+       for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
+                   sizeof(addr), port, sizeof(port),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           (ret != EAI_SYSTEM) ? gai_strerror(ret) :
+                           strerror(errno));
+               } else {
+                       if (ai->ai_family == AF_INET6)
+                               printf("listenaddress [%s]:%s\n", addr, port);
+                       else
+                               printf("listenaddress %s:%s\n", addr, port);
+               }
+       }
+
+       /* integer arguments */
+#ifdef USE_PAM
+       dump_cfg_int(sUsePAM, o->use_pam);
+#endif
+       dump_cfg_int(sServerKeyBits, o->server_key_bits);
+       dump_cfg_int(sLoginGraceTime, o->login_grace_time);
+       dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
+       dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
+       dump_cfg_int(sMaxAuthTries, o->max_authtries);
+       dump_cfg_int(sMaxSessions, o->max_sessions);
+       dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
+       dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
+
+       /* formatted integer arguments */
+       dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
+       dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
+       dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
+       dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
+       dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
+       dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
+           o->hostbased_uses_name_from_packet_only);
+       dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
+       dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
+#ifdef KRB5
+       dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
+       dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
+       dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
+# ifdef USE_AFS
+       dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
+# endif
+#endif
+#ifdef GSSAPI
+       dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+       dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
+       dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
+       dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
+       dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
+#endif
+#ifdef JPAKE
+       dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
+           o->zero_knowledge_password_authentication);
+#endif
+       dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
+       dump_cfg_fmtint(sKbdInteractiveAuthentication,
+           o->kbd_interactive_authentication);
+       dump_cfg_fmtint(sChallengeResponseAuthentication,
+           o->challenge_response_authentication);
+       dump_cfg_fmtint(sPrintMotd, o->print_motd);
+       dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
+       dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
+       dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
+       dump_cfg_fmtint(sStrictModes, o->strict_modes);
+       dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
+       dump_cfg_fmtint(sPermitBlacklistedKeys, o->permit_blacklisted_keys);
+       dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
+       dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
+       dump_cfg_fmtint(sUseLogin, o->use_login);
+       dump_cfg_fmtint(sCompression, o->compression);
+       dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
+       dump_cfg_fmtint(sUseDNS, o->use_dns);
+       dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
+       dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
+
+       /* string arguments */
+       dump_cfg_string(sPidFile, o->pid_file);
+       dump_cfg_string(sXAuthLocation, o->xauth_location);
+       dump_cfg_string(sCiphers, o->ciphers);
+       dump_cfg_string(sMacs, o->macs);
+       dump_cfg_string(sBanner, o->banner);
+       dump_cfg_string(sForceCommand, o->adm_forced_command);
+       dump_cfg_string(sChrootDirectory, o->chroot_directory);
+       dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
+       dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
+       dump_cfg_string(sAuthorizedPrincipalsFile,
+           o->authorized_principals_file);
+
+       /* string arguments requiring a lookup */
+       dump_cfg_string(sLogLevel, log_level_name(o->log_level));
+       dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
+
+       /* string array arguments */
+       dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
+           o->authorized_keys_files);
+       dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
+            o->host_key_files);
+       dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
+            o->host_cert_files);
+       dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
+       dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
+       dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
+       dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
+       dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
+
+       /* other arguments */
+       for (i = 0; i < o->num_subsystems; i++)
+               printf("subsystem %s %s\n", o->subsystem_name[i],
+                   o->subsystem_args[i]);
+
+       printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
+           o->max_startups_rate, o->max_startups);
+
+       for (i = 0; tunmode_desc[i].val != -1; i++)
+               if (tunmode_desc[i].val == o->permit_tun) {
+                       s = tunmode_desc[i].text;
+                       break;
+               }
+       dump_cfg_string(sPermitTunnel, s);
+
+       printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
+       printf("%s\n", iptos2str(o->ip_qos_bulk));
+
+       channel_print_adm_permitted_opens();
+}
diff --git a/.pc/debian-banner.patch/servconf.h b/.pc/debian-banner.patch/servconf.h
new file mode 100644 (file)
index 0000000..229e759
--- /dev/null
@@ -0,0 +1,202 @@
+/* $OpenBSD: servconf.h,v 1.99 2011/06/22 21:57:01 djm Exp $ */
+
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Definitions for server configuration data and for the functions reading it.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#ifndef SERVCONF_H
+#define SERVCONF_H
+
+#define MAX_PORTS              256     /* Max # ports. */
+
+#define MAX_ALLOW_USERS                256     /* Max # users on allow list. */
+#define MAX_DENY_USERS         256     /* Max # users on deny list. */
+#define MAX_ALLOW_GROUPS       256     /* Max # groups on allow list. */
+#define MAX_DENY_GROUPS                256     /* Max # groups on deny list. */
+#define MAX_SUBSYSTEMS         256     /* Max # subsystems. */
+#define MAX_HOSTKEYS           256     /* Max # hostkeys. */
+#define MAX_HOSTCERTS          256     /* Max # host certificates. */
+#define MAX_ACCEPT_ENV         256     /* Max # of env vars. */
+#define MAX_MATCH_GROUPS       256     /* Max # of groups for Match. */
+#define MAX_AUTHKEYS_FILES     256     /* Max # of authorized_keys files. */
+
+/* permit_root_login */
+#define        PERMIT_NOT_SET          -1
+#define        PERMIT_NO               0
+#define        PERMIT_FORCED_ONLY      1
+#define        PERMIT_NO_PASSWD        2
+#define        PERMIT_YES              3
+
+/* use_privsep */
+#define PRIVSEP_OFF            0
+#define PRIVSEP_ON             1
+#define PRIVSEP_SANDBOX                2
+
+#define DEFAULT_AUTH_FAIL_MAX  6       /* Default for MaxAuthTries */
+#define DEFAULT_SESSIONS_MAX   10      /* Default for MaxSessions */
+
+/* Magic name for internal sftp-server */
+#define INTERNAL_SFTP_NAME     "internal-sftp"
+
+typedef struct {
+       u_int   num_ports;
+       u_int   ports_from_cmdline;
+       int     ports[MAX_PORTS];       /* Port number to listen on. */
+       char   *listen_addr;            /* Address on which the server listens. */
+       struct addrinfo *listen_addrs;  /* Addresses on which the server listens. */
+       int     address_family;         /* Address family used by the server. */
+       char   *host_key_files[MAX_HOSTKEYS];   /* Files containing host keys. */
+       int     num_host_key_files;     /* Number of files for host keys. */
+       char   *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */
+       int     num_host_cert_files;     /* Number of files for host certs. */
+       char   *pid_file;       /* Where to put our pid */
+       int     server_key_bits;/* Size of the server key. */
+       int     login_grace_time;       /* Disconnect if no auth in this time
+                                        * (sec). */
+       int     key_regeneration_time;  /* Server key lifetime (seconds). */
+       int     permit_root_login;      /* PERMIT_*, see above */
+       int     ignore_rhosts;  /* Ignore .rhosts and .shosts. */
+       int     ignore_user_known_hosts;        /* Ignore ~/.ssh/known_hosts
+                                                * for RhostsRsaAuth */
+       int     print_motd;     /* If true, print /etc/motd. */
+       int     print_lastlog;  /* If true, print lastlog */
+       int     x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
+       int     x11_display_offset;     /* What DISPLAY number to start
+                                        * searching at */
+       int     x11_use_localhost;      /* If true, use localhost for fake X11 server. */
+       char   *xauth_location; /* Location of xauth program */
+       int     strict_modes;   /* If true, require string home dir modes. */
+       int     tcp_keep_alive; /* If true, set SO_KEEPALIVE. */
+       int     ip_qos_interactive;     /* IP ToS/DSCP/class for interactive */
+       int     ip_qos_bulk;            /* IP ToS/DSCP/class for bulk traffic */
+       char   *ciphers;        /* Supported SSH2 ciphers. */
+       char   *macs;           /* Supported SSH2 macs. */
+       char   *kex_algorithms; /* SSH2 kex methods in order of preference. */
+       int     protocol;       /* Supported protocol versions. */
+       int     gateway_ports;  /* If true, allow remote connects to forwarded ports. */
+       SyslogFacility log_facility;    /* Facility for system logging. */
+       LogLevel log_level;     /* Level for system logging. */
+       int     rhosts_rsa_authentication;      /* If true, permit rhosts RSA
+                                                * authentication. */
+       int     hostbased_authentication;       /* If true, permit ssh2 hostbased auth */
+       int     hostbased_uses_name_from_packet_only; /* experimental */
+       int     rsa_authentication;     /* If true, permit RSA authentication. */
+       int     pubkey_authentication;  /* If true, permit ssh2 pubkey authentication. */
+       int     kerberos_authentication;        /* If true, permit Kerberos
+                                                * authentication. */
+       int     kerberos_or_local_passwd;       /* If true, permit kerberos
+                                                * and any other password
+                                                * authentication mechanism,
+                                                * such as SecurID or
+                                                * /etc/passwd */
+       int     kerberos_ticket_cleanup;        /* If true, destroy ticket
+                                                * file on logout. */
+       int     kerberos_get_afs_token;         /* If true, try to get AFS token if
+                                                * authenticated with Kerberos. */
+       int     gss_authentication;     /* If true, permit GSSAPI authentication */
+       int     gss_keyex;              /* If true, permit GSSAPI key exchange */
+       int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
+       int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
+       int     gss_store_rekey;
+       int     password_authentication;        /* If true, permit password
+                                                * authentication. */
+       int     kbd_interactive_authentication; /* If true, permit */
+       int     challenge_response_authentication;
+       int     zero_knowledge_password_authentication;
+                                       /* If true, permit jpake auth */
+       int     permit_blacklisted_keys;        /* If true, permit */
+       int     permit_empty_passwd;    /* If false, do not permit empty
+                                        * passwords. */
+       int     permit_user_env;        /* If true, read ~/.ssh/environment */
+       int     use_login;      /* If true, login(1) is used */
+       int     compression;    /* If true, compression is allowed */
+       int     allow_tcp_forwarding;
+       int     allow_agent_forwarding;
+       u_int num_allow_users;
+       char   *allow_users[MAX_ALLOW_USERS];
+       u_int num_deny_users;
+       char   *deny_users[MAX_DENY_USERS];
+       u_int num_allow_groups;
+       char   *allow_groups[MAX_ALLOW_GROUPS];
+       u_int num_deny_groups;
+       char   *deny_groups[MAX_DENY_GROUPS];
+
+       u_int num_subsystems;
+       char   *subsystem_name[MAX_SUBSYSTEMS];
+       char   *subsystem_command[MAX_SUBSYSTEMS];
+       char   *subsystem_args[MAX_SUBSYSTEMS];
+
+       u_int num_accept_env;
+       char   *accept_env[MAX_ACCEPT_ENV];
+
+       int     max_startups_begin;
+       int     max_startups_rate;
+       int     max_startups;
+       int     max_authtries;
+       int     max_sessions;
+       char   *banner;                 /* SSH-2 banner message */
+       int     use_dns;
+       int     client_alive_interval;  /*
+                                        * poke the client this often to
+                                        * see if it's still there
+                                        */
+       int     client_alive_count_max; /*
+                                        * If the client is unresponsive
+                                        * for this many intervals above,
+                                        * disconnect the session
+                                        */
+
+       u_int num_authkeys_files;       /* Files containing public keys */
+       char   *authorized_keys_files[MAX_AUTHKEYS_FILES];
+
+       char   *adm_forced_command;
+
+       int     use_pam;                /* Enable auth via PAM */
+
+       int     permit_tun;
+
+       int     num_permitted_opens;
+
+       char   *chroot_directory;
+       char   *revoked_keys_file;
+       char   *trusted_user_ca_keys;
+       char   *authorized_principals_file;
+}       ServerOptions;
+
+/*
+ * These are string config options that must be copied between the
+ * Match sub-config and the main config, and must be sent from the
+ * privsep slave to the privsep master. We use a macro to ensure all
+ * the options are copied and the copies are done in the correct order.
+ */
+#define COPY_MATCH_STRING_OPTS() do { \
+               M_CP_STROPT(banner); \
+               M_CP_STROPT(trusted_user_ca_keys); \
+               M_CP_STROPT(revoked_keys_file); \
+               M_CP_STROPT(authorized_principals_file); \
+               M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
+       } while (0)
+
+void    initialize_server_options(ServerOptions *);
+void    fill_default_server_options(ServerOptions *);
+int     process_server_config_line(ServerOptions *, char *, const char *, int,
+            int *, const char *, const char *, const char *);
+void    load_server_config(const char *, Buffer *);
+void    parse_server_config(ServerOptions *, const char *, Buffer *,
+            const char *, const char *, const char *);
+void    parse_server_match_config(ServerOptions *, const char *, const char *,
+            const char *);
+void    copy_set_server_options(ServerOptions *, ServerOptions *, int);
+void    dump_config(ServerOptions *);
+char   *derelativise_path(const char *);
+
+#endif                         /* SERVCONF_H */
diff --git a/.pc/debian-banner.patch/sshd.c b/.pc/debian-banner.patch/sshd.c
new file mode 100644 (file)
index 0000000..6bba735
--- /dev/null
@@ -0,0 +1,2486 @@
+/* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * This program is the ssh daemon.  It listens for connections from clients,
+ * and performs authentication, executes use commands or shell, and forwards
+ * information to/from the application to the user client over an encrypted
+ * connection.  This can also handle forwarding of X11, TCP/IP, and
+ * authentication agent connections.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 implementation:
+ * Privilege Separation:
+ *
+ * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2002 Niels Provos.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include "openbsd-compat/sys-tree.h"
+#include "openbsd-compat/sys-queue.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/md5.h>
+#include <openssl/rand.h>
+#include "openbsd-compat/openssl-compat.h"
+
+#ifdef HAVE_SECUREWARE
+#include <sys/security.h>
+#include <prot.h>
+#endif
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "rsa.h"
+#include "sshpty.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "dh.h"
+#include "myproposal.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "atomicio.h"
+#include "canohost.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "misc.h"
+#include "msg.h"
+#include "dispatch.h"
+#include "channels.h"
+#include "session.h"
+#include "monitor_mm.h"
+#include "monitor.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "roaming.h"
+#include "ssh-sandbox.h"
+#include "version.h"
+
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
+
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int allow_severity;
+int deny_severity;
+#endif /* LIBWRAP */
+
+#ifndef O_NOCTTY
+#define O_NOCTTY       0
+#endif
+
+/* Re-exec fds */
+#define REEXEC_DEVCRYPTO_RESERVED_FD   (STDERR_FILENO + 1)
+#define REEXEC_STARTUP_PIPE_FD         (STDERR_FILENO + 2)
+#define REEXEC_CONFIG_PASS_FD          (STDERR_FILENO + 3)
+#define REEXEC_MIN_FREE_FD             (STDERR_FILENO + 4)
+
+extern char *__progname;
+
+/* Server configuration options. */
+ServerOptions options;
+
+/* Name of the server configuration file. */
+char *config_file_name = _PATH_SERVER_CONFIG_FILE;
+
+/*
+ * Debug mode flag.  This can be set on the command line.  If debug
+ * mode is enabled, extra debugging output will be sent to the system
+ * log, the daemon will not go to background, and will exit after processing
+ * the first connection.
+ */
+int debug_flag = 0;
+
+/* Flag indicating that the daemon should only test the configuration and keys. */
+int test_flag = 0;
+
+/* Flag indicating that the daemon is being started from inetd. */
+int inetd_flag = 0;
+
+/* Flag indicating that sshd should not detach and become a daemon. */
+int no_daemon_flag = 0;
+
+/* debug goes to stderr unless inetd_flag is set */
+int log_stderr = 0;
+
+/* Saved arguments to main(). */
+char **saved_argv;
+int saved_argc;
+
+/* re-exec */
+int rexeced_flag = 0;
+int rexec_flag = 1;
+int rexec_argc = 0;
+char **rexec_argv;
+
+/*
+ * The sockets that the server is listening; this is used in the SIGHUP
+ * signal handler.
+ */
+#define        MAX_LISTEN_SOCKS        16
+int listen_socks[MAX_LISTEN_SOCKS];
+int num_listen_socks = 0;
+
+/*
+ * the client's version string, passed by sshd2 in compat mode. if != NULL,
+ * sshd will skip the version-number exchange
+ */
+char *client_version_string = NULL;
+char *server_version_string = NULL;
+
+/* for rekeying XXX fixme */
+Kex *xxx_kex;
+
+/*
+ * Any really sensitive data in the application is contained in this
+ * structure. The idea is that this structure could be locked into memory so
+ * that the pages do not get written into swap.  However, there are some
+ * problems. The private key contains BIGNUMs, and we do not (in principle)
+ * have access to the internals of them, and locking just the structure is
+ * not very useful.  Currently, memory locking is not implemented.
+ */
+struct {
+       Key     *server_key;            /* ephemeral server key */
+       Key     *ssh1_host_key;         /* ssh1 host key */
+       Key     **host_keys;            /* all private host keys */
+       Key     **host_certificates;    /* all public host certificates */
+       int     have_ssh1_key;
+       int     have_ssh2_key;
+       u_char  ssh1_cookie[SSH_SESSION_KEY_LENGTH];
+} sensitive_data;
+
+/*
+ * Flag indicating whether the RSA server key needs to be regenerated.
+ * Is set in the SIGALRM handler and cleared when the key is regenerated.
+ */
+static volatile sig_atomic_t key_do_regen = 0;
+
+/* This is set to true when a signal is received. */
+static volatile sig_atomic_t received_sighup = 0;
+static volatile sig_atomic_t received_sigterm = 0;
+
+/* session identifier, used by RSA-auth */
+u_char session_id[16];
+
+/* same for ssh2 */
+u_char *session_id2 = NULL;
+u_int session_id2_len = 0;
+
+/* record remote hostname or ip */
+u_int utmp_len = MAXHOSTNAMELEN;
+
+/* options.max_startup sized array of fd ints */
+int *startup_pipes = NULL;
+int startup_pipe;              /* in child */
+
+/* variables used for privilege separation */
+int use_privsep = -1;
+struct monitor *pmonitor = NULL;
+
+/* global authentication context */
+Authctxt *the_authctxt = NULL;
+
+/* sshd_config buffer */
+Buffer cfg;
+
+/* message to be displayed after login */
+Buffer loginmsg;
+
+/* Unprivileged user */
+struct passwd *privsep_pw = NULL;
+
+/* Prototypes for various functions defined later in this file. */
+void destroy_sensitive_data(void);
+void demote_sensitive_data(void);
+
+static void do_ssh1_kex(void);
+static void do_ssh2_kex(void);
+
+/*
+ * Close all listening sockets
+ */
+static void
+close_listen_socks(void)
+{
+       int i;
+
+       for (i = 0; i < num_listen_socks; i++)
+               close(listen_socks[i]);
+       num_listen_socks = -1;
+}
+
+static void
+close_startup_pipes(void)
+{
+       int i;
+
+       if (startup_pipes)
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               close(startup_pipes[i]);
+}
+
+/*
+ * Signal handler for SIGHUP.  Sshd execs itself when it receives SIGHUP;
+ * the effect is to reread the configuration file (and to regenerate
+ * the server key).
+ */
+
+/*ARGSUSED*/
+static void
+sighup_handler(int sig)
+{
+       int save_errno = errno;
+
+       received_sighup = 1;
+       signal(SIGHUP, sighup_handler);
+       errno = save_errno;
+}
+
+/*
+ * Called from the main program after receiving SIGHUP.
+ * Restarts the server.
+ */
+static void
+sighup_restart(void)
+{
+       logit("Received SIGHUP; restarting.");
+       close_listen_socks();
+       close_startup_pipes();
+       alarm(0);  /* alarm timer persists across exec */
+       signal(SIGHUP, SIG_IGN); /* will be restored after exec */
+       execv(saved_argv[0], saved_argv);
+       logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
+           strerror(errno));
+       exit(1);
+}
+
+/*
+ * Generic signal handler for terminating signals in the master daemon.
+ */
+/*ARGSUSED*/
+static void
+sigterm_handler(int sig)
+{
+       received_sigterm = sig;
+}
+
+/*
+ * SIGCHLD handler.  This is called whenever a child dies.  This will then
+ * reap any zombies left by exited children.
+ */
+/*ARGSUSED*/
+static void
+main_sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+           (pid < 0 && errno == EINTR))
+               ;
+
+       signal(SIGCHLD, main_sigchld_handler);
+       errno = save_errno;
+}
+
+/*
+ * Signal handler for the alarm after the login grace period has expired.
+ */
+/*ARGSUSED*/
+static void
+grace_alarm_handler(int sig)
+{
+       if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
+               kill(pmonitor->m_pid, SIGALRM);
+
+       /* Log error and exit. */
+       sigdie("Timeout before authentication for %s", get_remote_ipaddr());
+}
+
+/*
+ * Signal handler for the key regeneration alarm.  Note that this
+ * alarm only occurs in the daemon waiting for connections, and it does not
+ * do anything with the private key or random state before forking.
+ * Thus there should be no concurrency control/asynchronous execution
+ * problems.
+ */
+static void
+generate_ephemeral_server_key(void)
+{
+       verbose("Generating %s%d bit RSA key.",
+           sensitive_data.server_key ? "new " : "", options.server_key_bits);
+       if (sensitive_data.server_key != NULL)
+               key_free(sensitive_data.server_key);
+       sensitive_data.server_key = key_generate(KEY_RSA1,
+           options.server_key_bits);
+       verbose("RSA key generation complete.");
+
+       arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+       arc4random_stir();
+}
+
+/*ARGSUSED*/
+static void
+key_regeneration_alarm(int sig)
+{
+       int save_errno = errno;
+
+       signal(SIGALRM, SIG_DFL);
+       errno = save_errno;
+       key_do_regen = 1;
+}
+
+static void
+sshd_exchange_identification(int sock_in, int sock_out)
+{
+       u_int i;
+       int mismatch;
+       int remote_major, remote_minor;
+       int major, minor;
+       char *s, *newline = "\n";
+       char buf[256];                  /* Must not be larger than remote_version. */
+       char remote_version[256];       /* Must be at least as big as buf. */
+
+       if ((options.protocol & SSH_PROTO_1) &&
+           (options.protocol & SSH_PROTO_2)) {
+               major = PROTOCOL_MAJOR_1;
+               minor = 99;
+       } else if (options.protocol & SSH_PROTO_2) {
+               major = PROTOCOL_MAJOR_2;
+               minor = PROTOCOL_MINOR_2;
+               newline = "\r\n";
+       } else {
+               major = PROTOCOL_MAJOR_1;
+               minor = PROTOCOL_MINOR_1;
+       }
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+           SSH_RELEASE, newline);
+       server_version_string = xstrdup(buf);
+
+       /* Send our protocol version identification. */
+       if (roaming_atomicio(vwrite, sock_out, server_version_string,
+           strlen(server_version_string))
+           != strlen(server_version_string)) {
+               logit("Could not write ident string to %s", get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+
+       /* Read other sides version identification. */
+       memset(buf, 0, sizeof(buf));
+       for (i = 0; i < sizeof(buf) - 1; i++) {
+               if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {
+                       logit("Did not receive identification string from %s",
+                           get_remote_ipaddr());
+                       cleanup_exit(255);
+               }
+               if (buf[i] == '\r') {
+                       buf[i] = 0;
+                       /* Kludge for F-Secure Macintosh < 1.0.2 */
+                       if (i == 12 &&
+                           strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
+                               break;
+                       continue;
+               }
+               if (buf[i] == '\n') {
+                       buf[i] = 0;
+                       break;
+               }
+       }
+       buf[sizeof(buf) - 1] = 0;
+       client_version_string = xstrdup(buf);
+
+       /*
+        * Check that the versions match.  In future this might accept
+        * several versions and set appropriate flags to handle them.
+        */
+       if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
+           &remote_major, &remote_minor, remote_version) != 3) {
+               s = "Protocol mismatch.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Bad protocol version identification '%.100s' from %s",
+                   client_version_string, get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+       debug("Client protocol version %d.%d; client software version %.100s",
+           remote_major, remote_minor, remote_version);
+
+       compat_datafellows(remote_version);
+
+       if (datafellows & SSH_BUG_PROBE) {
+               logit("probed from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       if (datafellows & SSH_BUG_SCANNER) {
+               logit("scanned from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       mismatch = 0;
+       switch (remote_major) {
+       case 1:
+               if (remote_minor == 99) {
+                       if (options.protocol & SSH_PROTO_2)
+                               enable_compat20();
+                       else
+                               mismatch = 1;
+                       break;
+               }
+               if (!(options.protocol & SSH_PROTO_1)) {
+                       mismatch = 1;
+                       break;
+               }
+               if (remote_minor < 3) {
+                       packet_disconnect("Your ssh version is too old and "
+                           "is no longer supported.  Please install a newer version.");
+               } else if (remote_minor == 3) {
+                       /* note that this disables agent-forwarding */
+                       enable_compat13();
+               }
+               break;
+       case 2:
+               if (options.protocol & SSH_PROTO_2) {
+                       enable_compat20();
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               mismatch = 1;
+               break;
+       }
+       chop(server_version_string);
+       debug("Local version string %.200s", server_version_string);
+
+       if (mismatch) {
+               s = "Protocol major versions differ.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Protocol major versions differ for %s: %.200s vs. %.200s",
+                   get_remote_ipaddr(),
+                   server_version_string, client_version_string);
+               cleanup_exit(255);
+       }
+}
+
+/* Destroy the host and server keys.  They will no longer be needed. */
+void
+destroy_sensitive_data(void)
+{
+       int i;
+
+       if (sensitive_data.server_key) {
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = NULL;
+       }
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = NULL;
+               }
+               if (sensitive_data.host_certificates[i]) {
+                       key_free(sensitive_data.host_certificates[i]);
+                       sensitive_data.host_certificates[i] = NULL;
+               }
+       }
+       sensitive_data.ssh1_host_key = NULL;
+       memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
+}
+
+/* Demote private to public keys for network child */
+void
+demote_sensitive_data(void)
+{
+       Key *tmp;
+       int i;
+
+       if (sensitive_data.server_key) {
+               tmp = key_demote(sensitive_data.server_key);
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = tmp;
+       }
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       tmp = key_demote(sensitive_data.host_keys[i]);
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = tmp;
+                       if (tmp->type == KEY_RSA1)
+                               sensitive_data.ssh1_host_key = tmp;
+               }
+               /* Certs do not need demotion */
+       }
+
+       /* We do not clear ssh1_host key and cookie.  XXX - Okay Niels? */
+}
+
+static void
+privsep_preauth_child(void)
+{
+       u_int32_t rnd[256];
+       gid_t gidset[1];
+
+       /* Enable challenge-response authentication for privilege separation */
+       privsep_challenge_enable();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       /* Change our root directory */
+       if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+               fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+                   strerror(errno));
+       if (chdir("/") == -1)
+               fatal("chdir(\"/\"): %s", strerror(errno));
+
+       /* Drop our privileges */
+       debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
+           (u_int)privsep_pw->pw_gid);
+#if 0
+       /* XXX not ready, too heavy after chroot */
+       do_setusercontext(privsep_pw);
+#else
+       gidset[0] = privsep_pw->pw_gid;
+       if (setgroups(1, gidset) < 0)
+               fatal("setgroups: %.100s", strerror(errno));
+       permanently_set_uid(privsep_pw);
+#endif
+}
+
+static int
+privsep_preauth(Authctxt *authctxt)
+{
+       int status;
+       pid_t pid;
+       struct ssh_sandbox *box = NULL;
+
+       /* Set up unprivileged child process to deal with network data */
+       pmonitor = monitor_init();
+       /* Store a pointer to the kex for later rekeying */
+       pmonitor->m_pkex = &xxx_kex;
+
+       if (use_privsep == PRIVSEP_SANDBOX)
+               box = ssh_sandbox_init();
+       pid = fork();
+       if (pid == -1) {
+               fatal("fork of unprivileged child failed");
+       } else if (pid != 0) {
+               debug2("Network child is on pid %ld", (long)pid);
+
+               if (box != NULL)
+                       ssh_sandbox_parent_preauth(box, pid);
+               pmonitor->m_pid = pid;
+               monitor_child_preauth(authctxt, pmonitor);
+
+               /* Sync memory */
+               monitor_sync(pmonitor);
+
+               /* Wait for the child's exit status */
+               while (waitpid(pid, &status, 0) < 0) {
+                       if (errno != EINTR)
+                               fatal("%s: waitpid: %s", __func__,
+                                   strerror(errno));
+               }
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status) != 0)
+                               fatal("%s: preauth child exited with status %d",
+                                   __func__, WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status))
+                       fatal("%s: preauth child terminated by signal %d",
+                           __func__, WTERMSIG(status));
+               if (box != NULL)
+                       ssh_sandbox_parent_finish(box);
+               return 1;
+       } else {
+               /* child */
+               close(pmonitor->m_sendfd);
+               close(pmonitor->m_log_recvfd);
+
+               /* Arrange for logging to be sent to the monitor */
+               set_log_handler(mm_log_handler, pmonitor);
+
+               /* Demote the child */
+               if (getuid() == 0 || geteuid() == 0)
+                       privsep_preauth_child();
+               setproctitle("%s", "[net]");
+               if (box != NULL)
+                       ssh_sandbox_child(box);
+
+               return 0;
+       }
+}
+
+static void
+privsep_postauth(Authctxt *authctxt)
+{
+       u_int32_t rnd[256];
+
+#ifdef DISABLE_FD_PASSING
+       if (1) {
+#else
+       if (authctxt->pw->pw_uid == 0 || options.use_login) {
+#endif
+               /* File descriptor passing is broken or root login */
+               use_privsep = 0;
+               goto skip;
+       }
+
+       /* New socket pair */
+       monitor_reinit(pmonitor);
+
+       pmonitor->m_pid = fork();
+       if (pmonitor->m_pid == -1)
+               fatal("fork of unprivileged child failed");
+       else if (pmonitor->m_pid != 0) {
+               verbose("User child is on pid %ld", (long)pmonitor->m_pid);
+               buffer_clear(&loginmsg);
+               monitor_child_postauth(pmonitor);
+
+               /* NEVERREACHED */
+               exit(0);
+       }
+
+       /* child */
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Drop privileges */
+       do_setusercontext(authctxt->pw, authctxt->role);
+
+ skip:
+       /* It is safe now to apply the key state */
+       monitor_apply_keystate(pmonitor);
+
+       /*
+        * Tell the packet layer that authentication was successful, since
+        * this information is not part of the key state.
+        */
+       packet_set_authenticated();
+}
+
+static char *
+list_hostkey_types(void)
+{
+       Buffer b;
+       const char *p;
+       char *ret;
+       int i;
+       Key *key;
+
+       buffer_init(&b);
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = sensitive_data.host_keys[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+               /* If the private key has a cert peer, then list that too */
+               key = sensitive_data.host_certificates[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       ret = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       debug("list_hostkey_types: %s", ret);
+       return ret;
+}
+
+static Key *
+get_hostkey_by_type(int type, int need_private)
+{
+       int i;
+       Key *key;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               switch (type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       key = sensitive_data.host_certificates[i];
+                       break;
+               default:
+                       key = sensitive_data.host_keys[i];
+                       break;
+               }
+               if (key != NULL && key->type == type)
+                       return need_private ?
+                           sensitive_data.host_keys[i] : key;
+       }
+       return NULL;
+}
+
+Key *
+get_hostkey_public_by_type(int type)
+{
+       return get_hostkey_by_type(type, 0);
+}
+
+Key *
+get_hostkey_private_by_type(int type)
+{
+       return get_hostkey_by_type(type, 1);
+}
+
+Key *
+get_hostkey_by_index(int ind)
+{
+       if (ind < 0 || ind >= options.num_host_key_files)
+               return (NULL);
+       return (sensitive_data.host_keys[ind]);
+}
+
+int
+get_hostkey_index(Key *key)
+{
+       int i;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (key_is_cert(key)) {
+                       if (key == sensitive_data.host_certificates[i])
+                               return (i);
+               } else {
+                       if (key == sensitive_data.host_keys[i])
+                               return (i);
+               }
+       }
+       return (-1);
+}
+
+/*
+ * returns 1 if connection should be dropped, 0 otherwise.
+ * dropping starts at connection #max_startups_begin with a probability
+ * of (max_startups_rate/100). the probability increases linearly until
+ * all connections are dropped for startups > max_startups
+ */
+static int
+drop_connection(int startups)
+{
+       int p, r;
+
+       if (startups < options.max_startups_begin)
+               return 0;
+       if (startups >= options.max_startups)
+               return 1;
+       if (options.max_startups_rate == 100)
+               return 1;
+
+       p  = 100 - options.max_startups_rate;
+       p *= startups - options.max_startups_begin;
+       p /= options.max_startups - options.max_startups_begin;
+       p += options.max_startups_rate;
+       r = arc4random_uniform(100);
+
+       debug("drop_connection: p %d, r %d", p, r);
+       return (r < p) ? 1 : 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "%s, %s\n",
+           SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+       fprintf(stderr,
+"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
+"            [-f config_file] [-g login_grace_time] [-h host_key_file]\n"
+"            [-k key_gen_time] [-o option] [-p port] [-u len]\n"
+       );
+       exit(1);
+}
+
+static void
+send_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+
+       debug3("%s: entering fd = %d config len %d", __func__, fd,
+           buffer_len(conf));
+
+       /*
+        * Protocol from reexec master to child:
+        *      string  configuration
+        *      u_int   ephemeral_key_follows
+        *      bignum  e               (only if ephemeral_key_follows == 1)
+        *      bignum  n                       "
+        *      bignum  d                       "
+        *      bignum  iqmp                    "
+        *      bignum  p                       "
+        *      bignum  q                       "
+        *      string rngseed          (only if OpenSSL is not self-seeded)
+        */
+       buffer_init(&m);
+       buffer_put_cstring(&m, buffer_ptr(conf));
+
+       if (sensitive_data.server_key != NULL &&
+           sensitive_data.server_key->type == KEY_RSA1) {
+               buffer_put_int(&m, 1);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
+       } else
+               buffer_put_int(&m, 0);
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_send_rng_seed(&m);
+#endif
+
+       if (ssh_msg_send(fd, 0, &m) == -1)
+               fatal("%s: ssh_msg_send failed", __func__);
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+static void
+recv_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+       char *cp;
+       u_int len;
+
+       debug3("%s: entering fd = %d", __func__, fd);
+
+       buffer_init(&m);
+
+       if (ssh_msg_recv(fd, &m) == -1)
+               fatal("%s: ssh_msg_recv failed", __func__);
+       if (buffer_get_char(&m) != 0)
+               fatal("%s: rexec version mismatch", __func__);
+
+       cp = buffer_get_string(&m, &len);
+       if (conf != NULL)
+               buffer_append(conf, cp, len + 1);
+       xfree(cp);
+
+       if (buffer_get_int(&m)) {
+               if (sensitive_data.server_key != NULL)
+                       key_free(sensitive_data.server_key);
+               sensitive_data.server_key = key_new_private(KEY_RSA1);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
+               rsa_generate_additional_parameters(
+                   sensitive_data.server_key->rsa);
+       }
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_recv_rng_seed(&m);
+#endif
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+/* Accept a connection from inetd */
+static void
+server_accept_inetd(int *sock_in, int *sock_out)
+{
+       int fd;
+
+       startup_pipe = -1;
+       if (rexeced_flag) {
+               close(REEXEC_CONFIG_PASS_FD);
+               *sock_in = *sock_out = dup(STDIN_FILENO);
+               if (!debug_flag) {
+                       startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+                       close(REEXEC_STARTUP_PIPE_FD);
+               }
+       } else {
+               *sock_in = dup(STDIN_FILENO);
+               *sock_out = dup(STDOUT_FILENO);
+       }
+       /*
+        * We intentionally do not close the descriptors 0, 1, and 2
+        * as our code for setting the descriptors won't work if
+        * ttyfd happens to be one of those.
+        */
+       if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+               dup2(fd, STDIN_FILENO);
+               dup2(fd, STDOUT_FILENO);
+               if (fd > STDOUT_FILENO)
+                       close(fd);
+       }
+       debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
+}
+
+/*
+ * Listen for TCP connections
+ */
+static void
+server_listen(void)
+{
+       int ret, listen_sock, on = 1;
+       struct addrinfo *ai;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+
+       for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                       continue;
+               if (num_listen_socks >= MAX_LISTEN_SOCKS)
+                       fatal("Too many listen sockets. "
+                           "Enlarge MAX_LISTEN_SOCKS");
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                   ntop, sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           ssh_gai_strerror(ret));
+                       continue;
+               }
+               /* Create socket for listening. */
+               listen_sock = socket(ai->ai_family, ai->ai_socktype,
+                   ai->ai_protocol);
+               if (listen_sock < 0) {
+                       /* kernel may not support ipv6 */
+                       verbose("socket: %.100s", strerror(errno));
+                       continue;
+               }
+               if (set_nonblock(listen_sock) == -1) {
+                       close(listen_sock);
+                       continue;
+               }
+               /*
+                * Set socket options.
+                * Allow local port reuse in TIME_WAIT.
+                */
+               if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
+                   &on, sizeof(on)) == -1)
+                       error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+
+               /* Only communicate in IPv6 over AF_INET6 sockets. */
+               if (ai->ai_family == AF_INET6)
+                       sock_set_v6only(listen_sock);
+
+               debug("Bind to port %s on %s.", strport, ntop);
+
+               /* Bind the socket to the desired port. */
+               if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       error("Bind to port %s on %s failed: %.200s.",
+                           strport, ntop, strerror(errno));
+                       close(listen_sock);
+                       continue;
+               }
+               listen_socks[num_listen_socks] = listen_sock;
+               num_listen_socks++;
+
+               /* Start listening on the port. */
+               if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
+                       fatal("listen on [%s]:%s: %.100s",
+                           ntop, strport, strerror(errno));
+               logit("Server listening on %s port %s.", ntop, strport);
+       }
+       freeaddrinfo(options.listen_addrs);
+
+       if (!num_listen_socks)
+               fatal("Cannot bind any address.");
+}
+
+/*
+ * The main TCP accept loop. Note that, for the non-debug case, returns
+ * from this function are in a forked subprocess.
+ */
+static void
+server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
+{
+       fd_set *fdset;
+       int i, j, ret, maxfd;
+       int key_used = 0, startups = 0;
+       int startup_p[2] = { -1 , -1 };
+       struct sockaddr_storage from;
+       socklen_t fromlen;
+       pid_t pid;
+
+       /* setup fd set for accept */
+       fdset = NULL;
+       maxfd = 0;
+       for (i = 0; i < num_listen_socks; i++)
+               if (listen_socks[i] > maxfd)
+                       maxfd = listen_socks[i];
+       /* pipes connected to unauthenticated childs */
+       startup_pipes = xcalloc(options.max_startups, sizeof(int));
+       for (i = 0; i < options.max_startups; i++)
+               startup_pipes[i] = -1;
+
+       /*
+        * Stay listening for connections until the system crashes or
+        * the daemon is killed with a signal.
+        */
+       for (;;) {
+               if (received_sighup)
+                       sighup_restart();
+               if (fdset != NULL)
+                       xfree(fdset);
+               fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),
+                   sizeof(fd_mask));
+
+               for (i = 0; i < num_listen_socks; i++)
+                       FD_SET(listen_socks[i], fdset);
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               FD_SET(startup_pipes[i], fdset);
+
+               /* Wait in select until there is a connection. */
+               ret = select(maxfd+1, fdset, NULL, NULL, NULL);
+               if (ret < 0 && errno != EINTR)
+                       error("select: %.100s", strerror(errno));
+               if (received_sigterm) {
+                       logit("Received signal %d; terminating.",
+                           (int) received_sigterm);
+                       close_listen_socks();
+                       unlink(options.pid_file);
+                       exit(received_sigterm == SIGTERM ? 0 : 255);
+               }
+               if (key_used && key_do_regen) {
+                       generate_ephemeral_server_key();
+                       key_used = 0;
+                       key_do_regen = 0;
+               }
+               if (ret < 0)
+                       continue;
+
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1 &&
+                           FD_ISSET(startup_pipes[i], fdset)) {
+                               /*
+                                * the read end of the pipe is ready
+                                * if the child has closed the pipe
+                                * after successful authentication
+                                * or if the child has died
+                                */
+                               close(startup_pipes[i]);
+                               startup_pipes[i] = -1;
+                               startups--;
+                       }
+               for (i = 0; i < num_listen_socks; i++) {
+                       if (!FD_ISSET(listen_socks[i], fdset))
+                               continue;
+                       fromlen = sizeof(from);
+                       *newsock = accept(listen_socks[i],
+                           (struct sockaddr *)&from, &fromlen);
+                       if (*newsock < 0) {
+                               if (errno != EINTR && errno != EAGAIN &&
+                                   errno != EWOULDBLOCK)
+                                       error("accept: %.100s", strerror(errno));
+                               continue;
+                       }
+                       if (unset_nonblock(*newsock) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+                       if (drop_connection(startups) == 1) {
+                               debug("drop connection #%d", startups);
+                               close(*newsock);
+                               continue;
+                       }
+                       if (pipe(startup_p) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+
+                       if (rexec_flag && socketpair(AF_UNIX,
+                           SOCK_STREAM, 0, config_s) == -1) {
+                               error("reexec socketpair: %s",
+                                   strerror(errno));
+                               close(*newsock);
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               continue;
+                       }
+
+                       for (j = 0; j < options.max_startups; j++)
+                               if (startup_pipes[j] == -1) {
+                                       startup_pipes[j] = startup_p[0];
+                                       if (maxfd < startup_p[0])
+                                               maxfd = startup_p[0];
+                                       startups++;
+                                       break;
+                               }
+
+                       /*
+                        * Got connection.  Fork a child to handle it, unless
+                        * we are in debugging mode.
+                        */
+                       if (debug_flag) {
+                               /*
+                                * In debugging mode.  Close the listening
+                                * socket, and start processing the
+                                * connection without forking.
+                                */
+                               debug("Server will not fork when running in debugging mode.");
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               startup_pipe = -1;
+                               pid = getpid();
+                               if (rexec_flag) {
+                                       send_rexec_state(config_s[0],
+                                           &cfg);
+                                       close(config_s[0]);
+                               }
+                               break;
+                       }
+
+                       /*
+                        * Normal production daemon.  Fork, and have
+                        * the child process the connection. The
+                        * parent continues listening.
+                        */
+                       platform_pre_fork();
+                       if ((pid = fork()) == 0) {
+                               /*
+                                * Child.  Close the listening and
+                                * max_startup sockets.  Start using
+                                * the accepted socket. Reinitialize
+                                * logging (since our pid has changed).
+                                * We break out of the loop to handle
+                                * the connection.
+                                */
+                               platform_post_fork_child();
+                               startup_pipe = startup_p[1];
+                               close_startup_pipes();
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               log_init(__progname,
+                                   options.log_level,
+                                   options.log_facility,
+                                   log_stderr);
+                               if (rexec_flag)
+                                       close(config_s[0]);
+                               break;
+                       }
+
+                       /* Parent.  Stay in the loop. */
+                       platform_post_fork_parent(pid);
+                       if (pid < 0)
+                               error("fork: %.100s", strerror(errno));
+                       else
+                               debug("Forked child %ld.", (long)pid);
+
+                       close(startup_p[1]);
+
+                       if (rexec_flag) {
+                               send_rexec_state(config_s[0], &cfg);
+                               close(config_s[0]);
+                               close(config_s[1]);
+                       }
+
+                       /*
+                        * Mark that the key has been used (it
+                        * was "given" to the child).
+                        */
+                       if ((options.protocol & SSH_PROTO_1) &&
+                           key_used == 0) {
+                               /* Schedule server key regeneration alarm. */
+                               signal(SIGALRM, key_regeneration_alarm);
+                               alarm(options.key_regeneration_time);
+                               key_used = 1;
+                       }
+
+                       close(*newsock);
+
+                       /*
+                        * Ensure that our random state differs
+                        * from that of the child
+                        */
+                       arc4random_stir();
+               }
+
+               /* child process check (or debug mode) */
+               if (num_listen_socks < 0)
+                       break;
+       }
+}
+
+
+/*
+ * Main program for the daemon.
+ */
+int
+main(int ac, char **av)
+{
+       extern char *optarg;
+       extern int optind;
+       int opt, i, j, on = 1;
+       int sock_in = -1, sock_out = -1, newsock = -1;
+       const char *remote_ip;
+       char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
+       int remote_port;
+       char *line, *p, *cp;
+       int config_s[2] = { -1 , -1 };
+       u_int64_t ibytes, obytes;
+       mode_t new_umask;
+       Key *key;
+       Authctxt *authctxt;
+
+#ifdef HAVE_SECUREWARE
+       (void)set_auth_parameters(ac, av);
+#endif
+       __progname = ssh_get_progname(av[0]);
+
+       /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
+       saved_argc = ac;
+       rexec_argc = ac;
+       saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
+       for (i = 0; i < ac; i++)
+               saved_argv[i] = xstrdup(av[i]);
+       saved_argv[i] = NULL;
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       compat_init_setproctitle(ac, av);
+       av = saved_argv;
+#endif
+
+       if (geteuid() == 0 && setgroups(0, NULL) == -1)
+               debug("setgroups(): %.200s", strerror(errno));
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       /* Initialize configuration options to their default values. */
+       initialize_server_options(&options);
+
+       /* Parse command-line arguments. */
+       while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) {
+               switch (opt) {
+               case '4':
+                       options.address_family = AF_INET;
+                       break;
+               case '6':
+                       options.address_family = AF_INET6;
+                       break;
+               case 'f':
+                       config_file_name = optarg;
+                       break;
+               case 'c':
+                       if (options.num_host_cert_files >= MAX_HOSTCERTS) {
+                               fprintf(stderr, "too many host certificates.\n");
+                               exit(1);
+                       }
+                       options.host_cert_files[options.num_host_cert_files++] =
+                          derelativise_path(optarg);
+                       break;
+               case 'd':
+                       if (debug_flag == 0) {
+                               debug_flag = 1;
+                               options.log_level = SYSLOG_LEVEL_DEBUG1;
+                       } else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                               options.log_level++;
+                       break;
+               case 'D':
+                       no_daemon_flag = 1;
+                       break;
+               case 'e':
+                       log_stderr = 1;
+                       break;
+               case 'i':
+                       inetd_flag = 1;
+                       break;
+               case 'r':
+                       rexec_flag = 0;
+                       break;
+               case 'R':
+                       rexeced_flag = 1;
+                       inetd_flag = 1;
+                       break;
+               case 'Q':
+                       /* ignored */
+                       break;
+               case 'q':
+                       options.log_level = SYSLOG_LEVEL_QUIET;
+                       break;
+               case 'b':
+                       options.server_key_bits = (int)strtonum(optarg, 256,
+                           32768, NULL);
+                       break;
+               case 'p':
+                       options.ports_from_cmdline = 1;
+                       if (options.num_ports >= MAX_PORTS) {
+                               fprintf(stderr, "too many ports.\n");
+                               exit(1);
+                       }
+                       options.ports[options.num_ports++] = a2port(optarg);
+                       if (options.ports[options.num_ports-1] <= 0) {
+                               fprintf(stderr, "Bad port number.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'g':
+                       if ((options.login_grace_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid login grace time.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'k':
+                       if ((options.key_regeneration_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid key regeneration interval.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'h':
+                       if (options.num_host_key_files >= MAX_HOSTKEYS) {
+                               fprintf(stderr, "too many host keys.\n");
+                               exit(1);
+                       }
+                       options.host_key_files[options.num_host_key_files++] = 
+                          derelativise_path(optarg);
+                       break;
+               case 't':
+                       test_flag = 1;
+                       break;
+               case 'T':
+                       test_flag = 2;
+                       break;
+               case 'C':
+                       cp = optarg;
+                       while ((p = strsep(&cp, ",")) && *p != '\0') {
+                               if (strncmp(p, "addr=", 5) == 0)
+                                       test_addr = xstrdup(p + 5);
+                               else if (strncmp(p, "host=", 5) == 0)
+                                       test_host = xstrdup(p + 5);
+                               else if (strncmp(p, "user=", 5) == 0)
+                                       test_user = xstrdup(p + 5);
+                               else {
+                                       fprintf(stderr, "Invalid test "
+                                           "mode specification %s\n", p);
+                                       exit(1);
+                               }
+                       }
+                       break;
+               case 'u':
+                       utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
+                       if (utmp_len > MAXHOSTNAMELEN) {
+                               fprintf(stderr, "Invalid utmp length.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'o':
+                       line = xstrdup(optarg);
+                       if (process_server_config_line(&options, line,
+                           "command-line", 0, NULL, NULL, NULL, NULL) != 0)
+                               exit(1);
+                       xfree(line);
+                       break;
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+       }
+       if (rexeced_flag || inetd_flag)
+               rexec_flag = 0;
+       if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
+               fatal("sshd re-exec requires execution with an absolute path");
+       if (rexeced_flag)
+               closefrom(REEXEC_MIN_FREE_FD);
+       else
+               closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
+
+       OpenSSL_add_all_algorithms();
+
+       /*
+        * Force logging to stderr until we have loaded the private host
+        * key (unless started from inetd)
+        */
+       log_init(__progname,
+           options.log_level == SYSLOG_LEVEL_NOT_SET ?
+           SYSLOG_LEVEL_INFO : options.log_level,
+           options.log_facility == SYSLOG_FACILITY_NOT_SET ?
+           SYSLOG_FACILITY_AUTH : options.log_facility,
+           log_stderr || !inetd_flag);
+
+       /*
+        * Unset KRB5CCNAME, otherwise the user's session may inherit it from
+        * root's environment
+        */
+       if (getenv("KRB5CCNAME") != NULL)
+               unsetenv("KRB5CCNAME");
+
+#ifdef _UNICOS
+       /* Cray can define user privs drop all privs now!
+        * Not needed on PRIV_SU systems!
+        */
+       drop_cray_privs();
+#endif
+
+       sensitive_data.server_key = NULL;
+       sensitive_data.ssh1_host_key = NULL;
+       sensitive_data.have_ssh1_key = 0;
+       sensitive_data.have_ssh2_key = 0;
+
+       /*
+        * If we're doing an extended config test, make sure we have all of
+        * the parameters we need.  If we're not doing an extended test,
+        * do not silently ignore connection test params.
+        */
+       if (test_flag >= 2 &&
+          (test_user != NULL || test_host != NULL || test_addr != NULL)
+           && (test_user == NULL || test_host == NULL || test_addr == NULL))
+               fatal("user, host and addr are all required when testing "
+                  "Match configs");
+       if (test_flag < 2 && (test_user != NULL || test_host != NULL ||
+           test_addr != NULL))
+               fatal("Config test connection parameter (-C) provided without "
+                  "test mode (-T)");
+
+       /* Fetch our configuration */
+       buffer_init(&cfg);
+       if (rexeced_flag)
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
+       else
+               load_server_config(config_file_name, &cfg);
+
+       parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
+           &cfg, NULL, NULL, NULL);
+
+       seed_rng();
+
+       /* Fill in default values for those options not explicitly set. */
+       fill_default_server_options(&options);
+
+       /* challenge-response is implemented via keyboard interactive */
+       if (options.challenge_response_authentication)
+               options.kbd_interactive_authentication = 1;
+
+       /* set default channel AF */
+       channel_set_af(options.address_family);
+
+       /* Check that there are no remaining arguments. */
+       if (optind < ac) {
+               fprintf(stderr, "Extra argument %s.\n", av[optind]);
+               exit(1);
+       }
+
+       debug("sshd version %.100s", SSH_RELEASE);
+
+       /* Store privilege separation user for later use if required. */
+       if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
+               if (use_privsep || options.kerberos_authentication)
+                       fatal("Privilege separation user %s does not exist",
+                           SSH_PRIVSEP_USER);
+       } else {
+               memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd));
+               privsep_pw = pwcopy(privsep_pw);
+               xfree(privsep_pw->pw_passwd);
+               privsep_pw->pw_passwd = xstrdup("*");
+       }
+       endpwent();
+
+       /* load private host keys */
+       sensitive_data.host_keys = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_keys[i] = NULL;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = key_load_private(options.host_key_files[i], "", NULL);
+               sensitive_data.host_keys[i] = key;
+               if (key == NULL) {
+                       error("Could not load host key: %s",
+                           options.host_key_files[i]);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
+               if (auth_key_is_revoked(key, 1)) {
+                       key_free(key);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
+               switch (key->type) {
+               case KEY_RSA1:
+                       sensitive_data.ssh1_host_key = key;
+                       sensitive_data.have_ssh1_key = 1;
+                       break;
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       sensitive_data.have_ssh2_key = 1;
+                       break;
+               }
+               debug("private host key: #%d type %d %s", i, key->type,
+                   key_type(key));
+       }
+       if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
+               logit("Disabling protocol version 1. Could not load host key");
+               options.protocol &= ~SSH_PROTO_1;
+       }
+#ifndef GSSAPI
+       /* The GSSAPI key exchange can run without a host key */
+       if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
+               logit("Disabling protocol version 2. Could not load host key");
+               options.protocol &= ~SSH_PROTO_2;
+       }
+#endif
+       if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+               logit("sshd: no hostkeys available -- exiting.");
+               exit(1);
+       }
+
+       /*
+        * Load certificates. They are stored in an array at identical
+        * indices to the public keys that they relate to.
+        */
+       sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_certificates[i] = NULL;
+
+       for (i = 0; i < options.num_host_cert_files; i++) {
+               key = key_load_public(options.host_cert_files[i], NULL);
+               if (key == NULL) {
+                       error("Could not load host certificate: %s",
+                           options.host_cert_files[i]);
+                       continue;
+               }
+               if (!key_is_cert(key)) {
+                       error("Certificate file is not a certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               /* Find matching private key */
+               for (j = 0; j < options.num_host_key_files; j++) {
+                       if (key_equal_public(key,
+                           sensitive_data.host_keys[j])) {
+                               sensitive_data.host_certificates[j] = key;
+                               break;
+                       }
+               }
+               if (j >= options.num_host_key_files) {
+                       error("No matching private key for certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               sensitive_data.host_certificates[j] = key;
+               debug("host certificate: #%d type %d %s", j, key->type,
+                   key_type(key));
+       }
+       /* Check certain values for sanity. */
+       if (options.protocol & SSH_PROTO_1) {
+               if (options.server_key_bits < 512 ||
+                   options.server_key_bits > 32768) {
+                       fprintf(stderr, "Bad server key size.\n");
+                       exit(1);
+               }
+               /*
+                * Check that server and host key lengths differ sufficiently. This
+                * is necessary to make double encryption work with rsaref. Oh, I
+                * hate software patents. I dont know if this can go? Niels
+                */
+               if (options.server_key_bits >
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -
+                   SSH_KEY_BITS_RESERVED && options.server_key_bits <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       options.server_key_bits =
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                           SSH_KEY_BITS_RESERVED;
+                       debug("Forcing server key to %d bits to make it differ from host key.",
+                           options.server_key_bits);
+               }
+       }
+
+       if (use_privsep) {
+               struct stat st;
+
+               if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
+                   (S_ISDIR(st.st_mode) == 0))
+                       fatal("Missing privilege separation directory: %s",
+                           _PATH_PRIVSEP_CHROOT_DIR);
+
+#ifdef HAVE_CYGWIN
+               if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) &&
+                   (st.st_uid != getuid () ||
+                   (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
+#else
+               if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
+#endif
+                       fatal("%s must be owned by root and not group or "
+                           "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
+       }
+
+       if (test_flag > 1) {
+               if (test_user != NULL && test_addr != NULL && test_host != NULL)
+                       parse_server_match_config(&options, test_user,
+                           test_host, test_addr);
+               dump_config(&options);
+       }
+
+       /* Configuration looks good, so exit if in test mode. */
+       if (test_flag)
+               exit(0);
+
+       /*
+        * Clear out any supplemental groups we may have inherited.  This
+        * prevents inadvertent creation of files with bad modes (in the
+        * portable version at least, it's certainly possible for PAM
+        * to create a file, and we can't control the code in every
+        * module which might be used).
+        */
+       if (setgroups(0, NULL) < 0)
+               debug("setgroups() failed: %.200s", strerror(errno));
+
+       if (rexec_flag) {
+               rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *));
+               for (i = 0; i < rexec_argc; i++) {
+                       debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
+                       rexec_argv[i] = saved_argv[i];
+               }
+               rexec_argv[rexec_argc] = "-R";
+               rexec_argv[rexec_argc + 1] = NULL;
+       }
+
+       /* Ensure that umask disallows at least group and world write */
+       new_umask = umask(0077) | 0022;
+       (void) umask(new_umask);
+
+       /* Initialize the log (it is reinitialized below in case we forked). */
+       if (debug_flag && (!inetd_flag || rexeced_flag))
+               log_stderr = 1;
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /*
+        * If not in debugging mode, and not started from inetd, disconnect
+        * from the controlling terminal, and fork.  The original process
+        * exits.
+        */
+       if (!(debug_flag || inetd_flag || no_daemon_flag)) {
+#ifdef TIOCNOTTY
+               int fd;
+#endif /* TIOCNOTTY */
+               if (daemon(0, 0) < 0)
+                       fatal("daemon() failed: %.200s", strerror(errno));
+
+               /* Disconnect from the controlling tty. */
+#ifdef TIOCNOTTY
+               fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
+               if (fd >= 0) {
+                       (void) ioctl(fd, TIOCNOTTY, NULL);
+                       close(fd);
+               }
+#endif /* TIOCNOTTY */
+       }
+       /* Reinitialize the log (because of the fork above). */
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /* Initialize the random number generator. */
+       arc4random_stir();
+
+       /* Chdir to the root directory so that the current disk can be
+          unmounted if desired. */
+       chdir("/");
+
+       /* ignore SIGPIPE */
+       signal(SIGPIPE, SIG_IGN);
+
+       /* Get a connection, either from inetd or a listening TCP socket */
+       if (inetd_flag) {
+               server_accept_inetd(&sock_in, &sock_out);
+       } else {
+               platform_pre_listen();
+               server_listen();
+
+               if (options.protocol & SSH_PROTO_1)
+                       generate_ephemeral_server_key();
+
+               signal(SIGHUP, sighup_handler);
+               signal(SIGCHLD, main_sigchld_handler);
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+
+               /*
+                * Write out the pid file after the sigterm handler
+                * is setup and the listen sockets are bound
+                */
+               if (!debug_flag) {
+                       FILE *f = fopen(options.pid_file, "w");
+
+                       if (f == NULL) {
+                               error("Couldn't create pid file \"%s\": %s",
+                                   options.pid_file, strerror(errno));
+                       } else {
+                               fprintf(f, "%ld\n", (long) getpid());
+                               fclose(f);
+                       }
+               }
+
+               /* Accept a connection and return in a forked child */
+               server_accept_loop(&sock_in, &sock_out,
+                   &newsock, config_s);
+       }
+
+       /* This is the child processing a new connection. */
+       setproctitle("%s", "[accepted]");
+
+       /*
+        * Create a new session and process group since the 4.4BSD
+        * setlogin() affects the entire process group.  We don't
+        * want the child to be able to affect the parent.
+        */
+#if !defined(SSHD_ACQUIRES_CTTY)
+       /*
+        * If setsid is called, on some platforms sshd will later acquire a
+        * controlling terminal which will result in "could not set
+        * controlling tty" errors.
+        */
+       if (!debug_flag && !inetd_flag && setsid() < 0)
+               error("setsid: %.100s", strerror(errno));
+#endif
+
+       if (rexec_flag) {
+               int fd;
+
+               debug("rexec start in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+               dup2(newsock, STDIN_FILENO);
+               dup2(STDIN_FILENO, STDOUT_FILENO);
+               if (startup_pipe == -1)
+                       close(REEXEC_STARTUP_PIPE_FD);
+               else
+                       dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
+
+               dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
+               close(config_s[1]);
+               if (startup_pipe != -1)
+                       close(startup_pipe);
+
+               execv(rexec_argv[0], rexec_argv);
+
+               /* Reexec has failed, fall back and continue */
+               error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
+
+               /* Clean up fds */
+               startup_pipe = REEXEC_STARTUP_PIPE_FD;
+               close(config_s[1]);
+               close(REEXEC_CONFIG_PASS_FD);
+               newsock = sock_out = sock_in = dup(STDIN_FILENO);
+               if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       if (fd > STDERR_FILENO)
+                               close(fd);
+               }
+               debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+       }
+
+       /* Executed child processes don't need these. */
+       fcntl(sock_out, F_SETFD, FD_CLOEXEC);
+       fcntl(sock_in, F_SETFD, FD_CLOEXEC);
+
+       /*
+        * Disable the key regeneration alarm.  We will not regenerate the
+        * key since we are no longer in a position to give it to anyone. We
+        * will not restart on SIGHUP since it no longer makes sense.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGQUIT, SIG_DFL);
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGINT, SIG_DFL);
+
+       /*
+        * Register our connection.  This turns encryption off because we do
+        * not have a key.
+        */
+       packet_set_connection(sock_in, sock_out);
+       packet_set_server();
+
+       /* Set SO_KEEPALIVE if requested. */
+       if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
+           setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
+       if ((remote_port = get_remote_port()) < 0) {
+               debug("get_remote_port failed");
+               cleanup_exit(255);
+       }
+
+       /*
+        * We use get_canonical_hostname with usedns = 0 instead of
+        * get_remote_ipaddr here so IP options will be checked.
+        */
+       (void) get_canonical_hostname(0);
+       /*
+        * The rest of the code depends on the fact that
+        * get_remote_ipaddr() caches the remote ip, even if
+        * the socket goes away.
+        */
+       remote_ip = get_remote_ipaddr();
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_connection_from(remote_ip, remote_port);
+#endif
+#ifdef LIBWRAP
+       allow_severity = options.log_facility|LOG_INFO;
+       deny_severity = options.log_facility|LOG_WARNING;
+       /* Check whether logins are denied from this host. */
+       if (packet_connection_is_on_socket()) {
+               struct request_info req;
+
+               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
+               fromhost(&req);
+
+               if (!hosts_access(&req)) {
+                       debug("Connection refused by tcp wrapper");
+                       refuse(&req);
+                       /* NOTREACHED */
+                       fatal("libwrap refuse returns");
+               }
+       }
+#endif /* LIBWRAP */
+
+       /* Log the connection. */
+       verbose("Connection from %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_SECURITY_SESSION_API
+       /*
+        * Create a new security session for use by the new user login if
+        * the current session is the root session or we are not launched
+        * by inetd (eg: debugging mode or server mode).  We do not
+        * necessarily need to create a session if we are launched from
+        * inetd because Panther xinetd will create a session for us.
+        *
+        * The only case where this logic will fail is if there is an
+        * inetd running in a non-root session which is not creating
+        * new sessions for us.  Then all the users will end up in the
+        * same session (bad).
+        *
+        * When the client exits, the session will be destroyed for us
+        * automatically.
+        *
+        * We must create the session before any credentials are stored
+        * (including AFS pags, which happens a few lines below).
+        */
+       {
+               OSStatus err = 0;
+               SecuritySessionId sid = 0;
+               SessionAttributeBits sattrs = 0;
+
+               err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+               if (err)
+                       error("SessionGetInfo() failed with error %.8X",
+                           (unsigned) err);
+               else
+                       debug("Current Session ID is %.8X / Session Attributes are %.8X",
+                           (unsigned) sid, (unsigned) sattrs);
+
+               if (inetd_flag && !(sattrs & sessionIsRoot))
+                       debug("Running in inetd mode in a non-root session... "
+                           "assuming inetd created the session for us.");
+               else {
+                       debug("Creating new security session...");
+                       err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+                       if (err)
+                               error("SessionCreate() failed with error %.8X",
+                                   (unsigned) err);
+
+                       err = SessionGetInfo(callerSecuritySession, &sid, 
+                           &sattrs);
+                       if (err)
+                               error("SessionGetInfo() failed with error %.8X",
+                                   (unsigned) err);
+                       else
+                               debug("New Session ID is %.8X / Session Attributes are %.8X",
+                                   (unsigned) sid, (unsigned) sattrs);
+               }
+       }
+#endif
+
+       /*
+        * We don't want to listen forever unless the other side
+        * successfully authenticates itself.  So we set up an alarm which is
+        * cleared after successful authentication.  A limit of zero
+        * indicates no limit. Note that we don't set the alarm in debugging
+        * mode; it is just annoying to have the server exit just when you
+        * are about to discover the bug.
+        */
+       signal(SIGALRM, grace_alarm_handler);
+       if (!debug_flag)
+               alarm(options.login_grace_time);
+
+       sshd_exchange_identification(sock_in, sock_out);
+
+       /* In inetd mode, generate ephemeral key only for proto 1 connections */
+       if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
+               generate_ephemeral_server_key();
+
+       packet_set_nonblocking();
+
+       /* allocate authentication context */
+       authctxt = xcalloc(1, sizeof(*authctxt));
+
+       authctxt->loginmsg = &loginmsg;
+
+       /* XXX global for cleanup, access from other modules */
+       the_authctxt = authctxt;
+
+       /* prepare buffer to collect messages to display to user after login */
+       buffer_init(&loginmsg);
+       auth_debug_reset();
+
+       if (use_privsep)
+               if (privsep_preauth(authctxt) == 1)
+                       goto authenticated;
+
+       /* perform the key exchange */
+       /* authenticate user and start session */
+       if (compat20) {
+               do_ssh2_kex();
+               do_authentication2(authctxt);
+       } else {
+               do_ssh1_kex();
+               do_authentication(authctxt);
+       }
+       /*
+        * If we use privilege separation, the unprivileged child transfers
+        * the current keystate and exits
+        */
+       if (use_privsep) {
+               mm_send_keystate(pmonitor);
+               exit(0);
+       }
+
+ authenticated:
+       /*
+        * Cancel the alarm we set to limit the time taken for
+        * authentication.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       authctxt->authenticated = 1;
+       if (startup_pipe != -1) {
+               close(startup_pipe);
+               startup_pipe = -1;
+       }
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_event(SSH_AUTH_SUCCESS);
+#endif
+
+#ifdef GSSAPI
+       if (options.gss_authentication) {
+               temporarily_use_uid(authctxt->pw);
+               ssh_gssapi_storecreds();
+               restore_uid();
+       }
+#endif
+#ifdef USE_PAM
+       if (options.use_pam) {
+               do_pam_setcred(1);
+               do_pam_session();
+       }
+#endif
+
+       /*
+        * In privilege separation, we fork another child and prepare
+        * file descriptor passing.
+        */
+       if (use_privsep) {
+               privsep_postauth(authctxt);
+               /* the monitor process [priv] will not return */
+               if (!compat20)
+                       destroy_sensitive_data();
+       }
+
+       packet_set_timeout(options.client_alive_interval,
+           options.client_alive_count_max);
+
+       /* Start session. */
+       do_authenticated(authctxt);
+
+       /* The connection has been terminated. */
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes",
+           (unsigned long long)obytes, (unsigned long long)ibytes);
+
+       verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               finish_pam();
+#endif /* USE_PAM */
+
+#ifdef SSH_AUDIT_EVENTS
+       PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));
+#endif
+
+       packet_close();
+
+       if (use_privsep)
+               mm_terminate();
+
+       exit(0);
+}
+
+/*
+ * Decrypt session_key_int using our private server key and private host key
+ * (key with larger modulus first).
+ */
+int
+ssh1_session_key(BIGNUM *session_key_int)
+{
+       int rsafail = 0;
+
+       if (BN_cmp(sensitive_data.server_key->rsa->n,
+           sensitive_data.ssh1_host_key->rsa->n) > 0) {
+               /* Server key has bigger modulus. */
+               if (BN_num_bits(sensitive_data.server_key->rsa->n) <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) <= 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) <= 0)
+                       rsafail++;
+       } else {
+               /* Host key has bigger modulus (or they are equal). */
+               if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
+                   BN_num_bits(sensitive_data.server_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) < 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) < 0)
+                       rsafail++;
+       }
+       return (rsafail);
+}
+/*
+ * SSH1 key exchange
+ */
+static void
+do_ssh1_kex(void)
+{
+       int i, len;
+       int rsafail = 0;
+       BIGNUM *session_key_int;
+       u_char session_key[SSH_SESSION_KEY_LENGTH];
+       u_char cookie[8];
+       u_int cipher_type, auth_mask, protocol_flags;
+
+       /*
+        * Generate check bytes that the client must send back in the user
+        * packet in order for it to be accepted; this is used to defy ip
+        * spoofing attacks.  Note that this only works against somebody
+        * doing IP spoofing from a remote machine; any machine on the local
+        * network can still see outgoing packets and catch the random
+        * cookie.  This only affects rhosts authentication, and this is one
+        * of the reasons why it is inherently insecure.
+        */
+       arc4random_buf(cookie, sizeof(cookie));
+
+       /*
+        * Send our public key.  We include in the packet 64 bits of random
+        * data that must be matched in the reply in order to prevent IP
+        * spoofing.
+        */
+       packet_start(SSH_SMSG_PUBLIC_KEY);
+       for (i = 0; i < 8; i++)
+               packet_put_char(cookie[i]);
+
+       /* Store our public server RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
+       packet_put_bignum(sensitive_data.server_key->rsa->e);
+       packet_put_bignum(sensitive_data.server_key->rsa->n);
+
+       /* Store our public host RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
+
+       /* Put protocol flags. */
+       packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
+
+       /* Declare which ciphers we support. */
+       packet_put_int(cipher_mask_ssh1(0));
+
+       /* Declare supported authentication types. */
+       auth_mask = 0;
+       if (options.rhosts_rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
+       if (options.rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RSA;
+       if (options.challenge_response_authentication == 1)
+               auth_mask |= 1 << SSH_AUTH_TIS;
+       if (options.password_authentication)
+               auth_mask |= 1 << SSH_AUTH_PASSWORD;
+       packet_put_int(auth_mask);
+
+       /* Send the packet and wait for it to be sent. */
+       packet_send();
+       packet_write_wait();
+
+       debug("Sent %d bit server key and %d bit host key.",
+           BN_num_bits(sensitive_data.server_key->rsa->n),
+           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+
+       /* Read clients reply (cipher type and session key). */
+       packet_read_expect(SSH_CMSG_SESSION_KEY);
+
+       /* Get cipher type and check whether we accept this. */
+       cipher_type = packet_get_char();
+
+       if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
+               packet_disconnect("Warning: client selects unsupported cipher.");
+
+       /* Get check bytes from the packet.  These must match those we
+          sent earlier with the public key packet. */
+       for (i = 0; i < 8; i++)
+               if (cookie[i] != packet_get_char())
+                       packet_disconnect("IP Spoofing check bytes do not match.");
+
+       debug("Encryption type: %.200s", cipher_name(cipher_type));
+
+       /* Get the encrypted integer. */
+       if ((session_key_int = BN_new()) == NULL)
+               fatal("do_ssh1_kex: BN_new failed");
+       packet_get_bignum(session_key_int);
+
+       protocol_flags = packet_get_int();
+       packet_set_protocol_flags(protocol_flags);
+       packet_check_eom();
+
+       /* Decrypt session_key_int using host/server keys */
+       rsafail = PRIVSEP(ssh1_session_key(session_key_int));
+
+       /*
+        * Extract session key from the decrypted integer.  The key is in the
+        * least significant 256 bits of the integer; the first byte of the
+        * key is in the highest bits.
+        */
+       if (!rsafail) {
+               (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
+               len = BN_num_bytes(session_key_int);
+               if (len < 0 || (u_int)len > sizeof(session_key)) {
+                       error("do_ssh1_kex: bad session key len from %s: "
+                           "session_key_int %d > sizeof(session_key) %lu",
+                           get_remote_ipaddr(), len, (u_long)sizeof(session_key));
+                       rsafail++;
+               } else {
+                       memset(session_key, 0, sizeof(session_key));
+                       BN_bn2bin(session_key_int,
+                           session_key + sizeof(session_key) - len);
+
+                       derive_ssh1_session_id(
+                           sensitive_data.ssh1_host_key->rsa->n,
+                           sensitive_data.server_key->rsa->n,
+                           cookie, session_id);
+                       /*
+                        * Xor the first 16 bytes of the session key with the
+                        * session id.
+                        */
+                       for (i = 0; i < 16; i++)
+                               session_key[i] ^= session_id[i];
+               }
+       }
+       if (rsafail) {
+               int bytes = BN_num_bytes(session_key_int);
+               u_char *buf = xmalloc(bytes);
+               MD5_CTX md;
+
+               logit("do_connection: generating a fake encryption key");
+               BN_bn2bin(session_key_int, buf);
+               MD5_Init(&md);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key, &md);
+               MD5_Init(&md);
+               MD5_Update(&md, session_key, 16);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key + 16, &md);
+               memset(buf, 0, bytes);
+               xfree(buf);
+               for (i = 0; i < 16; i++)
+                       session_id[i] = session_key[i] ^ session_key[i + 16];
+       }
+       /* Destroy the private and public keys. No longer. */
+       destroy_sensitive_data();
+
+       if (use_privsep)
+               mm_ssh1_session_id(session_id);
+
+       /* Destroy the decrypted integer.  It is no longer needed. */
+       BN_clear_free(session_key_int);
+
+       /* Set the session key.  From this on all communications will be encrypted. */
+       packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);
+
+       /* Destroy our copy of the session key.  It is no longer needed. */
+       memset(session_key, 0, sizeof(session_key));
+
+       debug("Received session key; encryption turned on.");
+
+       /* Send an acknowledgment packet.  Note that this packet is sent encrypted. */
+       packet_start(SSH_SMSG_SUCCESS);
+       packet_send();
+       packet_write_wait();
+}
+
+/*
+ * SSH2 key exchange: diffie-hellman-group1-sha1
+ */
+static void
+do_ssh2_kex(void)
+{
+       Kex *kex;
+
+       if (options.ciphers != NULL) {
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       myproposal[PROPOSAL_ENC_ALGS_STOC] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
+
+       if (options.macs != NULL) {
+               myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+               myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+       }
+       if (options.compression == COMP_NONE) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
+       } else if (options.compression == COMP_DELAYED) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";
+       }
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+
+       myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
+
+#ifdef GSSAPI
+       {
+       char *orig;
+       char *gss = NULL;
+       char *newstr = NULL;
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+
+       /* 
+        * If we don't have a host key, then there's no point advertising
+        * the other key exchange algorithms
+        */
+
+       if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+               orig = NULL;
+
+       if (options.gss_keyex)
+               gss = ssh_gssapi_server_mechanisms();
+       else
+               gss = NULL;
+
+       if (gss && orig)
+               xasprintf(&newstr, "%s,%s", gss, orig);
+       else if (gss)
+               newstr = gss;
+       else if (orig)
+               newstr = orig;
+
+       /* 
+        * If we've got GSSAPI mechanisms, then we've got the 'null' host
+        * key alg, but we can't tell people about it unless its the only
+        * host key algorithm we support
+        */
+       if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+       if (newstr)
+               myproposal[PROPOSAL_KEX_ALGS] = newstr;
+       else
+               fatal("No supported key exchange algorithms");
+       }
+#endif
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
+#endif
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->load_host_public_key=&get_hostkey_public_by_type;
+       kex->load_host_private_key=&get_hostkey_private_by_type;
+       kex->host_key_index=&get_hostkey_index;
+
+       xxx_kex = kex;
+
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
+
+#ifdef DEBUG_KEXDH
+       /* send 1st encrypted/maced/compressed message */
+       packet_start(SSH2_MSG_IGNORE);
+       packet_put_cstring("markus");
+       packet_send();
+       packet_write_wait();
+#endif
+       debug("KEX done");
+}
+
+/* server specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       if (the_authctxt)
+               do_cleanup(the_authctxt);
+#ifdef SSH_AUDIT_EVENTS
+       /* done after do_cleanup so it can cancel the PAM auth 'thread' */
+       if (!use_privsep || mm_is_monitor())
+               audit_event(SSH_CONNECTION_ABANDON);
+#endif
+       _exit(i);
+}
diff --git a/.pc/debian-banner.patch/sshd_config.5 b/.pc/debian-banner.patch/sshd_config.5
new file mode 100644 (file)
index 0000000..d75de02
--- /dev/null
@@ -0,0 +1,1260 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd_config.5,v 1.135 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD_CONFIG 5
+.Os
+.Sh NAME
+.Nm sshd_config
+.Nd OpenSSH SSH daemon configuration file
+.Sh SYNOPSIS
+.Nm /etc/ssh/sshd_config
+.Sh DESCRIPTION
+.Xr sshd 8
+reads configuration data from
+.Pa /etc/ssh/sshd_config
+(or the file specified with
+.Fl f
+on the command line).
+The file contains keyword-argument pairs, one per line.
+Lines starting with
+.Ql #
+and empty lines are interpreted as comments.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm AcceptEnv
+Specifies what environment variables sent by the client will be copied into
+the session's
+.Xr environ 7 .
+See
+.Cm SendEnv
+in
+.Xr ssh_config 5
+for how to configure the client.
+Note that environment passing is only supported for protocol 2.
+Variables are specified by name, which may contain the wildcard characters
+.Ql *
+and
+.Ql \&? .
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm AcceptEnv
+directives.
+Be warned that some environment variables could be used to bypass restricted
+user environments.
+For this reason, care should be taken in the use of this directive.
+The default is not to accept any environment variables.
+.It Cm AddressFamily
+Specifies which address family should be used by
+.Xr sshd 8 .
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+The default is
+.Dq any .
+.It Cm AllowAgentForwarding
+Specifies whether
+.Xr ssh-agent 1
+forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling agent forwarding does not improve security
+unless users are also denied shell access, as they can always install
+their own forwarders.
+.It Cm AllowGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+If specified, login is allowed only for users whose primary
+group or supplementary group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling TCP forwarding does not improve security unless
+users are also denied shell access, as they can always install their
+own forwarders.
+.It Cm AllowUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+If specified, login is allowed only for user names that
+match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AuthorizedKeysFile
+Specifies the file that contains the public keys that can be used
+for user authentication.
+The format is described in the
+.Sx AUTHORIZED_KEYS FILE FORMAT
+section of
+.Xr sshd 8 .
+.Cm AuthorizedKeysFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedKeysFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+Multiple files may be listed, separated by whitespace.
+The default is
+.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
+.It Cm AuthorizedPrincipalsFile
+Specifies a file that lists principal names that are accepted for
+certificate authentication.
+When using certificates signed by a key listed in
+.Cm TrustedUserCAKeys ,
+this file lists names, one of which must appear in the certificate for it
+to be accepted for authentication.
+Names are listed one per line preceded by key options (as described
+in
+.Sx AUTHORIZED_KEYS FILE FORMAT
+in
+.Xr sshd 8 ) .
+Empty lines and comments starting with
+.Ql #
+are ignored.
+.Pp
+.Cm AuthorizedPrincipalsFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedPrincipalsFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+.Pp
+The default is not to use a principals file \(en in this case, the username
+of the user must appear in a certificate's principals list for it to be
+accepted.
+Note that
+.Cm AuthorizedPrincipalsFile
+is only used when authentication proceeds using a CA listed in
+.Cm TrustedUserCAKeys
+and is not consulted for certification authorities trusted via
+.Pa ~/.ssh/authorized_keys ,
+though the
+.Cm principals=
+key option offers a similar facility (see
+.Xr sshd 8
+for details).
+.It Cm Banner
+The contents of the specified file are sent to the remote user before
+authentication is allowed.
+If the argument is
+.Dq none
+then no banner is displayed.
+This option is only available for protocol version 2.
+By default, no banner is displayed.
+.It Cm ChallengeResponseAuthentication
+Specifies whether challenge-response authentication is allowed (e.g. via
+PAM or though authentication styles supported in
+.Xr login.conf 5 )
+The default is
+.Dq yes .
+.It Cm ChrootDirectory
+Specifies the pathname of a directory to
+.Xr chroot 2
+to after authentication.
+All components of the pathname must be root-owned directories that are
+not writable by any other user or group.
+After the chroot,
+.Xr sshd 8
+changes the working directory to the user's home directory.
+.Pp
+The pathname may contain the following tokens that are expanded at runtime once
+the connecting user has been authenticated: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+.Pp
+The
+.Cm ChrootDirectory
+must contain the necessary files and directories to support the
+user's session.
+For an interactive session this requires at least a shell, typically
+.Xr sh 1 ,
+and basic
+.Pa /dev
+nodes such as
+.Xr null 4 ,
+.Xr zero 4 ,
+.Xr stdin 4 ,
+.Xr stdout 4 ,
+.Xr stderr 4 ,
+.Xr arandom 4
+and
+.Xr tty 4
+devices.
+For file transfer sessions using
+.Dq sftp ,
+no additional configuration of the environment is necessary if the
+in-process sftp server is used,
+though sessions which use logging do require
+.Pa /dev/log
+inside the chroot directory (see
+.Xr sftp-server 8
+for details).
+.Pp
+The default is not to
+.Xr chroot 2 .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClientAliveCountMax
+Sets the number of client alive messages (see below) which may be
+sent without
+.Xr sshd 8
+receiving any messages back from the client.
+If this threshold is reached while client alive messages are being sent,
+sshd will disconnect the client, terminating the session.
+It is important to note that the use of client alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The client alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The client alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If
+.Cm ClientAliveInterval
+(see below) is set to 15, and
+.Cm ClientAliveCountMax
+is left at the default, unresponsive SSH clients
+will be disconnected after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ClientAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the client,
+.Xr sshd 8
+will send a message through the encrypted
+channel to request a response from the client.
+The default
+is 0, indicating that these messages will not be sent to the client.
+This option applies to protocol version 2 only.
+.It Cm Compression
+Specifies whether compression is allowed, or delayed until
+the user has authenticated successfully.
+The argument must be
+.Dq yes ,
+.Dq delayed ,
+or
+.Dq no .
+The default is
+.Dq delayed .
+.It Cm DenyGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+Login is disallowed for users whose primary group or supplementary
+group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm DenyUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+Login is disallowed for user names that match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm ForceCommand
+Forces the execution of the command specified by
+.Cm ForceCommand ,
+ignoring any command supplied by the client and
+.Pa ~/.ssh/rc
+if present.
+The command is invoked by using the user's login shell with the -c option.
+This applies to shell, command, or subsystem execution.
+It is most useful inside a
+.Cm Match
+block.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Specifying a command of
+.Dq internal-sftp
+will force the use of an in-process sftp server that requires no support
+files when used with
+.Cm ChrootDirectory .
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to ports
+forwarded for the client.
+By default,
+.Xr sshd 8
+binds remote port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that sshd
+should allow remote port forwardings to bind to non-loopback addresses, thus
+allowing other hosts to connect.
+The argument may be
+.Dq no
+to force remote port forwardings to be available to the local host only,
+.Dq yes
+to force remote port forwardings to bind to the wildcard address, or
+.Dq clientspecified
+to allow the client to select the address to which the forwarding is bound.
+The default is
+.Dq no .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICleanupCredentials
+Specifies whether to automatically destroy the user's credentials cache
+on logout.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor 
+a client authenticates against. If
+.Dq yes
+then the client must authenticate against the
+.Pa host
+service on the current hostname. If 
+.Dq no
+then the client may authenticate against any service key stored in the 
+machine's default store. This facility is provided to assist with operation 
+on multi homed machines. 
+The default is
+.Dq yes .
+Note that this option applies only to protocol version 2 GSSAPI connections,
+and setting it to 
+.Dq no
+may only work with recent Kerberos GSSAPI libraries.
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
+.Dq no .
+.It Cm HostbasedAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful public key client host authentication is allowed
+(host-based authentication).
+This option is similar to
+.Cm RhostsRSAAuthentication
+and applies to protocol version 2 only.
+The default is
+.Dq no .
+.It Cm HostbasedUsesNameFromPacketOnly
+Specifies whether or not the server will attempt to perform a reverse
+name lookup when matching the name in the
+.Pa ~/.shosts ,
+.Pa ~/.rhosts ,
+and
+.Pa /etc/hosts.equiv
+files during
+.Cm HostbasedAuthentication .
+A setting of
+.Dq yes
+means that
+.Xr sshd 8
+uses the name supplied by the client rather than
+attempting to resolve the name from the TCP connection itself.
+The default is
+.Dq no .
+.It Cm HostCertificate
+Specifies a file containing a public host certificate.
+The certificate's public key must match a private host key already specified
+by
+.Cm HostKey .
+The default behaviour of
+.Xr sshd 8
+is not to load any certificates.
+.It Cm HostKey
+Specifies a file containing a private host key
+used by SSH.
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+Note that
+.Xr sshd 8
+will refuse to use a file if it is group/world-accessible.
+It is possible to have multiple host key files.
+.Dq rsa1
+keys are used for version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+are used for version 2 of the SSH protocol.
+.It Cm IgnoreRhosts
+Specifies that
+.Pa .rhosts
+and
+.Pa .shosts
+files will not be used in
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+.Pp
+.Pa /etc/hosts.equiv
+and
+.Pa /etc/shosts.equiv
+are still used.
+The default is
+.Dq yes .
+.It Cm IgnoreUserKnownHosts
+Specifies whether
+.Xr sshd 8
+should ignore the user's
+.Pa ~/.ssh/known_hosts
+during
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+The default is
+.Dq no .
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for the connection.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KerberosAuthentication
+Specifies whether the password provided by the user for
+.Cm PasswordAuthentication
+will be validated through the Kerberos KDC.
+To use this option, the server needs a
+Kerberos servtab which allows the verification of the KDC's identity.
+The default is
+.Dq no .
+.It Cm KerberosGetAFSToken
+If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
+an AFS token before accessing the user's home directory.
+The default is
+.Dq no .
+.It Cm KerberosOrLocalPasswd
+If password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as
+.Pa /etc/passwd .
+The default is
+.Dq yes .
+.It Cm KerberosTicketCleanup
+Specifies whether to automatically destroy the user's ticket cache
+file on logout.
+The default is
+.Dq yes .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq ecdh-sha2-nistp256 ,
+.Dq ecdh-sha2-nistp384 ,
+.Dq ecdh-sha2-nistp521 ,
+.Dq diffie-hellman-group-exchange-sha256 ,
+.Dq diffie-hellman-group-exchange-sha1 ,
+.Dq diffie-hellman-group14-sha1 ,
+.Dq diffie-hellman-group1-sha1 .
+.It Cm KeyRegenerationInterval
+In protocol version 1, the ephemeral server key is automatically regenerated
+after this many seconds (if it has been used).
+The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys.
+The key is never stored anywhere.
+If the value is 0, the key is never regenerated.
+The default is 3600 (seconds).
+.It Cm ListenAddress
+Specifies the local addresses
+.Xr sshd 8
+should listen on.
+The following forms may be used:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No : Ar port
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Oo
+.Ar host No | Ar IPv6_addr Oc : Ar port
+.Sm on
+.El
+.Pp
+If
+.Ar port
+is not specified,
+sshd will listen on the address and all prior
+.Cm Port
+options specified.
+The default is to listen on all local addresses.
+Multiple
+.Cm ListenAddress
+options are permitted.
+Additionally, any
+.Cm Port
+options must precede this option for non-port qualified addresses.
+.It Cm LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in.
+If the value is 0, there is no time limit.
+The default is 120 seconds.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr sshd 8 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of debugging output.
+Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm MACs
+Specifies the available MAC (message authentication code) algorithms.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm Match
+Introduces a conditional block.
+If all of the criteria on the
+.Cm Match
+line are satisfied, the keywords on the following lines override those
+set in the global section of the config file, until either another
+.Cm Match
+line or the end of the file.
+.Pp
+The arguments to
+.Cm Match
+are one or more criteria-pattern pairs.
+The available criteria are
+.Cm User ,
+.Cm Group ,
+.Cm Host ,
+and
+.Cm Address .
+The match patterns may consist of single entries or comma-separated
+lists and may use the wildcard and negation operators described in the
+.Sx PATTERNS
+section of
+.Xr ssh_config 5 .
+.Pp
+The patterns in an
+.Cm Address
+criteria may additionally contain addresses to match in CIDR
+address/masklen format, e.g.\&
+.Dq 192.0.2.0/24
+or
+.Dq 3ffe:ffff::/32 .
+Note that the mask length provided must be consistent with the address -
+it is an error to specify a mask length that is too long for the address
+or one with bits set in this host portion of the address.
+For example,
+.Dq 192.0.2.0/33
+and
+.Dq 192.0.2.0/8
+respectively.
+.Pp
+Only a subset of keywords may be used on the lines following a
+.Cm Match
+keyword.
+Available keywords are
+.Cm AllowAgentForwarding ,
+.Cm AllowTcpForwarding ,
+.Cm AuthorizedKeysFile ,
+.Cm AuthorizedPrincipalsFile ,
+.Cm Banner ,
+.Cm ChrootDirectory ,
+.Cm ForceCommand ,
+.Cm GatewayPorts ,
+.Cm GSSAPIAuthentication ,
+.Cm HostbasedAuthentication ,
+.Cm HostbasedUsesNameFromPacketOnly ,
+.Cm KbdInteractiveAuthentication ,
+.Cm KerberosAuthentication ,
+.Cm MaxAuthTries ,
+.Cm MaxSessions ,
+.Cm PasswordAuthentication ,
+.Cm PermitEmptyPasswords ,
+.Cm PermitOpen ,
+.Cm PermitRootLogin ,
+.Cm PermitTunnel ,
+.Cm PubkeyAuthentication ,
+.Cm RhostsRSAAuthentication ,
+.Cm RSAAuthentication ,
+.Cm X11DisplayOffset ,
+.Cm X11Forwarding
+and
+.Cm X11UseLocalHost .
+.It Cm MaxAuthTries
+Specifies the maximum number of authentication attempts permitted per
+connection.
+Once the number of failures reaches half this value,
+additional failures are logged.
+The default is 6.
+.It Cm MaxSessions
+Specifies the maximum number of open sessions permitted per network connection.
+The default is 10.
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+SSH daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g. "10:30:60").
+.Xr sshd 8
+will refuse connection attempts with a probability of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probability increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
+.It Cm PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is
+.Dq yes .
+.It Cm PermitBlacklistedKeys
+Specifies whether
+.Xr sshd 8
+should allow keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 ) .
+If
+.Dq yes ,
+then attempts to authenticate with compromised keys will be logged but
+accepted.
+If
+.Dq no ,
+then attempts to authenticate with compromised keys will be rejected.
+The default is
+.Dq no .
+.It Cm PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings.
+The default is
+.Dq no .
+.It Cm PermitOpen
+Specifies the destinations to which TCP port forwarding is permitted.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Dq any
+can be used to remove all restrictions and permit any forwarding requests.
+By default all port forwarding requests are permitted.
+.It Cm PermitRootLogin
+Specifies whether root can log in using
+.Xr ssh 1 .
+The argument must be
+.Dq yes ,
+.Dq without-password ,
+.Dq forced-commands-only ,
+or
+.Dq no .
+The default is
+.Dq yes .
+.Pp
+If this option is set to
+.Dq without-password ,
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only ,
+root login with public key authentication will be allowed,
+but only if the
+.Ar command
+option has been specified
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+All other authentication methods are disabled for root.
+.Pp
+If this option is set to
+.Dq no ,
+root is not allowed to log in.
+.It Cm PermitTunnel
+Specifies whether
+.Xr tun 4
+device forwarding is allowed.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2), or
+.Dq no .
+Specifying
+.Dq yes
+permits both
+.Dq point-to-point
+and
+.Dq ethernet .
+The default is
+.Dq no .
+.It Cm PermitUserEnvironment
+Specifies whether
+.Pa ~/.ssh/environment
+and
+.Cm environment=
+options in
+.Pa ~/.ssh/authorized_keys
+are processed by
+.Xr sshd 8 .
+The default is
+.Dq no .
+Enabling environment processing may enable users to bypass access
+restrictions in some configurations using mechanisms such as
+.Ev LD_PRELOAD .
+.It Cm PidFile
+Specifies the file that contains the process ID of the
+SSH daemon.
+The default is
+.Pa /var/run/sshd.pid .
+.It Cm Port
+Specifies the port number that
+.Xr sshd 8
+listens on.
+The default is 22.
+Multiple options of this type are permitted.
+See also
+.Cm ListenAddress .
+.It Cm PrintLastLog
+Specifies whether
+.Xr sshd 8
+should print the date and time of the last user login when a user logs
+in interactively.
+The default is
+.Dq yes .
+.It Cm PrintMotd
+Specifies whether
+.Xr sshd 8
+should print
+.Pa /etc/motd
+when a user logs in interactively.
+(On some systems it is also printed by the shell,
+.Pa /etc/profile ,
+or equivalent.)
+The default is
+.Dq yes .
+.It Cm Protocol
+Specifies the protocol versions
+.Xr sshd 8
+supports.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Sq 2 .
+Note that the order of the protocol list does not indicate preference,
+because the client selects among multiple protocol versions offered
+by the server.
+Specifying
+.Dq 2,1
+is identical to
+.Dq 1,2 .
+.It Cm PubkeyAuthentication
+Specifies whether public key authentication is allowed.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm RevokedKeys
+Specifies a list of revoked public keys.
+Keys listed in this file will be refused for public key authentication.
+Note that if this file is not readable, then public key authentication will
+be refused for all users.
+.It Cm RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RSAAuthentication
+Specifies whether pure RSA authentication is allowed.
+The default is
+.Dq yes .
+This option applies to protocol version 1 only.
+.It Cm ServerKeyBits
+Defines the number of bits in the ephemeral protocol version 1 server key.
+The minimum value is 512, and the default is 1024.
+.It Cm StrictModes
+Specifies whether
+.Xr sshd 8
+should check file modes and ownership of the
+user's files and home directory before accepting login.
+This is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable.
+The default is
+.Dq yes .
+Note that this does not apply to
+.Cm ChrootDirectory ,
+whose permissions and ownership are checked unconditionally.
+.It Cm Subsystem
+Configures an external subsystem (e.g. file transfer daemon).
+Arguments should be a subsystem name and a command (with optional arguments)
+to execute upon subsystem request.
+.Pp
+The command
+.Xr sftp-server 8
+implements the
+.Dq sftp
+file transfer subsystem.
+.Pp
+Alternately the name
+.Dq internal-sftp
+implements an in-process
+.Dq sftp
+server.
+This may simplify configurations using
+.Cm ChrootDirectory
+to force a different filesystem root on clients.
+.Pp
+By default no subsystems are defined.
+Note that this option applies to protocol version 2 only.
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Xr sshd 8 .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is AUTH.
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+On the other hand, if TCP keepalives are not sent,
+sessions may hang indefinitely on the server, leaving
+.Dq ghost
+users and consuming server resources.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the server will notice
+if the network goes down or the client host crashes.
+This avoids infinitely hanging sessions.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.Pp
+This option was formerly called
+.Cm KeepAlive .
+.It Cm TrustedUserCAKeys
+Specifies a file containing public keys of certificate authorities that are
+trusted to sign user certificates for authentication.
+Keys are listed one per line; empty lines and comments starting with
+.Ql #
+are allowed.
+If a certificate is presented for authentication and has its signing CA key
+listed in this file, then it may be used for authentication for any user
+listed in the certificate's principals list.
+Note that certificates that lack a list of principals will not be permitted
+for authentication using
+.Cm TrustedUserCAKeys .
+For more details on certificates, see the
+.Sx CERTIFICATES
+section in
+.Xr ssh-keygen 1 .
+.It Cm UseDNS
+Specifies whether
+.Xr sshd 8
+should look up the remote host name and check that
+the resolved host name for the remote IP address maps back to the
+very same IP address.
+The default is
+.Dq yes .
+.It Cm UseLogin
+Specifies whether
+.Xr login 1
+is used for interactive login sessions.
+The default is
+.Dq no .
+Note that
+.Xr login 1
+is never used for remote command execution.
+Note also, that if this is enabled,
+.Cm X11Forwarding
+will be disabled because
+.Xr login 1
+does not know how to handle
+.Xr xauth 1
+cookies.
+If
+.Cm UsePrivilegeSeparation
+is specified, it will be disabled after authentication.
+.It Cm UsePAM
+Enables the Pluggable Authentication Module interface.
+If set to
+.Dq yes
+this will enable PAM authentication using
+.Cm ChallengeResponseAuthentication
+and
+.Cm PasswordAuthentication
+in addition to PAM account and session module processing for all
+authentication types.
+.Pp
+Because PAM challenge-response authentication usually serves an equivalent
+role to password authentication, you should disable either
+.Cm PasswordAuthentication
+or
+.Cm ChallengeResponseAuthentication.
+.Pp
+If
+.Cm UsePAM
+is enabled, you will not be able to run
+.Xr sshd 8
+as a non-root user.
+The default is
+.Dq no .
+.It Cm UsePrivilegeSeparation
+Specifies whether
+.Xr sshd 8
+separates privileges by creating an unprivileged child process
+to deal with incoming network traffic.
+After successful authentication, another process will be created that has
+the privilege of the authenticated user.
+The goal of privilege separation is to prevent privilege
+escalation by containing any corruption within the unprivileged processes.
+The default is
+.Dq yes .
+If
+.Cm UsePrivilegeSeparation
+is set to
+.Dq sandbox
+then the pre-authentication unprivileged process is subject to additional
+restrictions.
+.It Cm X11DisplayOffset
+Specifies the first display number available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from interfering with real X11 servers.
+The default is 10.
+.It Cm X11Forwarding
+Specifies whether X11 forwarding is permitted.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+When X11 forwarding is enabled, there may be additional exposure to
+the server and to client displays if the
+.Xr sshd 8
+proxy display is configured to listen on the wildcard address (see
+.Cm X11UseLocalhost
+below), though this is not the default.
+Additionally, the authentication spoofing and authentication data
+verification and substitution occur on the client side.
+The security risk of using X11 forwarding is that the client's X11
+display server may be exposed to attack when the SSH client requests
+forwarding (see the warnings for
+.Cm ForwardX11
+in
+.Xr ssh_config 5 ) .
+A system administrator may have a stance in which they want to
+protect clients that may expose themselves to attack by unwittingly
+requesting X11 forwarding, which can warrant a
+.Dq no
+setting.
+.Pp
+Note that disabling X11 forwarding does not prevent users from
+forwarding X11 traffic, as users can always install their own forwarders.
+X11 forwarding is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm X11UseLocalhost
+Specifies whether
+.Xr sshd 8
+should bind the X11 forwarding server to the loopback address or to
+the wildcard address.
+By default,
+sshd binds the forwarding server to the loopback address and sets the
+hostname part of the
+.Ev DISPLAY
+environment variable to
+.Dq localhost .
+This prevents remote hosts from connecting to the proxy display.
+However, some older X11 clients may not function with this
+configuration.
+.Cm X11UseLocalhost
+may be set to
+.Dq no
+to specify that the forwarding server should be bound to the wildcard
+address.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh TIME FORMATS
+.Xr sshd 8
+command-line arguments and configuration file options that specify time
+may be expressed using a sequence of the form:
+.Sm off
+.Ar time Op Ar qualifier ,
+.Sm on
+where
+.Ar time
+is a positive integer value and
+.Ar qualifier
+is one of the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Aq Cm none
+seconds
+.It Cm s | Cm S
+seconds
+.It Cm m | Cm M
+minutes
+.It Cm h | Cm H
+hours
+.It Cm d | Cm D
+days
+.It Cm w | Cm W
+weeks
+.El
+.Pp
+Each member of the sequence is added together to calculate
+the total time value.
+.Pp
+Time format examples:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It 600
+600 seconds (10 minutes)
+.It 10m
+10 minutes
+.It 1h30m
+1 hour 30 minutes (90 minutes)
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Xr sshd 8 .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.El
+.Sh SEE ALSO
+.Xr sshd 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
diff --git a/.pc/debian-config.patch/readconf.c b/.pc/debian-config.patch/readconf.c
new file mode 100644 (file)
index 0000000..d8c7cfc
--- /dev/null
@@ -0,0 +1,1535 @@
+/* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for reading the configuration files.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "compat.h"
+#include "cipher.h"
+#include "pathnames.h"
+#include "log.h"
+#include "key.h"
+#include "readconf.h"
+#include "match.h"
+#include "misc.h"
+#include "buffer.h"
+#include "kex.h"
+#include "mac.h"
+
+/* Format of the configuration file:
+
+   # Configuration data is parsed as follows:
+   #  1. command line options
+   #  2. user-specific file
+   #  3. system-wide file
+   # Any configuration value is only changed the first time it is set.
+   # Thus, host-specific definitions should be at the beginning of the
+   # configuration file, and defaults at the end.
+
+   # Host-specific declarations.  These may override anything above.  A single
+   # host may match multiple declarations; these are processed in the order
+   # that they are given in.
+
+   Host *.ngs.fi ngs.fi
+     User foo
+
+   Host fake.com
+     HostName another.host.name.real.org
+     User blaah
+     Port 34289
+     ForwardX11 no
+     ForwardAgent no
+
+   Host books.com
+     RemoteForward 9999 shadows.cs.hut.fi:9999
+     Cipher 3des
+
+   Host fascist.blob.com
+     Port 23123
+     User tylonen
+     PasswordAuthentication no
+
+   Host puukko.hut.fi
+     User t35124p
+     ProxyCommand ssh-proxy %h %p
+
+   Host *.fr
+     PublicKeyAuthentication no
+
+   Host *.su
+     Cipher none
+     PasswordAuthentication no
+
+   Host vpn.fake.com
+     Tunnel yes
+     TunnelDevice 3
+
+   # Defaults for various options
+   Host *
+     ForwardAgent no
+     ForwardX11 no
+     PasswordAuthentication yes
+     RSAAuthentication yes
+     RhostsRSAAuthentication yes
+     StrictHostKeyChecking yes
+     TcpKeepAlive no
+     IdentityFile ~/.ssh/identity
+     Port 22
+     EscapeChar ~
+
+*/
+
+/* Keyword tokens. */
+
+typedef enum {
+       oBadOption,
+       oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
+       oGatewayPorts, oExitOnForwardFailure,
+       oPasswordAuthentication, oRSAAuthentication,
+       oChallengeResponseAuthentication, oXAuthLocation,
+       oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
+       oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+       oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
+       oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
+       oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
+       oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
+       oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
+       oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
+       oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
+       oUseBlacklistedKeys,
+       oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
+       oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+       oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
+       oGssServerIdentity, 
+       oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+       oSendEnv, oControlPath, oControlMaster, oControlPersist,
+       oHashKnownHosts,
+       oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
+       oKexAlgorithms, oIPQoS, oRequestTTY,
+       oProtocolKeepAlives, oSetupTimeOut,
+       oDeprecated, oUnsupported
+} OpCodes;
+
+/* Textual representations of the tokens. */
+
+static struct {
+       const char *name;
+       OpCodes opcode;
+} keywords[] = {
+       { "forwardagent", oForwardAgent },
+       { "forwardx11", oForwardX11 },
+       { "forwardx11trusted", oForwardX11Trusted },
+       { "forwardx11timeout", oForwardX11Timeout },
+       { "exitonforwardfailure", oExitOnForwardFailure },
+       { "xauthlocation", oXAuthLocation },
+       { "gatewayports", oGatewayPorts },
+       { "useprivilegedport", oUsePrivilegedPort },
+       { "rhostsauthentication", oDeprecated },
+       { "passwordauthentication", oPasswordAuthentication },
+       { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
+       { "kbdinteractivedevices", oKbdInteractiveDevices },
+       { "useblacklistedkeys", oUseBlacklistedKeys },
+       { "rsaauthentication", oRSAAuthentication },
+       { "pubkeyauthentication", oPubkeyAuthentication },
+       { "dsaauthentication", oPubkeyAuthentication },             /* alias */
+       { "rhostsrsaauthentication", oRhostsRSAAuthentication },
+       { "hostbasedauthentication", oHostbasedAuthentication },
+       { "challengeresponseauthentication", oChallengeResponseAuthentication },
+       { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
+       { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
+       { "kerberosauthentication", oUnsupported },
+       { "kerberostgtpassing", oUnsupported },
+       { "afstokenpassing", oUnsupported },
+#if defined(GSSAPI)
+       { "gssapiauthentication", oGssAuthentication },
+       { "gssapikeyexchange", oGssKeyEx },
+       { "gssapidelegatecredentials", oGssDelegateCreds },
+       { "gssapitrustdns", oGssTrustDns },
+       { "gssapiclientidentity", oGssClientIdentity },
+       { "gssapiserveridentity", oGssServerIdentity },
+       { "gssapirenewalforcesrekey", oGssRenewalRekey },
+#else
+       { "gssapiauthentication", oUnsupported },
+       { "gssapikeyexchange", oUnsupported },
+       { "gssapidelegatecredentials", oUnsupported },
+       { "gssapitrustdns", oUnsupported },
+       { "gssapiclientidentity", oUnsupported },
+       { "gssapirenewalforcesrekey", oUnsupported },
+#endif
+       { "fallbacktorsh", oDeprecated },
+       { "usersh", oDeprecated },
+       { "identityfile", oIdentityFile },
+       { "identityfile2", oIdentityFile },                     /* obsolete */
+       { "identitiesonly", oIdentitiesOnly },
+       { "hostname", oHostName },
+       { "hostkeyalias", oHostKeyAlias },
+       { "proxycommand", oProxyCommand },
+       { "port", oPort },
+       { "cipher", oCipher },
+       { "ciphers", oCiphers },
+       { "macs", oMacs },
+       { "protocol", oProtocol },
+       { "remoteforward", oRemoteForward },
+       { "localforward", oLocalForward },
+       { "user", oUser },
+       { "host", oHost },
+       { "escapechar", oEscapeChar },
+       { "globalknownhostsfile", oGlobalKnownHostsFile },
+       { "globalknownhostsfile2", oDeprecated },
+       { "userknownhostsfile", oUserKnownHostsFile },
+       { "userknownhostsfile2", oDeprecated }, 
+       { "connectionattempts", oConnectionAttempts },
+       { "batchmode", oBatchMode },
+       { "checkhostip", oCheckHostIP },
+       { "stricthostkeychecking", oStrictHostKeyChecking },
+       { "compression", oCompression },
+       { "compressionlevel", oCompressionLevel },
+       { "tcpkeepalive", oTCPKeepAlive },
+       { "keepalive", oTCPKeepAlive },                         /* obsolete */
+       { "numberofpasswordprompts", oNumberOfPasswordPrompts },
+       { "loglevel", oLogLevel },
+       { "dynamicforward", oDynamicForward },
+       { "preferredauthentications", oPreferredAuthentications },
+       { "hostkeyalgorithms", oHostKeyAlgorithms },
+       { "bindaddress", oBindAddress },
+#ifdef ENABLE_PKCS11
+       { "smartcarddevice", oPKCS11Provider },
+       { "pkcs11provider", oPKCS11Provider },
+#else
+       { "smartcarddevice", oUnsupported },
+       { "pkcs11provider", oUnsupported },
+#endif
+       { "clearallforwardings", oClearAllForwardings },
+       { "enablesshkeysign", oEnableSSHKeysign },
+       { "verifyhostkeydns", oVerifyHostKeyDNS },
+       { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
+       { "rekeylimit", oRekeyLimit },
+       { "connecttimeout", oConnectTimeout },
+       { "addressfamily", oAddressFamily },
+       { "serveraliveinterval", oServerAliveInterval },
+       { "serveralivecountmax", oServerAliveCountMax },
+       { "sendenv", oSendEnv },
+       { "controlpath", oControlPath },
+       { "controlmaster", oControlMaster },
+       { "controlpersist", oControlPersist },
+       { "hashknownhosts", oHashKnownHosts },
+       { "tunnel", oTunnel },
+       { "tunneldevice", oTunnelDevice },
+       { "localcommand", oLocalCommand },
+       { "permitlocalcommand", oPermitLocalCommand },
+       { "visualhostkey", oVisualHostKey },
+       { "useroaming", oUseRoaming },
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication",
+           oZeroKnowledgePasswordAuthentication },
+#else
+       { "zeroknowledgepasswordauthentication", oUnsupported },
+#endif
+       { "kexalgorithms", oKexAlgorithms },
+       { "ipqos", oIPQoS },
+       { "requesttty", oRequestTTY },
+       { "protocolkeepalives", oProtocolKeepAlives },
+       { "setuptimeout", oSetupTimeOut },
+
+       { NULL, oBadOption }
+};
+
+/*
+ * Adds a local TCP/IP port forward to options.  Never returns if there is an
+ * error.
+ */
+
+void
+add_local_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+#ifndef NO_IPPORT_RESERVED_CONCEPT
+       extern uid_t original_real_uid;
+       if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
+               fatal("Privileged ports can only be forwarded by root.");
+#endif
+       options->local_forwards = xrealloc(options->local_forwards,
+           options->num_local_forwards + 1,
+           sizeof(*options->local_forwards));
+       fwd = &options->local_forwards[options->num_local_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+}
+
+/*
+ * Adds a remote TCP/IP port forward to options.  Never returns if there is
+ * an error.
+ */
+
+void
+add_remote_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+
+       options->remote_forwards = xrealloc(options->remote_forwards,
+           options->num_remote_forwards + 1,
+           sizeof(*options->remote_forwards));
+       fwd = &options->remote_forwards[options->num_remote_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+       fwd->allocated_port = 0;
+}
+
+static void
+clear_forwardings(Options *options)
+{
+       int i;
+
+       for (i = 0; i < options->num_local_forwards; i++) {
+               if (options->local_forwards[i].listen_host != NULL)
+                       xfree(options->local_forwards[i].listen_host);
+               xfree(options->local_forwards[i].connect_host);
+       }
+       if (options->num_local_forwards > 0) {
+               xfree(options->local_forwards);
+               options->local_forwards = NULL;
+       }
+       options->num_local_forwards = 0;
+       for (i = 0; i < options->num_remote_forwards; i++) {
+               if (options->remote_forwards[i].listen_host != NULL)
+                       xfree(options->remote_forwards[i].listen_host);
+               xfree(options->remote_forwards[i].connect_host);
+       }
+       if (options->num_remote_forwards > 0) {
+               xfree(options->remote_forwards);
+               options->remote_forwards = NULL;
+       }
+       options->num_remote_forwards = 0;
+       options->tun_open = SSH_TUNMODE_NO;
+}
+
+/*
+ * Returns the number of the token pointed to by cp or oBadOption.
+ */
+
+static OpCodes
+parse_token(const char *cp, const char *filename, int linenum)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0)
+                       return keywords[i].opcode;
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return oBadOption;
+}
+
+/*
+ * Processes a single option line as used in the configuration files. This
+ * only sets those values that have not already been set.
+ */
+#define WHITESPACE " \t\r\n"
+
+int
+process_config_line(Options *options, const char *host,
+                   char *line, const char *filename, int linenum,
+                   int *activep)
+{
+       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+       char **cpptr, fwdarg[256];
+       u_int *uintptr, max_entries = 0;
+       int negated, opcode, *intptr, value, value2, scale;
+       LogLevel *log_level_ptr;
+       long long orig, val64;
+       size_t len;
+       Forward fwd;
+
+       /* Strip trailing whitespace */
+       for (len = strlen(line) - 1; len > 0; len--) {
+               if (strchr(WHITESPACE, line[len]) == NULL)
+                       break;
+               line[len] = '\0';
+       }
+
+       s = line;
+       /* Get the keyword. (Each line is supposed to begin with a keyword). */
+       if ((keyword = strdelim(&s)) == NULL)
+               return 0;
+       /* Ignore leading whitespace. */
+       if (*keyword == '\0')
+               keyword = strdelim(&s);
+       if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
+               return 0;
+
+       opcode = parse_token(keyword, filename, linenum);
+
+       switch (opcode) {
+       case oBadOption:
+               /* don't panic, but count bad options */
+               return -1;
+               /* NOTREACHED */
+       case oConnectTimeout:
+               intptr = &options->connection_timeout;
+parse_time:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardAgent:
+               intptr = &options->forward_agent;
+parse_flag:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else
+                       fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardX11:
+               intptr = &options->forward_x11;
+               goto parse_flag;
+
+       case oForwardX11Trusted:
+               intptr = &options->forward_x11_trusted;
+               goto parse_flag;
+       
+       case oForwardX11Timeout:
+               intptr = &options->forward_x11_timeout;
+               goto parse_time;
+
+       case oGatewayPorts:
+               intptr = &options->gateway_ports;
+               goto parse_flag;
+
+       case oExitOnForwardFailure:
+               intptr = &options->exit_on_forward_failure;
+               goto parse_flag;
+
+       case oUsePrivilegedPort:
+               intptr = &options->use_privileged_port;
+               goto parse_flag;
+
+       case oPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case oZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveDevices:
+               charptr = &options->kbd_interactive_devices;
+               goto parse_string;
+
+       case oPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case oRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case oRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case oHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case oChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case oUseBlacklistedKeys:
+               intptr = &options->use_blacklisted_keys;
+               goto parse_flag;
+
+       case oGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case oGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
+       case oGssDelegateCreds:
+               intptr = &options->gss_deleg_creds;
+               goto parse_flag;
+
+       case oGssTrustDns:
+               intptr = &options->gss_trust_dns;
+               goto parse_flag;
+
+       case oGssClientIdentity:
+               charptr = &options->gss_client_identity;
+               goto parse_string;
+
+       case oGssServerIdentity:
+               charptr = &options->gss_server_identity;
+               goto parse_string;
+
+       case oGssRenewalRekey:
+               intptr = &options->gss_renewal_rekey;
+               goto parse_flag;
+
+       case oBatchMode:
+               intptr = &options->batch_mode;
+               goto parse_flag;
+
+       case oCheckHostIP:
+               intptr = &options->check_host_ip;
+               goto parse_flag;
+
+       case oVerifyHostKeyDNS:
+               intptr = &options->verify_host_key_dns;
+               goto parse_yesnoask;
+
+       case oStrictHostKeyChecking:
+               intptr = &options->strict_host_key_checking;
+parse_yesnoask:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no/ask argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "ask") == 0)
+                       value = 2;
+               else
+                       fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCompression:
+               intptr = &options->compression;
+               goto parse_flag;
+
+       case oTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case oNoHostAuthenticationForLocalhost:
+               intptr = &options->no_host_authentication_for_localhost;
+               goto parse_flag;
+
+       case oNumberOfPasswordPrompts:
+               intptr = &options->number_of_password_prompts;
+               goto parse_int;
+
+       case oCompressionLevel:
+               intptr = &options->compression_level;
+               goto parse_int;
+
+       case oRekeyLimit:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               orig = val64 = strtoll(arg, &endofnumber, 10);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               switch (toupper(*endofnumber)) {
+               case '\0':
+                       scale = 1;
+                       break;
+               case 'K':
+                       scale = 1<<10;
+                       break;
+               case 'M':
+                       scale = 1<<20;
+                       break;
+               case 'G':
+                       scale = 1<<30;
+                       break;
+               default:
+                       fatal("%.200s line %d: Invalid RekeyLimit suffix",
+                           filename, linenum);
+               }
+               val64 *= scale;
+               /* detect integer wrap and too-large limits */
+               if ((val64 / scale) != orig || val64 > UINT_MAX)
+                       fatal("%.200s line %d: RekeyLimit too large",
+                           filename, linenum);
+               if (val64 < 16)
+                       fatal("%.200s line %d: RekeyLimit too small",
+                           filename, linenum);
+               if (*activep && options->rekey_limit == -1)
+                       options->rekey_limit = (u_int32_t)val64;
+               break;
+
+       case oIdentityFile:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (*activep) {
+                       intptr = &options->num_identity_files;
+                       if (*intptr >= SSH_MAX_IDENTITY_FILES)
+                               fatal("%.200s line %d: Too many identity files specified (max %d).",
+                                   filename, linenum, SSH_MAX_IDENTITY_FILES);
+                       charptr = &options->identity_files[*intptr];
+                       *charptr = xstrdup(arg);
+                       *intptr = *intptr + 1;
+               }
+               break;
+
+       case oXAuthLocation:
+               charptr=&options->xauth_location;
+               goto parse_string;
+
+       case oUser:
+               charptr = &options->user;
+parse_string:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case oGlobalKnownHostsFile:
+               cpptr = (char **)&options->system_hostfiles;
+               uintptr = &options->num_system_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+parse_char_array:
+               if (*activep && *uintptr == 0) {
+                       while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                               if ((*uintptr) >= max_entries)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               cpptr[(*uintptr)++] = xstrdup(arg);
+                       }
+               }
+               return 0;
+
+       case oUserKnownHostsFile:
+               cpptr = (char **)&options->user_hostfiles;
+               uintptr = &options->num_user_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+               goto parse_char_array;
+
+       case oHostName:
+               charptr = &options->hostname;
+               goto parse_string;
+
+       case oHostKeyAlias:
+               charptr = &options->host_key_alias;
+               goto parse_string;
+
+       case oPreferredAuthentications:
+               charptr = &options->preferred_authentications;
+               goto parse_string;
+
+       case oBindAddress:
+               charptr = &options->bind_address;
+               goto parse_string;
+
+       case oPKCS11Provider:
+               charptr = &options->pkcs11_provider;
+               goto parse_string;
+
+       case oProxyCommand:
+               charptr = &options->proxy_command;
+parse_command:
+               if (s == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               len = strspn(s, WHITESPACE "=");
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(s + len);
+               return 0;
+
+       case oPort:
+               intptr = &options->port;
+parse_int:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+
+               /* Octal, decimal, or hex format? */
+               value = strtol(arg, &endofnumber, 0);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oConnectionAttempts:
+               intptr = &options->connection_attempts;
+               goto parse_int;
+
+       case oCipher:
+               intptr = &options->cipher;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = cipher_number(arg);
+               if (value == -1)
+                       fatal("%.200s line %d: Bad cipher '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCiphers:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case oMacs:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case oKexAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case oHostKeyAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!key_names_valid2(arg))
+                       fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->hostkeyalgorithms == NULL)
+                       options->hostkeyalgorithms = xstrdup(arg);
+               break;
+
+       case oProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%.200s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case oLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&s);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case oLocalForward:
+       case oRemoteForward:
+       case oDynamicForward:
+               arg = strdelim(&s);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%.200s line %d: Missing port argument.",
+                           filename, linenum);
+
+               if (opcode == oLocalForward ||
+                   opcode == oRemoteForward) {
+                       arg2 = strdelim(&s);
+                       if (arg2 == NULL || *arg2 == '\0')
+                               fatal("%.200s line %d: Missing target argument.",
+                                   filename, linenum);
+
+                       /* construct a string for parse_forward */
+                       snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
+               } else if (opcode == oDynamicForward) {
+                       strlcpy(fwdarg, arg, sizeof(fwdarg));
+               }
+
+               if (parse_forward(&fwd, fwdarg,
+                   opcode == oDynamicForward ? 1 : 0,
+                   opcode == oRemoteForward ? 1 : 0) == 0)
+                       fatal("%.200s line %d: Bad forwarding specification.",
+                           filename, linenum);
+
+               if (*activep) {
+                       if (opcode == oLocalForward ||
+                           opcode == oDynamicForward)
+                               add_local_forward(options, &fwd);
+                       else if (opcode == oRemoteForward)
+                               add_remote_forward(options, &fwd);
+               }
+               break;
+
+       case oClearAllForwardings:
+               intptr = &options->clear_forwardings;
+               goto parse_flag;
+
+       case oHost:
+               *activep = 0;
+               arg2 = NULL;
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       negated = *arg == '!';
+                       if (negated)
+                               arg++;
+                       if (match_pattern(host, arg)) {
+                               if (negated) {
+                                       debug("%.200s line %d: Skipping Host "
+                                           "block because of negated match "
+                                           "for %.100s", filename, linenum,
+                                           arg);
+                                       *activep = 0;
+                                       break;
+                               }
+                               if (!*activep)
+                                       arg2 = arg; /* logged below */
+                               *activep = 1;
+                       }
+               }
+               if (*activep)
+                       debug("%.200s line %d: Applying options for %.100s",
+                           filename, linenum, arg2);
+               /* Avoid garbage check below, as strdelim is done. */
+               return 0;
+
+       case oEscapeChar:
+               intptr = &options->escape_char;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] == '^' && arg[2] == 0 &&
+                   (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
+                       value = (u_char) arg[1] & 31;
+               else if (strlen(arg) == 1)
+                       value = (u_char) arg[0];
+               else if (strcmp(arg, "none") == 0)
+                       value = SSH_ESCAPECHAR_NONE;
+               else {
+                       fatal("%.200s line %d: Bad escape character.",
+                           filename, linenum);
+                       /* NOTREACHED */
+                       value = 0;      /* Avoid compiler warning. */
+               }
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oAddressFamily:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing address family.",
+                           filename, linenum);
+               intptr = &options->address_family;
+               if (strcasecmp(arg, "inet") == 0)
+                       value = AF_INET;
+               else if (strcasecmp(arg, "inet6") == 0)
+                       value = AF_INET6;
+               else if (strcasecmp(arg, "any") == 0)
+                       value = AF_UNSPEC;
+               else
+                       fatal("Unsupported AddressFamily \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oEnableSSHKeysign:
+               intptr = &options->enable_ssh_keysign;
+               goto parse_flag;
+
+       case oIdentitiesOnly:
+               intptr = &options->identities_only;
+               goto parse_flag;
+
+       case oServerAliveInterval:
+       case oProtocolKeepAlives: /* Debian-specific compatibility alias */
+       case oSetupTimeOut:       /* Debian-specific compatibility alias */
+               intptr = &options->server_alive_interval;
+               goto parse_time;
+
+       case oServerAliveCountMax:
+               intptr = &options->server_alive_count_max;
+               goto parse_int;
+
+       case oSendEnv:
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (!*activep)
+                               continue;
+                       if (options->num_send_env >= MAX_SEND_ENV)
+                               fatal("%s line %d: too many send env.",
+                                   filename, linenum);
+                       options->send_env[options->num_send_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case oControlPath:
+               charptr = &options->control_path;
+               goto parse_string;
+
+       case oControlMaster:
+               intptr = &options->control_master;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlMaster argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = SSHCTL_MASTER_YES;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = SSHCTL_MASTER_NO;
+               else if (strcmp(arg, "auto") == 0)
+                       value = SSHCTL_MASTER_AUTO;
+               else if (strcmp(arg, "ask") == 0)
+                       value = SSHCTL_MASTER_ASK;
+               else if (strcmp(arg, "autoask") == 0)
+                       value = SSHCTL_MASTER_AUTO_ASK;
+               else
+                       fatal("%.200s line %d: Bad ControlMaster argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oControlPersist:
+               /* no/false/yes/true, or a time spec */
+               intptr = &options->control_persist;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlPersist"
+                           " argument.", filename, linenum);
+               value = 0;
+               value2 = 0;     /* timeout */
+               if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if ((value2 = convtime(arg)) >= 0)
+                       value = 1;
+               else
+                       fatal("%.200s line %d: Bad ControlPersist argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1) {
+                       *intptr = value;
+                       options->control_persist_timeout = value2;
+               }
+               break;
+
+       case oHashKnownHosts:
+               intptr = &options->hash_known_hosts;
+               goto parse_flag;
+
+       case oTunnel:
+               intptr = &options->tun_open;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcasecmp(arg, "ethernet") == 0)
+                       value = SSH_TUNMODE_ETHERNET;
+               else if (strcasecmp(arg, "point-to-point") == 0)
+                       value = SSH_TUNMODE_POINTOPOINT;
+               else if (strcasecmp(arg, "yes") == 0)
+                       value = SSH_TUNMODE_DEFAULT;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = SSH_TUNMODE_NO;
+               else
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*activep)
+                       *intptr = value;
+               break;
+
+       case oTunnelDevice:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = a2tun(arg, &value2);
+               if (value == SSH_TUNID_ERR)
+                       fatal("%.200s line %d: Bad tun device.", filename, linenum);
+               if (*activep) {
+                       options->tun_local = value;
+                       options->tun_remote = value2;
+               }
+               break;
+
+       case oLocalCommand:
+               charptr = &options->local_command;
+               goto parse_command;
+
+       case oPermitLocalCommand:
+               intptr = &options->permit_local_command;
+               goto parse_flag;
+
+       case oVisualHostKey:
+               intptr = &options->visual_host_key;
+               goto parse_flag;
+
+       case oIPQoS:
+               arg = strdelim(&s);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&s);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case oUseRoaming:
+               intptr = &options->use_roaming;
+               goto parse_flag;
+
+       case oRequestTTY:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               intptr = &options->request_tty;
+               if (strcasecmp(arg, "yes") == 0)
+                       value = REQUEST_TTY_YES;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = REQUEST_TTY_NO;
+               else if (strcasecmp(arg, "force") == 0)
+                       value = REQUEST_TTY_FORCE;
+               else if (strcasecmp(arg, "auto") == 0)
+                       value = REQUEST_TTY_AUTO;
+               else
+                       fatal("Unsupported RequestTTY \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oDeprecated:
+               debug("%s line %d: Deprecated option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       case oUnsupported:
+               error("%s line %d: Unsupported option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       default:
+               fatal("process_config_line: Unimplemented opcode %d", opcode);
+       }
+
+       /* Check that there is no garbage at end of line. */
+       if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+               fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       }
+       return 0;
+}
+
+
+/*
+ * Reads the config file and modifies the options accordingly.  Options
+ * should already be initialized before this call.  This never returns if
+ * there is an error.  If the file does not exist, this returns 0.
+ */
+
+int
+read_config_file(const char *filename, const char *host, Options *options,
+    int checkperm)
+{
+       FILE *f;
+       char line[1024];
+       int active, linenum;
+       int bad_options = 0;
+
+       if ((f = fopen(filename, "r")) == NULL)
+               return 0;
+
+       if (checkperm) {
+               struct stat sb;
+
+               if (fstat(fileno(f), &sb) == -1)
+                       fatal("fstat %s: %s", filename, strerror(errno));
+               if (!secure_permissions(&sb, getuid()))
+                       fatal("Bad owner or permissions on %s", filename);
+       }
+
+       debug("Reading configuration data %.200s", filename);
+
+       /*
+        * Mark that we are now processing the options.  This flag is turned
+        * on/off by Host specifications.
+        */
+       active = 1;
+       linenum = 0;
+       while (fgets(line, sizeof(line), f)) {
+               /* Update line number counter. */
+               linenum++;
+               if (process_config_line(options, host, line, filename, linenum, &active) != 0)
+                       bad_options++;
+       }
+       fclose(f);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+       return 1;
+}
+
+/*
+ * Initializes options to special values that indicate that they have not yet
+ * been set.  Read_config_file will only set options with this value. Options
+ * are processed in the following order: command line, user config file,
+ * system config file.  Last, fill_default_options is called.
+ */
+
+void
+initialize_options(Options * options)
+{
+       memset(options, 'X', sizeof(*options));
+       options->forward_agent = -1;
+       options->forward_x11 = -1;
+       options->forward_x11_trusted = -1;
+       options->forward_x11_timeout = -1;
+       options->exit_on_forward_failure = -1;
+       options->xauth_location = NULL;
+       options->gateway_ports = -1;
+       options->use_privileged_port = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->gss_authentication = -1;
+       options->gss_keyex = -1;
+       options->gss_deleg_creds = -1;
+       options->gss_trust_dns = -1;
+       options->gss_renewal_rekey = -1;
+       options->gss_client_identity = NULL;
+       options->gss_server_identity = NULL;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->kbd_interactive_devices = NULL;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->use_blacklisted_keys = -1;
+       options->batch_mode = -1;
+       options->check_host_ip = -1;
+       options->strict_host_key_checking = -1;
+       options->compression = -1;
+       options->tcp_keep_alive = -1;
+       options->compression_level = -1;
+       options->port = -1;
+       options->address_family = -1;
+       options->connection_attempts = -1;
+       options->connection_timeout = -1;
+       options->number_of_password_prompts = -1;
+       options->cipher = -1;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->hostkeyalgorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->num_identity_files = 0;
+       options->hostname = NULL;
+       options->host_key_alias = NULL;
+       options->proxy_command = NULL;
+       options->user = NULL;
+       options->escape_char = -1;
+       options->num_system_hostfiles = 0;
+       options->num_user_hostfiles = 0;
+       options->local_forwards = NULL;
+       options->num_local_forwards = 0;
+       options->remote_forwards = NULL;
+       options->num_remote_forwards = 0;
+       options->clear_forwardings = -1;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->preferred_authentications = NULL;
+       options->bind_address = NULL;
+       options->pkcs11_provider = NULL;
+       options->enable_ssh_keysign = - 1;
+       options->no_host_authentication_for_localhost = - 1;
+       options->identities_only = - 1;
+       options->rekey_limit = - 1;
+       options->verify_host_key_dns = -1;
+       options->server_alive_interval = -1;
+       options->server_alive_count_max = -1;
+       options->num_send_env = 0;
+       options->control_path = NULL;
+       options->control_master = -1;
+       options->control_persist = -1;
+       options->control_persist_timeout = 0;
+       options->hash_known_hosts = -1;
+       options->tun_open = -1;
+       options->tun_local = -1;
+       options->tun_remote = -1;
+       options->local_command = NULL;
+       options->permit_local_command = -1;
+       options->use_roaming = -1;
+       options->visual_host_key = -1;
+       options->zero_knowledge_password_authentication = -1;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+       options->request_tty = -1;
+}
+
+/*
+ * Called after processing other sources of option data, this fills those
+ * options for which no value has been specified with their default values.
+ */
+
+void
+fill_default_options(Options * options)
+{
+       int len;
+
+       if (options->forward_agent == -1)
+               options->forward_agent = 0;
+       if (options->forward_x11 == -1)
+               options->forward_x11 = 0;
+       if (options->forward_x11_trusted == -1)
+               options->forward_x11_trusted = 0;
+       if (options->forward_x11_timeout == -1)
+               options->forward_x11_timeout = 1200;
+       if (options->exit_on_forward_failure == -1)
+               options->exit_on_forward_failure = 0;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->use_privileged_port == -1)
+               options->use_privileged_port = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
+       if (options->gss_deleg_creds == -1)
+               options->gss_deleg_creds = 0;
+       if (options->gss_trust_dns == -1)
+               options->gss_trust_dns = 0;
+       if (options->gss_renewal_rekey == -1)
+               options->gss_renewal_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 1;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->use_blacklisted_keys == -1)
+               options->use_blacklisted_keys = 0;
+       if (options->batch_mode == -1)
+               options->batch_mode = 0;
+       if (options->check_host_ip == -1)
+               options->check_host_ip = 1;
+       if (options->strict_host_key_checking == -1)
+               options->strict_host_key_checking = 2;  /* 2 is default */
+       if (options->compression == -1)
+               options->compression = 0;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->compression_level == -1)
+               options->compression_level = 6;
+       if (options->port == -1)
+               options->port = 0;      /* Filled in ssh_connect. */
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (options->connection_attempts == -1)
+               options->connection_attempts = 1;
+       if (options->number_of_password_prompts == -1)
+               options->number_of_password_prompts = 3;
+       /* Selected in ssh_login(). */
+       if (options->cipher == -1)
+               options->cipher = SSH_CIPHER_NOT_SET;
+       /* options->ciphers, default set in myproposals.h */
+       /* options->macs, default set in myproposals.h */
+       /* options->kex_algorithms, default set in myproposals.h */
+       /* options->hostkeyalgorithms, default set in myproposals.h */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_identity_files == 0) {
+               if (options->protocol & SSH_PROTO_1) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
+               }
+               if (options->protocol & SSH_PROTO_2) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
+
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
+#ifdef OPENSSL_HAS_ECC
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
+#endif
+               }
+       }
+       if (options->escape_char == -1)
+               options->escape_char = '~';
+       if (options->num_system_hostfiles == 0) {
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
+       }
+       if (options->num_user_hostfiles == 0) {
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE);
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE2);
+       }
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->clear_forwardings == 1)
+               clear_forwardings(options);
+       if (options->no_host_authentication_for_localhost == - 1)
+               options->no_host_authentication_for_localhost = 0;
+       if (options->identities_only == -1)
+               options->identities_only = 0;
+       if (options->enable_ssh_keysign == -1)
+               options->enable_ssh_keysign = 0;
+       if (options->rekey_limit == -1)
+               options->rekey_limit = 0;
+       if (options->verify_host_key_dns == -1)
+               options->verify_host_key_dns = 0;
+       if (options->server_alive_interval == -1) {
+               /* in batch mode, default is 5mins */
+               if (options->batch_mode == 1)
+                       options->server_alive_interval = 300;
+               else
+                       options->server_alive_interval = 0;
+       }
+       if (options->server_alive_count_max == -1)
+               options->server_alive_count_max = 3;
+       if (options->control_master == -1)
+               options->control_master = 0;
+       if (options->control_persist == -1) {
+               options->control_persist = 0;
+               options->control_persist_timeout = 0;
+       }
+       if (options->hash_known_hosts == -1)
+               options->hash_known_hosts = 0;
+       if (options->tun_open == -1)
+               options->tun_open = SSH_TUNMODE_NO;
+       if (options->tun_local == -1)
+               options->tun_local = SSH_TUNID_ANY;
+       if (options->tun_remote == -1)
+               options->tun_remote = SSH_TUNID_ANY;
+       if (options->permit_local_command == -1)
+               options->permit_local_command = 0;
+       if (options->use_roaming == -1)
+               options->use_roaming = 1;
+       if (options->visual_host_key == -1)
+               options->visual_host_key = 0;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+       if (options->request_tty == -1)
+               options->request_tty = REQUEST_TTY_AUTO;
+       /* options->local_command should not be set by default */
+       /* options->proxy_command should not be set by default */
+       /* options->user will be set in the main program if appropriate */
+       /* options->hostname will be set in the main program if appropriate */
+       /* options->host_key_alias should not be set by default */
+       /* options->preferred_authentications will be set in ssh */
+}
+
+/*
+ * parse_forward
+ * parses a string containing a port forwarding specification of the form:
+ *   dynamicfwd == 0
+ *     [listenhost:]listenport:connecthost:connectport
+ *   dynamicfwd == 1
+ *     [listenhost:]listenport
+ * returns number of arguments parsed or zero on error
+ */
+int
+parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
+{
+       int i;
+       char *p, *cp, *fwdarg[4];
+
+       memset(fwd, '\0', sizeof(*fwd));
+
+       cp = p = xstrdup(fwdspec);
+
+       /* skip leading spaces */
+       while (isspace(*cp))
+               cp++;
+
+       for (i = 0; i < 4; ++i)
+               if ((fwdarg[i] = hpdelim(&cp)) == NULL)
+                       break;
+
+       /* Check for trailing garbage */
+       if (cp != NULL)
+               i = 0;  /* failure */
+
+       switch (i) {
+       case 1:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 2:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 3:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
+               fwd->connect_port = a2port(fwdarg[2]);
+               break;
+
+       case 4:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
+               fwd->connect_port = a2port(fwdarg[3]);
+               break;
+       default:
+               i = 0; /* failure */
+       }
+
+       xfree(p);
+
+       if (dynamicfwd) {
+               if (!(i == 1 || i == 2))
+                       goto fail_free;
+       } else {
+               if (!(i == 3 || i == 4))
+                       goto fail_free;
+               if (fwd->connect_port <= 0)
+                       goto fail_free;
+       }
+
+       if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
+               goto fail_free;
+
+       if (fwd->connect_host != NULL &&
+           strlen(fwd->connect_host) >= NI_MAXHOST)
+               goto fail_free;
+       if (fwd->listen_host != NULL &&
+           strlen(fwd->listen_host) >= NI_MAXHOST)
+               goto fail_free;
+
+
+       return (i);
+
+ fail_free:
+       if (fwd->connect_host != NULL) {
+               xfree(fwd->connect_host);
+               fwd->connect_host = NULL;
+       }
+       if (fwd->listen_host != NULL) {
+               xfree(fwd->listen_host);
+               fwd->listen_host = NULL;
+       }
+       return (0);
+}
diff --git a/.pc/debian-config.patch/ssh_config b/.pc/debian-config.patch/ssh_config
new file mode 100644 (file)
index 0000000..2c06ba7
--- /dev/null
@@ -0,0 +1,49 @@
+#      $OpenBSD: ssh_config,v 1.26 2010/01/11 01:39:46 dtucker Exp $
+
+# This is the ssh client system-wide configuration file.  See
+# ssh_config(5) for more information.  This file provides defaults for
+# users, and the values can be changed in per-user configuration files
+# or on the command line.
+
+# Configuration data is parsed as follows:
+#  1. command line options
+#  2. user-specific file
+#  3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# Site-wide defaults for some commonly used options.  For a comprehensive
+# list of available options, their meanings and defaults, please see the
+# ssh_config(5) man page.
+
+# Host *
+#   ForwardAgent no
+#   ForwardX11 no
+#   RhostsRSAAuthentication no
+#   RSAAuthentication yes
+#   PasswordAuthentication yes
+#   HostbasedAuthentication no
+#   GSSAPIAuthentication no
+#   GSSAPIDelegateCredentials no
+#   GSSAPIKeyExchange no
+#   GSSAPITrustDNS no
+#   BatchMode no
+#   CheckHostIP yes
+#   AddressFamily any
+#   ConnectTimeout 0
+#   StrictHostKeyChecking ask
+#   IdentityFile ~/.ssh/identity
+#   IdentityFile ~/.ssh/id_rsa
+#   IdentityFile ~/.ssh/id_dsa
+#   Port 22
+#   Protocol 2,1
+#   Cipher 3des
+#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
+#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
+#   EscapeChar ~
+#   Tunnel no
+#   TunnelDevice any:any
+#   PermitLocalCommand no
+#   VisualHostKey no
+#   ProxyCommand ssh -q -W %h:%p gateway.example.com
diff --git a/.pc/debian-config.patch/ssh_config.5 b/.pc/debian-config.patch/ssh_config.5
new file mode 100644 (file)
index 0000000..4dc65d4
--- /dev/null
@@ -0,0 +1,1368 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Nm ~/.ssh/config
+.Nm /etc/ssh/ssh_config
+.Sh DESCRIPTION
+.Xr ssh 1
+obtains configuration data from the following sources in
+the following order:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+command-line options
+.It
+user's configuration file
+.Pq Pa ~/.ssh/config
+.It
+system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+.El
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections separated by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp ,
+and
+.Nm sftp
+.Fl o
+option.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+If more than one pattern is provided, they should be separated by whitespace.
+A single
+.Ql *
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e. the name is not converted to
+a canonicalized host name before matching).
+.Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm AddressFamily
+Specifies which address family to use when connecting.
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+In addition, the
+.Cm ServerAliveInterval
+option will be set to 300 seconds by default.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password,
+and where it is desirable to detect a broken network swiftly.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Use the specified address on the local machine as the source address of
+the connection.
+Only useful on systems with more than one address.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge-response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Xr ssh 1
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote, and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared.
+This option is primarily useful when used from the
+.Xr ssh 1
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout (in seconds) used when connecting to the
+SSH server, instead of using the default system TCP timeout.
+This value is used only when the target is down or really unreachable,
+not when it refuses the connection.
+.It Cm ControlMaster
+Enables the sharing of multiple sessions over a single network connection.
+When set to
+.Dq yes ,
+.Xr ssh 1
+will listen for connections on a control socket specified using the
+.Cm ControlPath
+argument.
+Additional sessions can connect to this socket using the same
+.Cm ControlPath
+with
+.Cm ControlMaster
+set to
+.Dq no
+(the default).
+These sessions will try to reuse the master instance's network connection
+rather than initiating new ones, but will fall back to connecting normally
+if the control socket does not exist, or is not listening.
+.Pp
+Setting this to
+.Dq ask
+will cause ssh
+to listen for control connections, but require confirmation using the
+.Ev SSH_ASKPASS
+program before they are accepted (see
+.Xr ssh-add 1
+for details).
+If the
+.Cm ControlPath
+cannot be opened,
+ssh will continue without connecting to a master instance.
+.Pp
+X11 and
+.Xr ssh-agent 1
+forwarding is supported over these multiplexed connections, however the
+display and agent forwarded will be the one belonging to the master
+connection i.e. it is not possible to forward multiple displays or agents.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
+.It Cm ControlPath
+Specify the path to the control socket used for connection sharing as described
+in the
+.Cm ControlMaster
+section above or the string
+.Dq none
+to disable connection sharing.
+In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
+.Ql %l
+will be substituted by the local host name (including any domain name),
+.Ql %h
+will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
+.Ql %p
+the port,
+.Ql %r
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+at least %h, %p, and %r.
+This ensures that shared connections are uniquely identified.
+.It Cm ControlPersist
+When used in conjunction with
+.Cm ControlMaster ,
+specifies that the master connection should remain open
+in the background (waiting for future client connections)
+after the initial client connection has been closed.
+If set to
+.Dq no ,
+then the master connection will not be placed into the background,
+and will close as soon as the initial client connection is closed.
+If set to
+.Dq yes ,
+then the master connection will remain in the background indefinitely
+(until killed or closed via a mechanism such as the
+.Xr ssh 1
+.Dq Fl O No exit
+option).
+If set to a time in seconds, or a time in any of the formats documented in
+.Xr sshd_config 5 ,
+then the backgrounded master connection will automatically terminate
+after it has remained idle (with no client connections) for the
+specified time.
+.It Cm DynamicForward
+Specifies that a TCP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+.Pp
+The argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port .
+.Sm on
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.Pp
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Xr ssh 1
+will act as a SOCKS server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm EnableSSHKeysign
+Setting this option to
+.Dq yes
+in the global client configuration file
+.Pa /etc/ssh/ssh_config
+enables the use of the helper program
+.Xr ssh-keysign 8
+during
+.Cm HostbasedAuthentication .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option should be placed in the non-hostspecific section.
+See
+.Xr ssh-keysign 8
+for more information.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ExitOnForwardFailure
+Specifies whether
+.Xr ssh 1
+should terminate the connection if it cannot set up all requested
+dynamic, tunnel, local, and remote port forwardings.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's Unix-domain socket)
+can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X11 authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring
+if the
+.Cm ForwardX11Trusted
+option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
+.It Cm ForwardX11Trusted
+If this option is set to
+.Dq yes ,
+remote X11 clients will have full access to the original X11 display.
+.Pp
+If this option is set to
+.Dq no ,
+remote X11 clients will be considered untrusted and prevented
+from stealing or tampering with data belonging to trusted X11
+clients.
+Furthermore, the
+.Xr xauth 1
+token used for the session will be set to expire after 20 minutes.
+Remote clients will be refused access after this time.
+.Pp
+The default is
+.Dq no .
+.Pp
+See the X11 SECURITY extension specification for full details on
+the restrictions imposed on untrusted clients.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Xr ssh 1
+binds local port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
+.It Cm GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when 
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
+.It Cm GSSAPIDelegateCredentials
+Forward (delegate) credentials to the server.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI.
+.It Cm HashKnownHosts
+Indicates that
+.Xr ssh 1
+should hash host names and addresses when they are added to
+.Pa ~/.ssh/known_hosts .
+These hashed names may be used normally by
+.Xr ssh 1
+and
+.Xr sshd 8 ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+The default is
+.Dq no .
+Note that existing names and addresses in known hosts files
+will not be converted automatically,
+but may be manually hashed using
+.Xr ssh-keygen 1 .
+Use of this option may break facilities such as tab-completion that rely
+on being able to read unhashed host names from
+.Pa ~/.ssh/known_hosts .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
+ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-rsa,ssh-dss
+.Ed
+.Pp
+If hostkeys are known for the destination host then this default is modified
+to prefer their algorithms.
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling SSH connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+If the hostname contains the character sequence
+.Ql %h ,
+then this will be replaced with the host name specified on the command line
+(this is useful for manipulating unqualified names).
+The default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentitiesOnly
+Specifies that
+.Xr ssh 1
+should only use the authentication identity files configured in the
+.Nm
+files,
+even if
+.Xr ssh-agent 1
+offers more identities.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option is intended for situations where ssh-agent
+offers many different identities.
+The default is
+.Dq no .
+.It Cm IdentityFile
+Specifies a file from which the user's DSA, ECDSA or DSA authentication
+identity is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+.Xr ssh 1
+will try to load certificate information from the filename obtained by
+appending
+.Pa -cert.pub
+to the path of a specified
+.Cm IdentityFile .
+.Pp
+The file name may use the tilde
+syntax to refer to a user's home directory or one of the following
+escape characters:
+.Ql %d
+(local user's home directory),
+.Ql %u
+(local user name),
+.Ql %l
+(local host name),
+.Ql %h
+(remote host name) or
+.Ql %r
+(remote user name).
+.Pp
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KbdInteractiveAuthentication
+Specifies whether to use keyboard-interactive authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm KbdInteractiveDevices
+Specifies the list of methods to use in keyboard-interactive authentication.
+Multiple method names must be comma-separated.
+The default is to use the server specified list.
+The methods available vary depending on what the server supports.
+For an OpenSSH server,
+it may be zero or more of:
+.Dq bsdauth ,
+.Dq pam ,
+and
+.Dq skey .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
+diffie-hellman-group-exchange-sha256,
+diffie-hellman-group-exchange-sha1,
+diffie-hellman-group14-sha1,
+diffie-hellman-group1-sha1
+.Ed
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+The following escape character substitutions will be performed:
+.Ql %d
+(local user's home directory),
+.Ql %h
+(remote host name),
+.Ql %l
+(local host name),
+.Ql %n
+(host name as provided on the command line),
+.Ql %p
+(remote port),
+.Ql %r
+(remote user name) or
+.Ql %u
+(local user name).
+.Pp
+The command is run synchronously and does not have access to the
+session of the
+.Xr ssh 1
+that spawned it.
+It should not be used for interactive commands.
+.Pp
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
+.It Cm LocalForward
+Specifies that a TCP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional forwardings can be
+given on the command line.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr ssh 1 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+The default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic !\& Ns Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm PKCS11Provider
+Specifies which PKCS#11 provider to use.
+The argument to this keyword is the PKCS#11 shared library
+.Xr ssh 1
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Cm Port
+Specifies the port number to connect on the remote host.
+The default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods.
+This allows a client to prefer one method (e.g.\&
+.Cm keyboard-interactive )
+over another method (e.g.\&
+.Cm password ) .
+The default is:
+.Bd -literal -offset indent
+gssapi-with-mic,hostbased,publickey,
+keyboard-interactive,password
+.Ed
+.It Cm Protocol
+Specifies the protocol versions
+.Xr ssh 1
+should support in order of preference.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+When this option is set to
+.Dq 2,1
+.Nm ssh
+will try version 2 and fall back to version 1
+if version 2 is not available.
+The default is
+.Sq 2 .
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+the user's shell.
+In the command string, any occurrence of
+.Ql %h
+will be substituted by the host name to
+connect,
+.Ql %p
+by the port, and
+.Ql %r
+by the remote user name.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Setting the command to
+.Dq none
+disables this option entirely.
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+This directive is useful in conjunction with
+.Xr nc 1
+and its proxy support.
+For example, the following directive would connect via an HTTP proxy at
+192.0.2.0:
+.Bd -literal -offset 3n
+ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
+.Ed
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RekeyLimit
+Specifies the maximum amount of data that may be transmitted before the
+session key is renegotiated.
+The argument is the number of bytes, with an optional suffix of
+.Sq K ,
+.Sq M ,
+or
+.Sq G
+to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
+The default is between
+.Sq 1G
+and
+.Sq 4G ,
+depending on the cipher.
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+.Pp
+If the
+.Ar bind_address
+is not specified, the default is to only bind to loopback addresses.
+If the
+.Ar bind_address
+is
+.Ql *
+or an empty string, then the forwarding is requested to listen on all
+interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Xr ssh 1
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SendEnv
+Specifies what variables from the local
+.Xr environ 7
+should be sent to the server.
+Note that environment passing is only supported for protocol 2.
+The server must also support it, and the server must be configured to
+accept these environment variables.
+Refer to
+.Cm AcceptEnv
+in
+.Xr sshd_config 5
+for how to configure the server.
+Variables are specified by name, which may contain wildcard characters.
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm SendEnv
+directives.
+The default is not to send any environment variables.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm ServerAliveCountMax
+Sets the number of server alive messages (see below) which may be
+sent without
+.Xr ssh 1
+receiving any messages back from the server.
+If this threshold is reached while server alive messages are being sent,
+ssh will disconnect from the server, terminating the session.
+It is important to note that the use of server alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The server alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The server alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If, for example,
+.Cm ServerAliveInterval
+(see below) is set to 15 and
+.Cm ServerAliveCountMax
+is left at the default, if the server becomes unresponsive,
+ssh will disconnect after approximately 45 seconds.
+This option applies to protocol version 2 only; in protocol version
+1 there is no mechanism to request a response from the server to the
+server alive messages, so disconnection is the responsibility of the TCP
+stack.
+.It Cm ServerAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the server,
+.Xr ssh 1
+will send a message through the encrypted
+channel to request a response from the server.
+The default
+is 0, indicating that these messages will not be sent to the server,
+or 300 if the
+.Cm BatchMode
+option is set.
+This option applies to protocol version 2 only.
+.Cm ProtocolKeepAlives
+and
+.Cm SetupTimeOut
+are Debian-specific compatibility aliases for this option.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will never automatically add host keys to the
+.Pa ~/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+though it can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained or when connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+ssh will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+ssh will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+This option only uses TCP keepalives (as opposed to using ssh level
+keepalives), so takes a long time to notice when the connection dies.
+As such, you probably want
+the
+.Cm ServerAliveInterval
+option as well.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm Tunnel
+Request
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2),
+or
+.Dq no .
+Specifying
+.Dq yes
+requests the default tunnel mode, which is
+.Dq point-to-point .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Specifies the
+.Xr tun 4
+devices to open on the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The argument must be
+.Sm off
+.Ar local_tun Op : Ar remote_tun .
+.Sm on
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+The default is
+.Dq any:any .
+.It Cm UseBlacklistedKeys
+Specifies whether
+.Xr ssh 1
+should use keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 )
+for authentication.
+If
+.Dq yes ,
+then attempts to use compromised keys for authentication will be logged but
+accepted.
+It is strongly recommended that this be used only to install new authorized
+keys on the remote system, and even then only with the utmost care.
+If
+.Dq no ,
+then attempts to use compromised keys for authentication will be prevented.
+The default is
+.Dq no .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+If set to
+.Dq yes ,
+.Xr ssh 1
+must be setuid root.
+Note that this option must be set to
+.Dq yes
+for
+.Cm RhostsRSAAuthentication
+with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
+.It Cm VerifyHostKeyDNS
+Specifies whether to verify the remote key using DNS and SSHFP resource
+records.
+If this option is set to
+.Dq yes ,
+the client will implicitly trust keys that match a secure fingerprint
+from DNS.
+Insecure fingerprints will be handled as if this option was set to
+.Dq ask .
+If this option is set to
+.Dq ask ,
+information on fingerprint match will be displayed, but the user will still
+need to confirm new host keys according to the
+.Cm StrictHostKeyChecking
+option.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.Pp
+See also
+.Sx VERIFYING HOST KEYS
+in
+.Xr ssh 1 .
+.It Cm VisualHostKey
+If this flag is set to
+.Dq yes ,
+an ASCII art representation of the remote host key fingerprint is
+printed in addition to the hex fingerprint string at login and
+for unknown host keys.
+If this flag is set to
+.Dq no ,
+no fingerprint strings are printed at login and
+only the hex fingerprint string will be printed for unknown host keys.
+The default is
+.Dq no .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh PATTERNS
+A
+.Em pattern
+consists of zero or more non-whitespace characters,
+.Sq *
+(a wildcard that matches zero or more characters),
+or
+.Sq ?\&
+(a wildcard that matches exactly one character).
+For example, to specify a set of declarations for any host in the
+.Dq .co.uk
+set of domains,
+the following pattern could be used:
+.Pp
+.Dl Host *.co.uk
+.Pp
+The following pattern
+would match any host in the 192.168.0.[0-9] network range:
+.Pp
+.Dl Host 192.168.0.?
+.Pp
+A
+.Em pattern-list
+is a comma-separated list of patterns.
+Patterns within pattern-lists may be negated
+by preceding them with an exclamation mark
+.Pq Sq !\& .
+For example,
+to allow a key to be used from anywhere within an organisation
+except from the
+.Dq dialup
+pool,
+the following entry (in authorized_keys) could be used:
+.Pp
+.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the SSH client.
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+It may be group-writable provided that the group in question contains only
+the user.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh SEE ALSO
+.Xr ssh 1
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/debian-config.patch/sshd_config b/.pc/debian-config.patch/sshd_config
new file mode 100644 (file)
index 0000000..d02d7a7
--- /dev/null
@@ -0,0 +1,123 @@
+#      $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
+
+# This is the sshd server system-wide configuration file.  See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented.  Uncommented options override the
+# default value.
+
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# The default requires explicit activation of protocol 1
+#Protocol 2
+
+# HostKey for protocol version 1
+#HostKey /etc/ssh/ssh_host_key
+# HostKeys for protocol version 2
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_ecdsa_key
+
+# Lifetime and size of ephemeral version 1 server key
+#KeyRegenerationInterval 1h
+#ServerKeyBits 1024
+
+# Logging
+# obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile     .ssh/authorized_keys
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
+# similar for protocol version 2
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+#GSSAPIStrictAcceptorCheck yes
+#GSSAPIKeyExchange no
+
+# Set this to 'yes' to enable PAM authentication, account processing, 
+# and session processing. If this is enabled, PAM authentication will 
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication.  Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+#UsePAM no
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+#UseLogin no
+#UsePrivilegeSeparation yes
+#PermitUserEnvironment no
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#UseDNS yes
+#PidFile /var/run/sshd.pid
+#MaxStartups 10
+#PermitTunnel no
+#ChrootDirectory none
+
+# no default banner path
+#Banner none
+
+# override default of no subsystems
+Subsystem      sftp    /usr/libexec/sftp-server
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+#      X11Forwarding no
+#      AllowTcpForwarding no
+#      ForceCommand cvs server
diff --git a/.pc/debian-config.patch/sshd_config.5 b/.pc/debian-config.patch/sshd_config.5
new file mode 100644 (file)
index 0000000..35cb363
--- /dev/null
@@ -0,0 +1,1264 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd_config.5,v 1.135 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD_CONFIG 5
+.Os
+.Sh NAME
+.Nm sshd_config
+.Nd OpenSSH SSH daemon configuration file
+.Sh SYNOPSIS
+.Nm /etc/ssh/sshd_config
+.Sh DESCRIPTION
+.Xr sshd 8
+reads configuration data from
+.Pa /etc/ssh/sshd_config
+(or the file specified with
+.Fl f
+on the command line).
+The file contains keyword-argument pairs, one per line.
+Lines starting with
+.Ql #
+and empty lines are interpreted as comments.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm AcceptEnv
+Specifies what environment variables sent by the client will be copied into
+the session's
+.Xr environ 7 .
+See
+.Cm SendEnv
+in
+.Xr ssh_config 5
+for how to configure the client.
+Note that environment passing is only supported for protocol 2.
+Variables are specified by name, which may contain the wildcard characters
+.Ql *
+and
+.Ql \&? .
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm AcceptEnv
+directives.
+Be warned that some environment variables could be used to bypass restricted
+user environments.
+For this reason, care should be taken in the use of this directive.
+The default is not to accept any environment variables.
+.It Cm AddressFamily
+Specifies which address family should be used by
+.Xr sshd 8 .
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+The default is
+.Dq any .
+.It Cm AllowAgentForwarding
+Specifies whether
+.Xr ssh-agent 1
+forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling agent forwarding does not improve security
+unless users are also denied shell access, as they can always install
+their own forwarders.
+.It Cm AllowGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+If specified, login is allowed only for users whose primary
+group or supplementary group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling TCP forwarding does not improve security unless
+users are also denied shell access, as they can always install their
+own forwarders.
+.It Cm AllowUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+If specified, login is allowed only for user names that
+match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AuthorizedKeysFile
+Specifies the file that contains the public keys that can be used
+for user authentication.
+The format is described in the
+.Sx AUTHORIZED_KEYS FILE FORMAT
+section of
+.Xr sshd 8 .
+.Cm AuthorizedKeysFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedKeysFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+Multiple files may be listed, separated by whitespace.
+The default is
+.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
+.It Cm AuthorizedPrincipalsFile
+Specifies a file that lists principal names that are accepted for
+certificate authentication.
+When using certificates signed by a key listed in
+.Cm TrustedUserCAKeys ,
+this file lists names, one of which must appear in the certificate for it
+to be accepted for authentication.
+Names are listed one per line preceded by key options (as described
+in
+.Sx AUTHORIZED_KEYS FILE FORMAT
+in
+.Xr sshd 8 ) .
+Empty lines and comments starting with
+.Ql #
+are ignored.
+.Pp
+.Cm AuthorizedPrincipalsFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedPrincipalsFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+.Pp
+The default is not to use a principals file \(en in this case, the username
+of the user must appear in a certificate's principals list for it to be
+accepted.
+Note that
+.Cm AuthorizedPrincipalsFile
+is only used when authentication proceeds using a CA listed in
+.Cm TrustedUserCAKeys
+and is not consulted for certification authorities trusted via
+.Pa ~/.ssh/authorized_keys ,
+though the
+.Cm principals=
+key option offers a similar facility (see
+.Xr sshd 8
+for details).
+.It Cm Banner
+The contents of the specified file are sent to the remote user before
+authentication is allowed.
+If the argument is
+.Dq none
+then no banner is displayed.
+This option is only available for protocol version 2.
+By default, no banner is displayed.
+.It Cm ChallengeResponseAuthentication
+Specifies whether challenge-response authentication is allowed (e.g. via
+PAM).
+The default is
+.Dq yes .
+.It Cm ChrootDirectory
+Specifies the pathname of a directory to
+.Xr chroot 2
+to after authentication.
+All components of the pathname must be root-owned directories that are
+not writable by any other user or group.
+After the chroot,
+.Xr sshd 8
+changes the working directory to the user's home directory.
+.Pp
+The pathname may contain the following tokens that are expanded at runtime once
+the connecting user has been authenticated: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+.Pp
+The
+.Cm ChrootDirectory
+must contain the necessary files and directories to support the
+user's session.
+For an interactive session this requires at least a shell, typically
+.Xr sh 1 ,
+and basic
+.Pa /dev
+nodes such as
+.Xr null 4 ,
+.Xr zero 4 ,
+.Xr stdin 4 ,
+.Xr stdout 4 ,
+.Xr stderr 4 ,
+.Xr arandom 4
+and
+.Xr tty 4
+devices.
+For file transfer sessions using
+.Dq sftp ,
+no additional configuration of the environment is necessary if the
+in-process sftp server is used,
+though sessions which use logging do require
+.Pa /dev/log
+inside the chroot directory (see
+.Xr sftp-server 8
+for details).
+.Pp
+The default is not to
+.Xr chroot 2 .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClientAliveCountMax
+Sets the number of client alive messages (see below) which may be
+sent without
+.Xr sshd 8
+receiving any messages back from the client.
+If this threshold is reached while client alive messages are being sent,
+sshd will disconnect the client, terminating the session.
+It is important to note that the use of client alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The client alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The client alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If
+.Cm ClientAliveInterval
+(see below) is set to 15, and
+.Cm ClientAliveCountMax
+is left at the default, unresponsive SSH clients
+will be disconnected after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ClientAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the client,
+.Xr sshd 8
+will send a message through the encrypted
+channel to request a response from the client.
+The default
+is 0, indicating that these messages will not be sent to the client.
+This option applies to protocol version 2 only.
+.It Cm Compression
+Specifies whether compression is allowed, or delayed until
+the user has authenticated successfully.
+The argument must be
+.Dq yes ,
+.Dq delayed ,
+or
+.Dq no .
+The default is
+.Dq delayed .
+.It Cm DebianBanner
+Specifies whether the distribution-specified extra version suffix is
+included during initial protocol handshake.
+The default is
+.Dq yes .
+.It Cm DenyGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+Login is disallowed for users whose primary group or supplementary
+group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm DenyUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+Login is disallowed for user names that match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm ForceCommand
+Forces the execution of the command specified by
+.Cm ForceCommand ,
+ignoring any command supplied by the client and
+.Pa ~/.ssh/rc
+if present.
+The command is invoked by using the user's login shell with the -c option.
+This applies to shell, command, or subsystem execution.
+It is most useful inside a
+.Cm Match
+block.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Specifying a command of
+.Dq internal-sftp
+will force the use of an in-process sftp server that requires no support
+files when used with
+.Cm ChrootDirectory .
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to ports
+forwarded for the client.
+By default,
+.Xr sshd 8
+binds remote port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that sshd
+should allow remote port forwardings to bind to non-loopback addresses, thus
+allowing other hosts to connect.
+The argument may be
+.Dq no
+to force remote port forwardings to be available to the local host only,
+.Dq yes
+to force remote port forwardings to bind to the wildcard address, or
+.Dq clientspecified
+to allow the client to select the address to which the forwarding is bound.
+The default is
+.Dq no .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICleanupCredentials
+Specifies whether to automatically destroy the user's credentials cache
+on logout.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor 
+a client authenticates against. If
+.Dq yes
+then the client must authenticate against the
+.Pa host
+service on the current hostname. If 
+.Dq no
+then the client may authenticate against any service key stored in the 
+machine's default store. This facility is provided to assist with operation 
+on multi homed machines. 
+The default is
+.Dq yes .
+Note that this option applies only to protocol version 2 GSSAPI connections,
+and setting it to 
+.Dq no
+may only work with recent Kerberos GSSAPI libraries.
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
+.Dq no .
+.It Cm HostbasedAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful public key client host authentication is allowed
+(host-based authentication).
+This option is similar to
+.Cm RhostsRSAAuthentication
+and applies to protocol version 2 only.
+The default is
+.Dq no .
+.It Cm HostbasedUsesNameFromPacketOnly
+Specifies whether or not the server will attempt to perform a reverse
+name lookup when matching the name in the
+.Pa ~/.shosts ,
+.Pa ~/.rhosts ,
+and
+.Pa /etc/hosts.equiv
+files during
+.Cm HostbasedAuthentication .
+A setting of
+.Dq yes
+means that
+.Xr sshd 8
+uses the name supplied by the client rather than
+attempting to resolve the name from the TCP connection itself.
+The default is
+.Dq no .
+.It Cm HostCertificate
+Specifies a file containing a public host certificate.
+The certificate's public key must match a private host key already specified
+by
+.Cm HostKey .
+The default behaviour of
+.Xr sshd 8
+is not to load any certificates.
+.It Cm HostKey
+Specifies a file containing a private host key
+used by SSH.
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+Note that
+.Xr sshd 8
+will refuse to use a file if it is group/world-accessible.
+It is possible to have multiple host key files.
+.Dq rsa1
+keys are used for version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+are used for version 2 of the SSH protocol.
+.It Cm IgnoreRhosts
+Specifies that
+.Pa .rhosts
+and
+.Pa .shosts
+files will not be used in
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+.Pp
+.Pa /etc/hosts.equiv
+and
+.Pa /etc/shosts.equiv
+are still used.
+The default is
+.Dq yes .
+.It Cm IgnoreUserKnownHosts
+Specifies whether
+.Xr sshd 8
+should ignore the user's
+.Pa ~/.ssh/known_hosts
+during
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+The default is
+.Dq no .
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for the connection.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KerberosAuthentication
+Specifies whether the password provided by the user for
+.Cm PasswordAuthentication
+will be validated through the Kerberos KDC.
+To use this option, the server needs a
+Kerberos servtab which allows the verification of the KDC's identity.
+The default is
+.Dq no .
+.It Cm KerberosGetAFSToken
+If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
+an AFS token before accessing the user's home directory.
+The default is
+.Dq no .
+.It Cm KerberosOrLocalPasswd
+If password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as
+.Pa /etc/passwd .
+The default is
+.Dq yes .
+.It Cm KerberosTicketCleanup
+Specifies whether to automatically destroy the user's ticket cache
+file on logout.
+The default is
+.Dq yes .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq ecdh-sha2-nistp256 ,
+.Dq ecdh-sha2-nistp384 ,
+.Dq ecdh-sha2-nistp521 ,
+.Dq diffie-hellman-group-exchange-sha256 ,
+.Dq diffie-hellman-group-exchange-sha1 ,
+.Dq diffie-hellman-group14-sha1 ,
+.Dq diffie-hellman-group1-sha1 .
+.It Cm KeyRegenerationInterval
+In protocol version 1, the ephemeral server key is automatically regenerated
+after this many seconds (if it has been used).
+The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys.
+The key is never stored anywhere.
+If the value is 0, the key is never regenerated.
+The default is 3600 (seconds).
+.It Cm ListenAddress
+Specifies the local addresses
+.Xr sshd 8
+should listen on.
+The following forms may be used:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No : Ar port
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Oo
+.Ar host No | Ar IPv6_addr Oc : Ar port
+.Sm on
+.El
+.Pp
+If
+.Ar port
+is not specified,
+sshd will listen on the address and all prior
+.Cm Port
+options specified.
+The default is to listen on all local addresses.
+Multiple
+.Cm ListenAddress
+options are permitted.
+Additionally, any
+.Cm Port
+options must precede this option for non-port qualified addresses.
+.It Cm LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in.
+If the value is 0, there is no time limit.
+The default is 120 seconds.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr sshd 8 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of debugging output.
+Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm MACs
+Specifies the available MAC (message authentication code) algorithms.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm Match
+Introduces a conditional block.
+If all of the criteria on the
+.Cm Match
+line are satisfied, the keywords on the following lines override those
+set in the global section of the config file, until either another
+.Cm Match
+line or the end of the file.
+.Pp
+The arguments to
+.Cm Match
+are one or more criteria-pattern pairs.
+The available criteria are
+.Cm User ,
+.Cm Group ,
+.Cm Host ,
+and
+.Cm Address .
+The match patterns may consist of single entries or comma-separated
+lists and may use the wildcard and negation operators described in the
+.Sx PATTERNS
+section of
+.Xr ssh_config 5 .
+.Pp
+The patterns in an
+.Cm Address
+criteria may additionally contain addresses to match in CIDR
+address/masklen format, e.g.\&
+.Dq 192.0.2.0/24
+or
+.Dq 3ffe:ffff::/32 .
+Note that the mask length provided must be consistent with the address -
+it is an error to specify a mask length that is too long for the address
+or one with bits set in this host portion of the address.
+For example,
+.Dq 192.0.2.0/33
+and
+.Dq 192.0.2.0/8
+respectively.
+.Pp
+Only a subset of keywords may be used on the lines following a
+.Cm Match
+keyword.
+Available keywords are
+.Cm AllowAgentForwarding ,
+.Cm AllowTcpForwarding ,
+.Cm AuthorizedKeysFile ,
+.Cm AuthorizedPrincipalsFile ,
+.Cm Banner ,
+.Cm ChrootDirectory ,
+.Cm ForceCommand ,
+.Cm GatewayPorts ,
+.Cm GSSAPIAuthentication ,
+.Cm HostbasedAuthentication ,
+.Cm HostbasedUsesNameFromPacketOnly ,
+.Cm KbdInteractiveAuthentication ,
+.Cm KerberosAuthentication ,
+.Cm MaxAuthTries ,
+.Cm MaxSessions ,
+.Cm PasswordAuthentication ,
+.Cm PermitEmptyPasswords ,
+.Cm PermitOpen ,
+.Cm PermitRootLogin ,
+.Cm PermitTunnel ,
+.Cm PubkeyAuthentication ,
+.Cm RhostsRSAAuthentication ,
+.Cm RSAAuthentication ,
+.Cm X11DisplayOffset ,
+.Cm X11Forwarding
+and
+.Cm X11UseLocalHost .
+.It Cm MaxAuthTries
+Specifies the maximum number of authentication attempts permitted per
+connection.
+Once the number of failures reaches half this value,
+additional failures are logged.
+The default is 6.
+.It Cm MaxSessions
+Specifies the maximum number of open sessions permitted per network connection.
+The default is 10.
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+SSH daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g. "10:30:60").
+.Xr sshd 8
+will refuse connection attempts with a probability of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probability increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
+.It Cm PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is
+.Dq yes .
+.It Cm PermitBlacklistedKeys
+Specifies whether
+.Xr sshd 8
+should allow keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 ) .
+If
+.Dq yes ,
+then attempts to authenticate with compromised keys will be logged but
+accepted.
+If
+.Dq no ,
+then attempts to authenticate with compromised keys will be rejected.
+The default is
+.Dq no .
+.It Cm PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings.
+The default is
+.Dq no .
+.It Cm PermitOpen
+Specifies the destinations to which TCP port forwarding is permitted.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Dq any
+can be used to remove all restrictions and permit any forwarding requests.
+By default all port forwarding requests are permitted.
+.It Cm PermitRootLogin
+Specifies whether root can log in using
+.Xr ssh 1 .
+The argument must be
+.Dq yes ,
+.Dq without-password ,
+.Dq forced-commands-only ,
+or
+.Dq no .
+The default is
+.Dq yes .
+.Pp
+If this option is set to
+.Dq without-password ,
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only ,
+root login with public key authentication will be allowed,
+but only if the
+.Ar command
+option has been specified
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+All other authentication methods are disabled for root.
+.Pp
+If this option is set to
+.Dq no ,
+root is not allowed to log in.
+.It Cm PermitTunnel
+Specifies whether
+.Xr tun 4
+device forwarding is allowed.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2), or
+.Dq no .
+Specifying
+.Dq yes
+permits both
+.Dq point-to-point
+and
+.Dq ethernet .
+The default is
+.Dq no .
+.It Cm PermitUserEnvironment
+Specifies whether
+.Pa ~/.ssh/environment
+and
+.Cm environment=
+options in
+.Pa ~/.ssh/authorized_keys
+are processed by
+.Xr sshd 8 .
+The default is
+.Dq no .
+Enabling environment processing may enable users to bypass access
+restrictions in some configurations using mechanisms such as
+.Ev LD_PRELOAD .
+.It Cm PidFile
+Specifies the file that contains the process ID of the
+SSH daemon.
+The default is
+.Pa /var/run/sshd.pid .
+.It Cm Port
+Specifies the port number that
+.Xr sshd 8
+listens on.
+The default is 22.
+Multiple options of this type are permitted.
+See also
+.Cm ListenAddress .
+.It Cm PrintLastLog
+Specifies whether
+.Xr sshd 8
+should print the date and time of the last user login when a user logs
+in interactively.
+The default is
+.Dq yes .
+.It Cm PrintMotd
+Specifies whether
+.Xr sshd 8
+should print
+.Pa /etc/motd
+when a user logs in interactively.
+(On some systems it is also printed by the shell,
+.Pa /etc/profile ,
+or equivalent.)
+The default is
+.Dq yes .
+.It Cm Protocol
+Specifies the protocol versions
+.Xr sshd 8
+supports.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Sq 2 .
+Note that the order of the protocol list does not indicate preference,
+because the client selects among multiple protocol versions offered
+by the server.
+Specifying
+.Dq 2,1
+is identical to
+.Dq 1,2 .
+.It Cm PubkeyAuthentication
+Specifies whether public key authentication is allowed.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm RevokedKeys
+Specifies a list of revoked public keys.
+Keys listed in this file will be refused for public key authentication.
+Note that if this file is not readable, then public key authentication will
+be refused for all users.
+.It Cm RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RSAAuthentication
+Specifies whether pure RSA authentication is allowed.
+The default is
+.Dq yes .
+This option applies to protocol version 1 only.
+.It Cm ServerKeyBits
+Defines the number of bits in the ephemeral protocol version 1 server key.
+The minimum value is 512, and the default is 1024.
+.It Cm StrictModes
+Specifies whether
+.Xr sshd 8
+should check file modes and ownership of the
+user's files and home directory before accepting login.
+This is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable.
+The default is
+.Dq yes .
+Note that this does not apply to
+.Cm ChrootDirectory ,
+whose permissions and ownership are checked unconditionally.
+.It Cm Subsystem
+Configures an external subsystem (e.g. file transfer daemon).
+Arguments should be a subsystem name and a command (with optional arguments)
+to execute upon subsystem request.
+.Pp
+The command
+.Xr sftp-server 8
+implements the
+.Dq sftp
+file transfer subsystem.
+.Pp
+Alternately the name
+.Dq internal-sftp
+implements an in-process
+.Dq sftp
+server.
+This may simplify configurations using
+.Cm ChrootDirectory
+to force a different filesystem root on clients.
+.Pp
+By default no subsystems are defined.
+Note that this option applies to protocol version 2 only.
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Xr sshd 8 .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is AUTH.
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+On the other hand, if TCP keepalives are not sent,
+sessions may hang indefinitely on the server, leaving
+.Dq ghost
+users and consuming server resources.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the server will notice
+if the network goes down or the client host crashes.
+This avoids infinitely hanging sessions.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.Pp
+This option was formerly called
+.Cm KeepAlive .
+.It Cm TrustedUserCAKeys
+Specifies a file containing public keys of certificate authorities that are
+trusted to sign user certificates for authentication.
+Keys are listed one per line; empty lines and comments starting with
+.Ql #
+are allowed.
+If a certificate is presented for authentication and has its signing CA key
+listed in this file, then it may be used for authentication for any user
+listed in the certificate's principals list.
+Note that certificates that lack a list of principals will not be permitted
+for authentication using
+.Cm TrustedUserCAKeys .
+For more details on certificates, see the
+.Sx CERTIFICATES
+section in
+.Xr ssh-keygen 1 .
+.It Cm UseDNS
+Specifies whether
+.Xr sshd 8
+should look up the remote host name and check that
+the resolved host name for the remote IP address maps back to the
+very same IP address.
+The default is
+.Dq yes .
+.It Cm UseLogin
+Specifies whether
+.Xr login 1
+is used for interactive login sessions.
+The default is
+.Dq no .
+Note that
+.Xr login 1
+is never used for remote command execution.
+Note also, that if this is enabled,
+.Cm X11Forwarding
+will be disabled because
+.Xr login 1
+does not know how to handle
+.Xr xauth 1
+cookies.
+If
+.Cm UsePrivilegeSeparation
+is specified, it will be disabled after authentication.
+.It Cm UsePAM
+Enables the Pluggable Authentication Module interface.
+If set to
+.Dq yes
+this will enable PAM authentication using
+.Cm ChallengeResponseAuthentication
+and
+.Cm PasswordAuthentication
+in addition to PAM account and session module processing for all
+authentication types.
+.Pp
+Because PAM challenge-response authentication usually serves an equivalent
+role to password authentication, you should disable either
+.Cm PasswordAuthentication
+or
+.Cm ChallengeResponseAuthentication.
+.Pp
+If
+.Cm UsePAM
+is enabled, you will not be able to run
+.Xr sshd 8
+as a non-root user.
+The default is
+.Dq no .
+.It Cm UsePrivilegeSeparation
+Specifies whether
+.Xr sshd 8
+separates privileges by creating an unprivileged child process
+to deal with incoming network traffic.
+After successful authentication, another process will be created that has
+the privilege of the authenticated user.
+The goal of privilege separation is to prevent privilege
+escalation by containing any corruption within the unprivileged processes.
+The default is
+.Dq yes .
+If
+.Cm UsePrivilegeSeparation
+is set to
+.Dq sandbox
+then the pre-authentication unprivileged process is subject to additional
+restrictions.
+.It Cm X11DisplayOffset
+Specifies the first display number available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from interfering with real X11 servers.
+The default is 10.
+.It Cm X11Forwarding
+Specifies whether X11 forwarding is permitted.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+When X11 forwarding is enabled, there may be additional exposure to
+the server and to client displays if the
+.Xr sshd 8
+proxy display is configured to listen on the wildcard address (see
+.Cm X11UseLocalhost
+below), though this is not the default.
+Additionally, the authentication spoofing and authentication data
+verification and substitution occur on the client side.
+The security risk of using X11 forwarding is that the client's X11
+display server may be exposed to attack when the SSH client requests
+forwarding (see the warnings for
+.Cm ForwardX11
+in
+.Xr ssh_config 5 ) .
+A system administrator may have a stance in which they want to
+protect clients that may expose themselves to attack by unwittingly
+requesting X11 forwarding, which can warrant a
+.Dq no
+setting.
+.Pp
+Note that disabling X11 forwarding does not prevent users from
+forwarding X11 traffic, as users can always install their own forwarders.
+X11 forwarding is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm X11UseLocalhost
+Specifies whether
+.Xr sshd 8
+should bind the X11 forwarding server to the loopback address or to
+the wildcard address.
+By default,
+sshd binds the forwarding server to the loopback address and sets the
+hostname part of the
+.Ev DISPLAY
+environment variable to
+.Dq localhost .
+This prevents remote hosts from connecting to the proxy display.
+However, some older X11 clients may not function with this
+configuration.
+.Cm X11UseLocalhost
+may be set to
+.Dq no
+to specify that the forwarding server should be bound to the wildcard
+address.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh TIME FORMATS
+.Xr sshd 8
+command-line arguments and configuration file options that specify time
+may be expressed using a sequence of the form:
+.Sm off
+.Ar time Op Ar qualifier ,
+.Sm on
+where
+.Ar time
+is a positive integer value and
+.Ar qualifier
+is one of the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Aq Cm none
+seconds
+.It Cm s | Cm S
+seconds
+.It Cm m | Cm M
+minutes
+.It Cm h | Cm H
+hours
+.It Cm d | Cm D
+days
+.It Cm w | Cm W
+weeks
+.El
+.Pp
+Each member of the sequence is added together to calculate
+the total time value.
+.Pp
+Time format examples:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It 600
+600 seconds (10 minutes)
+.It 10m
+10 minutes
+.It 1h30m
+1 hour 30 minutes (90 minutes)
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Xr sshd 8 .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.El
+.Sh SEE ALSO
+.Xr sshd 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
diff --git a/.pc/dnssec-sshfp.patch/dns.c b/.pc/dnssec-sshfp.patch/dns.c
new file mode 100644 (file)
index 0000000..131cb3d
--- /dev/null
@@ -0,0 +1,306 @@
+/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */
+
+/*
+ * Copyright (c) 2003 Wesley Griffin. All rights reserved.
+ * Copyright (c) 2003 Jakob Schlyter. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "dns.h"
+#include "log.h"
+
+static const char *errset_text[] = {
+       "success",              /* 0 ERRSET_SUCCESS */
+       "out of memory",        /* 1 ERRSET_NOMEMORY */
+       "general failure",      /* 2 ERRSET_FAIL */
+       "invalid parameter",    /* 3 ERRSET_INVAL */
+       "name does not exist",  /* 4 ERRSET_NONAME */
+       "data does not exist",  /* 5 ERRSET_NODATA */
+};
+
+static const char *
+dns_result_totext(unsigned int res)
+{
+       switch (res) {
+       case ERRSET_SUCCESS:
+               return errset_text[ERRSET_SUCCESS];
+       case ERRSET_NOMEMORY:
+               return errset_text[ERRSET_NOMEMORY];
+       case ERRSET_FAIL:
+               return errset_text[ERRSET_FAIL];
+       case ERRSET_INVAL:
+               return errset_text[ERRSET_INVAL];
+       case ERRSET_NONAME:
+               return errset_text[ERRSET_NONAME];
+       case ERRSET_NODATA:
+               return errset_text[ERRSET_NODATA];
+       default:
+               return "unknown error";
+       }
+}
+
+/*
+ * Read SSHFP parameters from key buffer.
+ */
+static int
+dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
+    u_char **digest, u_int *digest_len, Key *key)
+{
+       int success = 0;
+
+       switch (key->type) {
+       case KEY_RSA:
+               *algorithm = SSHFP_KEY_RSA;
+               break;
+       case KEY_DSA:
+               *algorithm = SSHFP_KEY_DSA;
+               break;
+       /* XXX KEY_ECDSA */
+       default:
+               *algorithm = SSHFP_KEY_RESERVED; /* 0 */
+       }
+
+       if (*algorithm) {
+               *digest_type = SSHFP_HASH_SHA1;
+               *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
+               if (*digest == NULL)
+                       fatal("dns_read_key: null from key_fingerprint_raw()");
+               success = 1;
+       } else {
+               *digest_type = SSHFP_HASH_RESERVED;
+               *digest = NULL;
+               *digest_len = 0;
+               success = 0;
+       }
+
+       return success;
+}
+
+/*
+ * Read SSHFP parameters from rdata buffer.
+ */
+static int
+dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
+    u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len)
+{
+       int success = 0;
+
+       *algorithm = SSHFP_KEY_RESERVED;
+       *digest_type = SSHFP_HASH_RESERVED;
+
+       if (rdata_len >= 2) {
+               *algorithm = rdata[0];
+               *digest_type = rdata[1];
+               *digest_len = rdata_len - 2;
+
+               if (*digest_len > 0) {
+                       *digest = (u_char *) xmalloc(*digest_len);
+                       memcpy(*digest, rdata + 2, *digest_len);
+               } else {
+                       *digest = (u_char *)xstrdup("");
+               }
+
+               success = 1;
+       }
+
+       return success;
+}
+
+/*
+ * Check if hostname is numerical.
+ * Returns -1 if hostname is numeric, 0 otherwise
+ */
+static int
+is_numeric_hostname(const char *hostname)
+{
+       struct addrinfo hints, *ai;
+
+       /*
+        * We shouldn't ever get a null host but if we do then log an error
+        * and return -1 which stops DNS key fingerprint processing.
+        */
+       if (hostname == NULL) {
+               error("is_numeric_hostname called with NULL hostname");
+               return -1;
+       }
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_flags = AI_NUMERICHOST;
+
+       if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
+               freeaddrinfo(ai);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Verify the given hostname, address and host key using DNS.
+ * Returns 0 if lookup succeeds, -1 otherwise
+ */
+int
+verify_host_key_dns(const char *hostname, struct sockaddr *address,
+    Key *hostkey, int *flags)
+{
+       u_int counter;
+       int result;
+       struct rrsetinfo *fingerprints = NULL;
+
+       u_int8_t hostkey_algorithm;
+       u_int8_t hostkey_digest_type;
+       u_char *hostkey_digest;
+       u_int hostkey_digest_len;
+
+       u_int8_t dnskey_algorithm;
+       u_int8_t dnskey_digest_type;
+       u_char *dnskey_digest;
+       u_int dnskey_digest_len;
+
+       *flags = 0;
+
+       debug3("verify_host_key_dns");
+       if (hostkey == NULL)
+               fatal("No key to look up!");
+
+       if (is_numeric_hostname(hostname)) {
+               debug("skipped DNS lookup for numerical hostname");
+               return -1;
+       }
+
+       result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
+           DNS_RDATATYPE_SSHFP, 0, &fingerprints);
+       if (result) {
+               verbose("DNS lookup error: %s", dns_result_totext(result));
+               return -1;
+       }
+
+       if (fingerprints->rri_flags & RRSET_VALIDATED) {
+               *flags |= DNS_VERIFY_SECURE;
+               debug("found %d secure fingerprints in DNS",
+                   fingerprints->rri_nrdatas);
+       } else {
+               debug("found %d insecure fingerprints in DNS",
+                   fingerprints->rri_nrdatas);
+       }
+
+       /* Initialize host key parameters */
+       if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
+           &hostkey_digest, &hostkey_digest_len, hostkey)) {
+               error("Error calculating host key fingerprint.");
+               freerrset(fingerprints);
+               return -1;
+       }
+
+       if (fingerprints->rri_nrdatas)
+               *flags |= DNS_VERIFY_FOUND;
+
+       for (counter = 0; counter < fingerprints->rri_nrdatas; counter++) {
+               /*
+                * Extract the key from the answer. Ignore any badly
+                * formatted fingerprints.
+                */
+               if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type,
+                   &dnskey_digest, &dnskey_digest_len,
+                   fingerprints->rri_rdatas[counter].rdi_data,
+                   fingerprints->rri_rdatas[counter].rdi_length)) {
+                       verbose("Error parsing fingerprint from DNS.");
+                       continue;
+               }
+
+               /* Check if the current key is the same as the given key */
+               if (hostkey_algorithm == dnskey_algorithm &&
+                   hostkey_digest_type == dnskey_digest_type) {
+
+                       if (hostkey_digest_len == dnskey_digest_len &&
+                           memcmp(hostkey_digest, dnskey_digest,
+                           hostkey_digest_len) == 0) {
+
+                               *flags |= DNS_VERIFY_MATCH;
+                       }
+               }
+               xfree(dnskey_digest);
+       }
+
+       xfree(hostkey_digest); /* from key_fingerprint_raw() */
+       freerrset(fingerprints);
+
+       if (*flags & DNS_VERIFY_FOUND)
+               if (*flags & DNS_VERIFY_MATCH)
+                       debug("matching host key fingerprint found in DNS");
+               else
+                       debug("mismatching host key fingerprint found in DNS");
+       else
+               debug("no host key fingerprint found in DNS");
+
+       return 0;
+}
+
+/*
+ * Export the fingerprint of a key as a DNS resource record
+ */
+int
+export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
+{
+       u_int8_t rdata_pubkey_algorithm = 0;
+       u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
+       u_char *rdata_digest;
+       u_int rdata_digest_len;
+
+       u_int i;
+       int success = 0;
+
+       if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
+           &rdata_digest, &rdata_digest_len, key)) {
+
+               if (generic)
+                       fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
+                           DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len,
+                           rdata_pubkey_algorithm, rdata_digest_type);
+               else
+                       fprintf(f, "%s IN SSHFP %d %d ", hostname,
+                           rdata_pubkey_algorithm, rdata_digest_type);
+
+               for (i = 0; i < rdata_digest_len; i++)
+                       fprintf(f, "%02x", rdata_digest[i]);
+               fprintf(f, "\n");
+               xfree(rdata_digest); /* from key_fingerprint_raw() */
+               success = 1;
+       } else {
+               error("export_dns_rr: unsupported algorithm");
+       }
+
+       return success;
+}
diff --git a/.pc/dnssec-sshfp.patch/openbsd-compat/getrrsetbyname.c b/.pc/dnssec-sshfp.patch/openbsd-compat/getrrsetbyname.c
new file mode 100644 (file)
index 0000000..9887667
--- /dev/null
@@ -0,0 +1,610 @@
+/* $OpenBSD: getrrsetbyname.c,v 1.11 2007/10/11 18:36:41 jakob Exp $ */
+
+/*
+ * Copyright (c) 2001 Jakob Schlyter. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */
+
+#include "includes.h"
+
+#ifndef HAVE_GETRRSETBYNAME
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "getrrsetbyname.h"
+
+#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO
+extern int h_errno;
+#endif
+
+/* We don't need multithread support here */
+#ifdef _THREAD_PRIVATE
+# undef _THREAD_PRIVATE
+#endif
+#define _THREAD_PRIVATE(a,b,c) (c)
+
+#ifndef HAVE__RES_EXTERN
+struct __res_state _res;
+#endif
+
+/* Necessary functions and macros */
+
+/*
+ * Inline versions of get/put short/long.  Pointer is advanced.
+ *
+ * These macros demonstrate the property of C whereby it can be
+ * portable or it can be elegant but rarely both.
+ */
+
+#ifndef INT32SZ
+# define INT32SZ       4
+#endif
+#ifndef INT16SZ
+# define INT16SZ       2
+#endif
+
+#ifndef GETSHORT
+#define GETSHORT(s, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (s) = ((u_int16_t)t_cp[0] << 8) \
+           | ((u_int16_t)t_cp[1]) \
+           ; \
+       (cp) += INT16SZ; \
+}
+#endif
+
+#ifndef GETLONG
+#define GETLONG(l, cp) { \
+       register u_char *t_cp = (u_char *)(cp); \
+       (l) = ((u_int32_t)t_cp[0] << 24) \
+           | ((u_int32_t)t_cp[1] << 16) \
+           | ((u_int32_t)t_cp[2] << 8) \
+           | ((u_int32_t)t_cp[3]) \
+           ; \
+       (cp) += INT32SZ; \
+}
+#endif
+
+/*
+ * Routines to insert/extract short/long's.
+ */
+
+#ifndef HAVE__GETSHORT
+static u_int16_t
+_getshort(msgp)
+       register const u_char *msgp;
+{
+       register u_int16_t u;
+
+       GETSHORT(u, msgp);
+       return (u);
+}
+#elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0)
+u_int16_t _getshort(register const u_char *);
+#endif
+
+#ifndef HAVE__GETLONG
+static u_int32_t
+_getlong(msgp)
+       register const u_char *msgp;
+{
+       register u_int32_t u;
+
+       GETLONG(u, msgp);
+       return (u);
+}
+#elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0)
+u_int32_t _getlong(register const u_char *);
+#endif
+
+/* ************** */
+
+#define ANSWER_BUFFER_SIZE 0xffff
+
+struct dns_query {
+       char                    *name;
+       u_int16_t               type;
+       u_int16_t               class;
+       struct dns_query        *next;
+};
+
+struct dns_rr {
+       char                    *name;
+       u_int16_t               type;
+       u_int16_t               class;
+       u_int16_t               ttl;
+       u_int16_t               size;
+       void                    *rdata;
+       struct dns_rr           *next;
+};
+
+struct dns_response {
+       HEADER                  header;
+       struct dns_query        *query;
+       struct dns_rr           *answer;
+       struct dns_rr           *authority;
+       struct dns_rr           *additional;
+};
+
+static struct dns_response *parse_dns_response(const u_char *, int);
+static struct dns_query *parse_dns_qsection(const u_char *, int,
+    const u_char **, int);
+static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
+    int);
+
+static void free_dns_query(struct dns_query *);
+static void free_dns_rr(struct dns_rr *);
+static void free_dns_response(struct dns_response *);
+
+static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
+
+int
+getrrsetbyname(const char *hostname, unsigned int rdclass,
+    unsigned int rdtype, unsigned int flags,
+    struct rrsetinfo **res)
+{
+       struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
+       int result;
+       struct rrsetinfo *rrset = NULL;
+       struct dns_response *response = NULL;
+       struct dns_rr *rr;
+       struct rdatainfo *rdata;
+       int length;
+       unsigned int index_ans, index_sig;
+       u_char answer[ANSWER_BUFFER_SIZE];
+
+       /* check for invalid class and type */
+       if (rdclass > 0xffff || rdtype > 0xffff) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+
+       /* don't allow queries of class or type ANY */
+       if (rdclass == 0xff || rdtype == 0xff) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+
+       /* don't allow flags yet, unimplemented */
+       if (flags) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+
+       /* initialize resolver */
+       if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
+               result = ERRSET_FAIL;
+               goto fail;
+       }
+
+#ifdef DEBUG
+       _resp->options |= RES_DEBUG;
+#endif /* DEBUG */
+
+#ifdef RES_USE_DNSSEC
+       /* turn on DNSSEC if EDNS0 is configured */
+       if (_resp->options & RES_USE_EDNS0)
+               _resp->options |= RES_USE_DNSSEC;
+#endif /* RES_USE_DNSEC */
+
+       /* make query */
+       length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
+           answer, sizeof(answer));
+       if (length < 0) {
+               switch(h_errno) {
+               case HOST_NOT_FOUND:
+                       result = ERRSET_NONAME;
+                       goto fail;
+               case NO_DATA:
+                       result = ERRSET_NODATA;
+                       goto fail;
+               default:
+                       result = ERRSET_FAIL;
+                       goto fail;
+               }
+       }
+
+       /* parse result */
+       response = parse_dns_response(answer, length);
+       if (response == NULL) {
+               result = ERRSET_FAIL;
+               goto fail;
+       }
+
+       if (response->header.qdcount != 1) {
+               result = ERRSET_FAIL;
+               goto fail;
+       }
+
+       /* initialize rrset */
+       rrset = calloc(1, sizeof(struct rrsetinfo));
+       if (rrset == NULL) {
+               result = ERRSET_NOMEMORY;
+               goto fail;
+       }
+       rrset->rri_rdclass = response->query->class;
+       rrset->rri_rdtype = response->query->type;
+       rrset->rri_ttl = response->answer->ttl;
+       rrset->rri_nrdatas = response->header.ancount;
+
+#ifdef HAVE_HEADER_AD
+       /* check for authenticated data */
+       if (response->header.ad == 1)
+               rrset->rri_flags |= RRSET_VALIDATED;
+#endif
+
+       /* copy name from answer section */
+       rrset->rri_name = strdup(response->answer->name);
+       if (rrset->rri_name == NULL) {
+               result = ERRSET_NOMEMORY;
+               goto fail;
+       }
+
+       /* count answers */
+       rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
+           rrset->rri_rdtype);
+       rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
+           T_RRSIG);
+
+       /* allocate memory for answers */
+       rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
+           sizeof(struct rdatainfo));
+       if (rrset->rri_rdatas == NULL) {
+               result = ERRSET_NOMEMORY;
+               goto fail;
+       }
+
+       /* allocate memory for signatures */
+       if (rrset->rri_nsigs > 0) {
+               rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
+               if (rrset->rri_sigs == NULL) {
+                       result = ERRSET_NOMEMORY;
+                       goto fail;
+               }
+       }
+
+       /* copy answers & signatures */
+       for (rr = response->answer, index_ans = 0, index_sig = 0;
+           rr; rr = rr->next) {
+
+               rdata = NULL;
+
+               if (rr->class == rrset->rri_rdclass &&
+                   rr->type  == rrset->rri_rdtype)
+                       rdata = &rrset->rri_rdatas[index_ans++];
+
+               if (rr->class == rrset->rri_rdclass &&
+                   rr->type  == T_RRSIG)
+                       rdata = &rrset->rri_sigs[index_sig++];
+
+               if (rdata) {
+                       rdata->rdi_length = rr->size;
+                       rdata->rdi_data   = malloc(rr->size);
+
+                       if (rdata->rdi_data == NULL) {
+                               result = ERRSET_NOMEMORY;
+                               goto fail;
+                       }
+                       memcpy(rdata->rdi_data, rr->rdata, rr->size);
+               }
+       }
+       free_dns_response(response);
+
+       *res = rrset;
+       return (ERRSET_SUCCESS);
+
+fail:
+       if (rrset != NULL)
+               freerrset(rrset);
+       if (response != NULL)
+               free_dns_response(response);
+       return (result);
+}
+
+void
+freerrset(struct rrsetinfo *rrset)
+{
+       u_int16_t i;
+
+       if (rrset == NULL)
+               return;
+
+       if (rrset->rri_rdatas) {
+               for (i = 0; i < rrset->rri_nrdatas; i++) {
+                       if (rrset->rri_rdatas[i].rdi_data == NULL)
+                               break;
+                       free(rrset->rri_rdatas[i].rdi_data);
+               }
+               free(rrset->rri_rdatas);
+       }
+
+       if (rrset->rri_sigs) {
+               for (i = 0; i < rrset->rri_nsigs; i++) {
+                       if (rrset->rri_sigs[i].rdi_data == NULL)
+                               break;
+                       free(rrset->rri_sigs[i].rdi_data);
+               }
+               free(rrset->rri_sigs);
+       }
+
+       if (rrset->rri_name)
+               free(rrset->rri_name);
+       free(rrset);
+}
+
+/*
+ * DNS response parsing routines
+ */
+static struct dns_response *
+parse_dns_response(const u_char *answer, int size)
+{
+       struct dns_response *resp;
+       const u_char *cp;
+
+       /* allocate memory for the response */
+       resp = calloc(1, sizeof(*resp));
+       if (resp == NULL)
+               return (NULL);
+
+       /* initialize current pointer */
+       cp = answer;
+
+       /* copy header */
+       memcpy(&resp->header, cp, HFIXEDSZ);
+       cp += HFIXEDSZ;
+
+       /* fix header byte order */
+       resp->header.qdcount = ntohs(resp->header.qdcount);
+       resp->header.ancount = ntohs(resp->header.ancount);
+       resp->header.nscount = ntohs(resp->header.nscount);
+       resp->header.arcount = ntohs(resp->header.arcount);
+
+       /* there must be at least one query */
+       if (resp->header.qdcount < 1) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse query section */
+       resp->query = parse_dns_qsection(answer, size, &cp,
+           resp->header.qdcount);
+       if (resp->header.qdcount && resp->query == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse answer section */
+       resp->answer = parse_dns_rrsection(answer, size, &cp,
+           resp->header.ancount);
+       if (resp->header.ancount && resp->answer == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse authority section */
+       resp->authority = parse_dns_rrsection(answer, size, &cp,
+           resp->header.nscount);
+       if (resp->header.nscount && resp->authority == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       /* parse additional section */
+       resp->additional = parse_dns_rrsection(answer, size, &cp,
+           resp->header.arcount);
+       if (resp->header.arcount && resp->additional == NULL) {
+               free_dns_response(resp);
+               return (NULL);
+       }
+
+       return (resp);
+}
+
+static struct dns_query *
+parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
+{
+       struct dns_query *head, *curr, *prev;
+       int i, length;
+       char name[MAXDNAME];
+
+       for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
+
+               /* allocate and initialize struct */
+               curr = calloc(1, sizeof(struct dns_query));
+               if (curr == NULL) {
+                       free_dns_query(head);
+                       return (NULL);
+               }
+               if (head == NULL)
+                       head = curr;
+               if (prev != NULL)
+                       prev->next = curr;
+
+               /* name */
+               length = dn_expand(answer, answer + size, *cp, name,
+                   sizeof(name));
+               if (length < 0) {
+                       free_dns_query(head);
+                       return (NULL);
+               }
+               curr->name = strdup(name);
+               if (curr->name == NULL) {
+                       free_dns_query(head);
+                       return (NULL);
+               }
+               *cp += length;
+
+               /* type */
+               curr->type = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* class */
+               curr->class = _getshort(*cp);
+               *cp += INT16SZ;
+       }
+
+       return (head);
+}
+
+static struct dns_rr *
+parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
+    int count)
+{
+       struct dns_rr *head, *curr, *prev;
+       int i, length;
+       char name[MAXDNAME];
+
+       for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
+
+               /* allocate and initialize struct */
+               curr = calloc(1, sizeof(struct dns_rr));
+               if (curr == NULL) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               if (head == NULL)
+                       head = curr;
+               if (prev != NULL)
+                       prev->next = curr;
+
+               /* name */
+               length = dn_expand(answer, answer + size, *cp, name,
+                   sizeof(name));
+               if (length < 0) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               curr->name = strdup(name);
+               if (curr->name == NULL) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               *cp += length;
+
+               /* type */
+               curr->type = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* class */
+               curr->class = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* ttl */
+               curr->ttl = _getlong(*cp);
+               *cp += INT32SZ;
+
+               /* rdata size */
+               curr->size = _getshort(*cp);
+               *cp += INT16SZ;
+
+               /* rdata itself */
+               curr->rdata = malloc(curr->size);
+               if (curr->rdata == NULL) {
+                       free_dns_rr(head);
+                       return (NULL);
+               }
+               memcpy(curr->rdata, *cp, curr->size);
+               *cp += curr->size;
+       }
+
+       return (head);
+}
+
+static void
+free_dns_query(struct dns_query *p)
+{
+       if (p == NULL)
+               return;
+
+       if (p->name)
+               free(p->name);
+       free_dns_query(p->next);
+       free(p);
+}
+
+static void
+free_dns_rr(struct dns_rr *p)
+{
+       if (p == NULL)
+               return;
+
+       if (p->name)
+               free(p->name);
+       if (p->rdata)
+               free(p->rdata);
+       free_dns_rr(p->next);
+       free(p);
+}
+
+static void
+free_dns_response(struct dns_response *p)
+{
+       if (p == NULL)
+               return;
+
+       free_dns_query(p->query);
+       free_dns_rr(p->answer);
+       free_dns_rr(p->authority);
+       free_dns_rr(p->additional);
+       free(p);
+}
+
+static int
+count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
+{
+       int n = 0;
+
+       while(p) {
+               if (p->class == class && p->type == type)
+                       n++;
+               p = p->next;
+       }
+
+       return (n);
+}
+
+#endif /* !defined(HAVE_GETRRSETBYNAME) */
diff --git a/.pc/dnssec-sshfp.patch/openbsd-compat/getrrsetbyname.h b/.pc/dnssec-sshfp.patch/openbsd-compat/getrrsetbyname.h
new file mode 100644 (file)
index 0000000..1283f55
--- /dev/null
@@ -0,0 +1,110 @@
+/* OPENBSD BASED ON : include/netdb.h */
+
+/* $OpenBSD: getrrsetbyname.c,v 1.4 2001/08/16 18:16:43 ho Exp $ */
+
+/*
+ * Copyright (c) 2001 Jakob Schlyter. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GETRRSETBYNAME_H
+#define _GETRRSETBYNAME_H
+
+#include "includes.h"
+
+#ifndef HAVE_GETRRSETBYNAME
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+
+#ifndef HFIXEDSZ
+#define HFIXEDSZ 12
+#endif
+
+#ifndef T_RRSIG
+#define T_RRSIG 46
+#endif
+
+/*
+ * Flags for getrrsetbyname()
+ */
+#ifndef RRSET_VALIDATED
+# define RRSET_VALIDATED       1
+#endif
+
+/*
+ * Return codes for getrrsetbyname()
+ */
+#ifndef ERRSET_SUCCESS
+# define ERRSET_SUCCESS                0
+# define ERRSET_NOMEMORY       1
+# define ERRSET_FAIL           2
+# define ERRSET_INVAL          3
+# define ERRSET_NONAME         4
+# define ERRSET_NODATA         5
+#endif
+
+struct rdatainfo {
+       unsigned int            rdi_length;     /* length of data */
+       unsigned char           *rdi_data;      /* record data */
+};
+
+struct rrsetinfo {
+       unsigned int            rri_flags;      /* RRSET_VALIDATED ... */
+       unsigned int            rri_rdclass;    /* class number */
+       unsigned int            rri_rdtype;     /* RR type number */
+       unsigned int            rri_ttl;        /* time to live */
+       unsigned int            rri_nrdatas;    /* size of rdatas array */
+       unsigned int            rri_nsigs;      /* size of sigs array */
+       char                    *rri_name;      /* canonical name */
+       struct rdatainfo        *rri_rdatas;    /* individual records */
+       struct rdatainfo        *rri_sigs;      /* individual signatures */
+};
+
+int            getrrsetbyname(const char *, unsigned int, unsigned int, unsigned int, struct rrsetinfo **);
+void           freerrset(struct rrsetinfo *);
+
+#endif /* !defined(HAVE_GETRRSETBYNAME) */
+
+#endif /* _GETRRSETBYNAME_H */
diff --git a/.pc/doc-hash-tab-completion.patch/ssh_config.5 b/.pc/doc-hash-tab-completion.patch/ssh_config.5
new file mode 100644 (file)
index 0000000..15d7ab1
--- /dev/null
@@ -0,0 +1,1365 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Nm ~/.ssh/config
+.Nm /etc/ssh/ssh_config
+.Sh DESCRIPTION
+.Xr ssh 1
+obtains configuration data from the following sources in
+the following order:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+command-line options
+.It
+user's configuration file
+.Pq Pa ~/.ssh/config
+.It
+system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+.El
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections separated by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp ,
+and
+.Nm sftp
+.Fl o
+option.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+If more than one pattern is provided, they should be separated by whitespace.
+A single
+.Ql *
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e. the name is not converted to
+a canonicalized host name before matching).
+.Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm AddressFamily
+Specifies which address family to use when connecting.
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+In addition, the
+.Cm ServerAliveInterval
+option will be set to 300 seconds by default.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password,
+and where it is desirable to detect a broken network swiftly.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Use the specified address on the local machine as the source address of
+the connection.
+Only useful on systems with more than one address.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge-response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Xr ssh 1
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote, and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared.
+This option is primarily useful when used from the
+.Xr ssh 1
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout (in seconds) used when connecting to the
+SSH server, instead of using the default system TCP timeout.
+This value is used only when the target is down or really unreachable,
+not when it refuses the connection.
+.It Cm ControlMaster
+Enables the sharing of multiple sessions over a single network connection.
+When set to
+.Dq yes ,
+.Xr ssh 1
+will listen for connections on a control socket specified using the
+.Cm ControlPath
+argument.
+Additional sessions can connect to this socket using the same
+.Cm ControlPath
+with
+.Cm ControlMaster
+set to
+.Dq no
+(the default).
+These sessions will try to reuse the master instance's network connection
+rather than initiating new ones, but will fall back to connecting normally
+if the control socket does not exist, or is not listening.
+.Pp
+Setting this to
+.Dq ask
+will cause ssh
+to listen for control connections, but require confirmation using the
+.Ev SSH_ASKPASS
+program before they are accepted (see
+.Xr ssh-add 1
+for details).
+If the
+.Cm ControlPath
+cannot be opened,
+ssh will continue without connecting to a master instance.
+.Pp
+X11 and
+.Xr ssh-agent 1
+forwarding is supported over these multiplexed connections, however the
+display and agent forwarded will be the one belonging to the master
+connection i.e. it is not possible to forward multiple displays or agents.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
+.It Cm ControlPath
+Specify the path to the control socket used for connection sharing as described
+in the
+.Cm ControlMaster
+section above or the string
+.Dq none
+to disable connection sharing.
+In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
+.Ql %l
+will be substituted by the local host name (including any domain name),
+.Ql %h
+will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
+.Ql %p
+the port,
+.Ql %r
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+at least %h, %p, and %r.
+This ensures that shared connections are uniquely identified.
+.It Cm ControlPersist
+When used in conjunction with
+.Cm ControlMaster ,
+specifies that the master connection should remain open
+in the background (waiting for future client connections)
+after the initial client connection has been closed.
+If set to
+.Dq no ,
+then the master connection will not be placed into the background,
+and will close as soon as the initial client connection is closed.
+If set to
+.Dq yes ,
+then the master connection will remain in the background indefinitely
+(until killed or closed via a mechanism such as the
+.Xr ssh 1
+.Dq Fl O No exit
+option).
+If set to a time in seconds, or a time in any of the formats documented in
+.Xr sshd_config 5 ,
+then the backgrounded master connection will automatically terminate
+after it has remained idle (with no client connections) for the
+specified time.
+.It Cm DynamicForward
+Specifies that a TCP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+.Pp
+The argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port .
+.Sm on
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.Pp
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Xr ssh 1
+will act as a SOCKS server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm EnableSSHKeysign
+Setting this option to
+.Dq yes
+in the global client configuration file
+.Pa /etc/ssh/ssh_config
+enables the use of the helper program
+.Xr ssh-keysign 8
+during
+.Cm HostbasedAuthentication .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option should be placed in the non-hostspecific section.
+See
+.Xr ssh-keysign 8
+for more information.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ExitOnForwardFailure
+Specifies whether
+.Xr ssh 1
+should terminate the connection if it cannot set up all requested
+dynamic, tunnel, local, and remote port forwardings.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's Unix-domain socket)
+can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X11 authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring
+if the
+.Cm ForwardX11Trusted
+option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
+.It Cm ForwardX11Trusted
+If this option is set to
+.Dq yes ,
+remote X11 clients will have full access to the original X11 display.
+.Pp
+If this option is set to
+.Dq no ,
+remote X11 clients will be considered untrusted and prevented
+from stealing or tampering with data belonging to trusted X11
+clients.
+Furthermore, the
+.Xr xauth 1
+token used for the session will be set to expire after 20 minutes.
+Remote clients will be refused access after this time.
+.Pp
+The default is
+.Dq no .
+.Pp
+See the X11 SECURITY extension specification for full details on
+the restrictions imposed on untrusted clients.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Xr ssh 1
+binds local port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
+.It Cm GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when 
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
+.It Cm GSSAPIDelegateCredentials
+Forward (delegate) credentials to the server.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI.
+.It Cm HashKnownHosts
+Indicates that
+.Xr ssh 1
+should hash host names and addresses when they are added to
+.Pa ~/.ssh/known_hosts .
+These hashed names may be used normally by
+.Xr ssh 1
+and
+.Xr sshd 8 ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+The default is
+.Dq no .
+Note that existing names and addresses in known hosts files
+will not be converted automatically,
+but may be manually hashed using
+.Xr ssh-keygen 1 .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
+ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-rsa,ssh-dss
+.Ed
+.Pp
+If hostkeys are known for the destination host then this default is modified
+to prefer their algorithms.
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling SSH connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+If the hostname contains the character sequence
+.Ql %h ,
+then this will be replaced with the host name specified on the command line
+(this is useful for manipulating unqualified names).
+The default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentitiesOnly
+Specifies that
+.Xr ssh 1
+should only use the authentication identity files configured in the
+.Nm
+files,
+even if
+.Xr ssh-agent 1
+offers more identities.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option is intended for situations where ssh-agent
+offers many different identities.
+The default is
+.Dq no .
+.It Cm IdentityFile
+Specifies a file from which the user's DSA, ECDSA or DSA authentication
+identity is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+.Xr ssh 1
+will try to load certificate information from the filename obtained by
+appending
+.Pa -cert.pub
+to the path of a specified
+.Cm IdentityFile .
+.Pp
+The file name may use the tilde
+syntax to refer to a user's home directory or one of the following
+escape characters:
+.Ql %d
+(local user's home directory),
+.Ql %u
+(local user name),
+.Ql %l
+(local host name),
+.Ql %h
+(remote host name) or
+.Ql %r
+(remote user name).
+.Pp
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KbdInteractiveAuthentication
+Specifies whether to use keyboard-interactive authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm KbdInteractiveDevices
+Specifies the list of methods to use in keyboard-interactive authentication.
+Multiple method names must be comma-separated.
+The default is to use the server specified list.
+The methods available vary depending on what the server supports.
+For an OpenSSH server,
+it may be zero or more of:
+.Dq bsdauth ,
+.Dq pam ,
+and
+.Dq skey .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
+diffie-hellman-group-exchange-sha256,
+diffie-hellman-group-exchange-sha1,
+diffie-hellman-group14-sha1,
+diffie-hellman-group1-sha1
+.Ed
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+The following escape character substitutions will be performed:
+.Ql %d
+(local user's home directory),
+.Ql %h
+(remote host name),
+.Ql %l
+(local host name),
+.Ql %n
+(host name as provided on the command line),
+.Ql %p
+(remote port),
+.Ql %r
+(remote user name) or
+.Ql %u
+(local user name).
+.Pp
+The command is run synchronously and does not have access to the
+session of the
+.Xr ssh 1
+that spawned it.
+It should not be used for interactive commands.
+.Pp
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
+.It Cm LocalForward
+Specifies that a TCP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional forwardings can be
+given on the command line.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr ssh 1 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+The default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic !\& Ns Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm PKCS11Provider
+Specifies which PKCS#11 provider to use.
+The argument to this keyword is the PKCS#11 shared library
+.Xr ssh 1
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Cm Port
+Specifies the port number to connect on the remote host.
+The default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods.
+This allows a client to prefer one method (e.g.\&
+.Cm keyboard-interactive )
+over another method (e.g.\&
+.Cm password ) .
+The default is:
+.Bd -literal -offset indent
+gssapi-with-mic,hostbased,publickey,
+keyboard-interactive,password
+.Ed
+.It Cm Protocol
+Specifies the protocol versions
+.Xr ssh 1
+should support in order of preference.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+When this option is set to
+.Dq 2,1
+.Nm ssh
+will try version 2 and fall back to version 1
+if version 2 is not available.
+The default is
+.Sq 2 .
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+the user's shell.
+In the command string, any occurrence of
+.Ql %h
+will be substituted by the host name to
+connect,
+.Ql %p
+by the port, and
+.Ql %r
+by the remote user name.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Setting the command to
+.Dq none
+disables this option entirely.
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+This directive is useful in conjunction with
+.Xr nc 1
+and its proxy support.
+For example, the following directive would connect via an HTTP proxy at
+192.0.2.0:
+.Bd -literal -offset 3n
+ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
+.Ed
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RekeyLimit
+Specifies the maximum amount of data that may be transmitted before the
+session key is renegotiated.
+The argument is the number of bytes, with an optional suffix of
+.Sq K ,
+.Sq M ,
+or
+.Sq G
+to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
+The default is between
+.Sq 1G
+and
+.Sq 4G ,
+depending on the cipher.
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+.Pp
+If the
+.Ar bind_address
+is not specified, the default is to only bind to loopback addresses.
+If the
+.Ar bind_address
+is
+.Ql *
+or an empty string, then the forwarding is requested to listen on all
+interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Xr ssh 1
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SendEnv
+Specifies what variables from the local
+.Xr environ 7
+should be sent to the server.
+Note that environment passing is only supported for protocol 2.
+The server must also support it, and the server must be configured to
+accept these environment variables.
+Refer to
+.Cm AcceptEnv
+in
+.Xr sshd_config 5
+for how to configure the server.
+Variables are specified by name, which may contain wildcard characters.
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm SendEnv
+directives.
+The default is not to send any environment variables.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm ServerAliveCountMax
+Sets the number of server alive messages (see below) which may be
+sent without
+.Xr ssh 1
+receiving any messages back from the server.
+If this threshold is reached while server alive messages are being sent,
+ssh will disconnect from the server, terminating the session.
+It is important to note that the use of server alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The server alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The server alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If, for example,
+.Cm ServerAliveInterval
+(see below) is set to 15 and
+.Cm ServerAliveCountMax
+is left at the default, if the server becomes unresponsive,
+ssh will disconnect after approximately 45 seconds.
+This option applies to protocol version 2 only; in protocol version
+1 there is no mechanism to request a response from the server to the
+server alive messages, so disconnection is the responsibility of the TCP
+stack.
+.It Cm ServerAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the server,
+.Xr ssh 1
+will send a message through the encrypted
+channel to request a response from the server.
+The default
+is 0, indicating that these messages will not be sent to the server,
+or 300 if the
+.Cm BatchMode
+option is set.
+This option applies to protocol version 2 only.
+.Cm ProtocolKeepAlives
+and
+.Cm SetupTimeOut
+are Debian-specific compatibility aliases for this option.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will never automatically add host keys to the
+.Pa ~/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+though it can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained or when connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+ssh will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+ssh will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+This option only uses TCP keepalives (as opposed to using ssh level
+keepalives), so takes a long time to notice when the connection dies.
+As such, you probably want
+the
+.Cm ServerAliveInterval
+option as well.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm Tunnel
+Request
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2),
+or
+.Dq no .
+Specifying
+.Dq yes
+requests the default tunnel mode, which is
+.Dq point-to-point .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Specifies the
+.Xr tun 4
+devices to open on the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The argument must be
+.Sm off
+.Ar local_tun Op : Ar remote_tun .
+.Sm on
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+The default is
+.Dq any:any .
+.It Cm UseBlacklistedKeys
+Specifies whether
+.Xr ssh 1
+should use keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 )
+for authentication.
+If
+.Dq yes ,
+then attempts to use compromised keys for authentication will be logged but
+accepted.
+It is strongly recommended that this be used only to install new authorized
+keys on the remote system, and even then only with the utmost care.
+If
+.Dq no ,
+then attempts to use compromised keys for authentication will be prevented.
+The default is
+.Dq no .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+If set to
+.Dq yes ,
+.Xr ssh 1
+must be setuid root.
+Note that this option must be set to
+.Dq yes
+for
+.Cm RhostsRSAAuthentication
+with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
+.It Cm VerifyHostKeyDNS
+Specifies whether to verify the remote key using DNS and SSHFP resource
+records.
+If this option is set to
+.Dq yes ,
+the client will implicitly trust keys that match a secure fingerprint
+from DNS.
+Insecure fingerprints will be handled as if this option was set to
+.Dq ask .
+If this option is set to
+.Dq ask ,
+information on fingerprint match will be displayed, but the user will still
+need to confirm new host keys according to the
+.Cm StrictHostKeyChecking
+option.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.Pp
+See also
+.Sx VERIFYING HOST KEYS
+in
+.Xr ssh 1 .
+.It Cm VisualHostKey
+If this flag is set to
+.Dq yes ,
+an ASCII art representation of the remote host key fingerprint is
+printed in addition to the hex fingerprint string at login and
+for unknown host keys.
+If this flag is set to
+.Dq no ,
+no fingerprint strings are printed at login and
+only the hex fingerprint string will be printed for unknown host keys.
+The default is
+.Dq no .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh PATTERNS
+A
+.Em pattern
+consists of zero or more non-whitespace characters,
+.Sq *
+(a wildcard that matches zero or more characters),
+or
+.Sq ?\&
+(a wildcard that matches exactly one character).
+For example, to specify a set of declarations for any host in the
+.Dq .co.uk
+set of domains,
+the following pattern could be used:
+.Pp
+.Dl Host *.co.uk
+.Pp
+The following pattern
+would match any host in the 192.168.0.[0-9] network range:
+.Pp
+.Dl Host 192.168.0.?
+.Pp
+A
+.Em pattern-list
+is a comma-separated list of patterns.
+Patterns within pattern-lists may be negated
+by preceding them with an exclamation mark
+.Pq Sq !\& .
+For example,
+to allow a key to be used from anywhere within an organisation
+except from the
+.Dq dialup
+pool,
+the following entry (in authorized_keys) could be used:
+.Pp
+.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the SSH client.
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+It may be group-writable provided that the group in question contains only
+the user.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh SEE ALSO
+.Xr ssh 1
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/gnome-ssh-askpass2-icon.patch/contrib/gnome-ssh-askpass2.c b/.pc/gnome-ssh-askpass2-icon.patch/contrib/gnome-ssh-askpass2.c
new file mode 100644 (file)
index 0000000..9d97c30
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2000-2002 Damien Miller.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* GTK2 support by Nalin Dahyabhai <nalin@redhat.com> */
+
+/*
+ * This is a simple GNOME SSH passphrase grabber. To use it, set the
+ * environment variable SSH_ASKPASS to point to the location of
+ * gnome-ssh-askpass before calling "ssh-add < /dev/null".
+ *
+ * There is only two run-time options: if you set the environment variable
+ * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab
+ * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the
+ * pointer will be grabbed too. These may have some benefit to security if
+ * you don't trust your X server. We grab the keyboard always.
+ */
+
+#define GRAB_TRIES     16
+#define GRAB_WAIT      250 /* milliseconds */
+
+/*
+ * Compile with:
+ *
+ * cc -Wall `pkg-config --cflags gtk+-2.0` \
+ *    gnome-ssh-askpass2.c -o gnome-ssh-askpass \
+ *    `pkg-config --libs gtk+-2.0`
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+static void
+report_failed_grab (const char *what)
+{
+       GtkWidget *err;
+
+       err = gtk_message_dialog_new(NULL, 0,
+                                    GTK_MESSAGE_ERROR,
+                                    GTK_BUTTONS_CLOSE,
+                                    "Could not grab %s. "
+                                    "A malicious client may be eavesdropping "
+                                    "on your session.", what);
+       gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
+       gtk_label_set_line_wrap(GTK_LABEL((GTK_MESSAGE_DIALOG(err))->label),
+                               TRUE);
+
+       gtk_dialog_run(GTK_DIALOG(err));
+
+       gtk_widget_destroy(err);
+}
+
+static void
+ok_dialog(GtkWidget *entry, gpointer dialog)
+{
+       g_return_if_fail(GTK_IS_DIALOG(dialog));
+       gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+}
+
+static int
+passphrase_dialog(char *message)
+{
+       const char *failed;
+       char *passphrase, *local;
+       int result, grab_tries, grab_server, grab_pointer;
+       GtkWidget *dialog, *entry;
+       GdkGrabStatus status;
+
+       grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
+       grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL);
+       grab_tries = 0;
+
+       dialog = gtk_message_dialog_new(NULL, 0,
+                                       GTK_MESSAGE_QUESTION,
+                                       GTK_BUTTONS_OK_CANCEL,
+                                       "%s",
+                                       message);
+
+       entry = gtk_entry_new();
+       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, FALSE,
+           FALSE, 0);
+       gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
+       gtk_widget_grab_focus(entry);
+       gtk_widget_show(entry);
+
+       gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH");
+       gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
+       gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
+       gtk_label_set_line_wrap(GTK_LABEL((GTK_MESSAGE_DIALOG(dialog))->label),
+                               TRUE);
+
+       /* Make <enter> close dialog */
+       gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+       g_signal_connect(G_OBJECT(entry), "activate",
+                        G_CALLBACK(ok_dialog), dialog);
+
+       gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
+
+       /* Grab focus */
+       gtk_widget_show_now(dialog);
+       if (grab_pointer) {
+               for(;;) {
+                       status = gdk_pointer_grab(
+                          (GTK_WIDGET(dialog))->window, TRUE, 0, NULL,
+                          NULL, GDK_CURRENT_TIME);
+                       if (status == GDK_GRAB_SUCCESS)
+                               break;
+                       usleep(GRAB_WAIT * 1000);
+                       if (++grab_tries > GRAB_TRIES) {
+                               failed = "mouse";
+                               goto nograb;
+                       }
+               }
+       }
+       for(;;) {
+               status = gdk_keyboard_grab((GTK_WIDGET(dialog))->window,
+                  FALSE, GDK_CURRENT_TIME);
+               if (status == GDK_GRAB_SUCCESS)
+                       break;
+               usleep(GRAB_WAIT * 1000);
+               if (++grab_tries > GRAB_TRIES) {
+                       failed = "keyboard";
+                       goto nograbkb;
+               }
+       }
+       if (grab_server) {
+               gdk_x11_grab_server();
+       }
+
+       result = gtk_dialog_run(GTK_DIALOG(dialog));
+
+       /* Ungrab */
+       if (grab_server)
+               XUngrabServer(GDK_DISPLAY());
+       if (grab_pointer)
+               gdk_pointer_ungrab(GDK_CURRENT_TIME);
+       gdk_keyboard_ungrab(GDK_CURRENT_TIME);
+       gdk_flush();
+
+       /* Report passphrase if user selected OK */
+       passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+       if (result == GTK_RESPONSE_OK) {
+               local = g_locale_from_utf8(passphrase, strlen(passphrase),
+                                          NULL, NULL, NULL);
+               if (local != NULL) {
+                       puts(local);
+                       memset(local, '\0', strlen(local));
+                       g_free(local);
+               } else {
+                       puts(passphrase);
+               }
+       }
+               
+       /* Zero passphrase in memory */
+       memset(passphrase, '\b', strlen(passphrase));
+       gtk_entry_set_text(GTK_ENTRY(entry), passphrase);
+       memset(passphrase, '\0', strlen(passphrase));
+       g_free(passphrase);
+                       
+       gtk_widget_destroy(dialog);
+       return (result == GTK_RESPONSE_OK ? 0 : -1);
+
+       /* At least one grab failed - ungrab what we got, and report
+          the failure to the user.  Note that XGrabServer() cannot
+          fail.  */
+ nograbkb:
+       gdk_pointer_ungrab(GDK_CURRENT_TIME);
+ nograb:
+       if (grab_server)
+               XUngrabServer(GDK_DISPLAY());
+       gtk_widget_destroy(dialog);
+       
+       report_failed_grab(failed);
+
+       return (-1);
+}
+
+int
+main(int argc, char **argv)
+{
+       char *message;
+       int result;
+
+       gtk_init(&argc, &argv);
+
+       if (argc > 1) {
+               message = g_strjoinv(" ", argv + 1);
+       } else {
+               message = g_strdup("Enter your OpenSSH passphrase:");
+       }
+
+       setvbuf(stdout, 0, _IONBF, 0);
+       result = passphrase_dialog(message);
+       g_free(message);
+
+       return (result);
+}
diff --git a/.pc/gssapi.patch/ChangeLog.gssapi b/.pc/gssapi.patch/ChangeLog.gssapi
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/.pc/gssapi.patch/Makefile.in b/.pc/gssapi.patch/Makefile.in
new file mode 100644 (file)
index 0000000..3be3aa6
--- /dev/null
@@ -0,0 +1,442 @@
+# $Id: Makefile.in,v 1.325 2011/08/05 20:15:18 djm Exp $
+
+# uncomment if you run a non bourne compatable shell. Ie. csh
+#SHELL = @SH@
+
+AUTORECONF=autoreconf
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+sbindir=@sbindir@
+libexecdir=@libexecdir@
+datadir=@datadir@
+datarootdir=@datarootdir@
+mandir=@mandir@
+mansubdir=@mansubdir@
+sysconfdir=@sysconfdir@
+piddir=@piddir@
+srcdir=@srcdir@
+top_srcdir=@top_srcdir@
+
+DESTDIR=
+VPATH=@srcdir@
+SSH_PROGRAM=@bindir@/ssh
+ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
+SFTP_SERVER=$(libexecdir)/sftp-server
+SSH_KEYSIGN=$(libexecdir)/ssh-keysign
+SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
+PRIVSEP_PATH=@PRIVSEP_PATH@
+SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
+STRIP_OPT=@STRIP_OPT@
+
+PATHS= -DSSHDIR=\"$(sysconfdir)\" \
+       -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
+       -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
+       -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
+       -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
+       -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
+       -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
+       -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
+
+CC=@CC@
+LD=@LD@
+CFLAGS=@CFLAGS@
+CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+LIBS=@LIBS@
+SSHLIBS=@SSHLIBS@
+SSHDLIBS=@SSHDLIBS@
+LIBEDIT=@LIBEDIT@
+AR=@AR@
+AWK=@AWK@
+RANLIB=@RANLIB@
+INSTALL=@INSTALL@
+PERL=@PERL@
+SED=@SED@
+ENT=@ENT@
+XAUTH_PATH=@XAUTH_PATH@
+LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
+EXEEXT=@EXEEXT@
+MANFMT=@MANFMT@
+
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
+
+LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
+       canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
+       cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
+       compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
+       log.o match.o md-sha256.o moduli.o nchan.o packet.o \
+       readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
+       atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
+       monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
+       kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
+       msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
+       schnorr.o ssh-pkcs11.o
+
+SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
+       sshconnect.o sshconnect1.o sshconnect2.o mux.o \
+       roaming_common.o roaming_client.o
+
+SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
+       audit.o audit-bsm.o audit-linux.o platform.o \
+       sshpty.o sshlogin.o servconf.o serverloop.o \
+       auth.o auth1.o auth2.o auth-options.o session.o \
+       auth-chall.o auth2-chall.o groupaccess.o \
+       auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
+       auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
+       monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
+       auth-krb5.o \
+       auth2-gss.o gss-serv.o gss-serv-krb5.o \
+       loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
+       sftp-server.o sftp-common.o \
+       roaming_common.o roaming_serv.o \
+       sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
+
+MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
+MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
+MANTYPE                = @MANTYPE@
+
+CONFIGFILES=sshd_config.out ssh_config.out moduli.out
+CONFIGFILES_IN=sshd_config ssh_config moduli
+
+PATHSUBS       = \
+       -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
+       -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
+       -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \
+       -e 's|/usr/libexec|$(libexecdir)|g' \
+       -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \
+       -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \
+       -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
+       -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
+       -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \
+       -e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \
+       -e 's|/var/empty|$(PRIVSEP_PATH)|g' \
+       -e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g'
+
+FIXPATHSCMD    = $(SED) $(PATHSUBS)
+
+all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+
+$(LIBSSH_OBJS): Makefile.in config.h
+$(SSHOBJS): Makefile.in config.h
+$(SSHDOBJS): Makefile.in config.h
+
+.c.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
+$(LIBCOMPAT): always
+       (cd openbsd-compat && $(MAKE))
+always:
+
+libssh.a: $(LIBSSH_OBJS)
+       $(AR) rv $@ $(LIBSSH_OBJS)
+       $(RANLIB) $@
+
+ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
+       $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
+
+sshd$(EXEEXT): libssh.a        $(LIBCOMPAT) $(SSHDOBJS)
+       $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
+
+scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
+       $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
+       $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
+       $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
+       $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o
+       $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
+       $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
+       $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
+       $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
+       $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
+
+# test driver for the loginrec code - not built by default
+logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
+       $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
+
+$(MANPAGES): $(MANPAGES_IN)
+       if test "$(MANTYPE)" = "cat"; then \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \
+       else \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \
+       fi; \
+       if test "$(MANTYPE)" = "man"; then \
+               $(FIXPATHSCMD) $${manpage} | $(AWK) -f $(srcdir)/mdoc2man.awk > $@; \
+       else \
+               $(FIXPATHSCMD) $${manpage} > $@; \
+       fi
+
+$(CONFIGFILES): $(CONFIGFILES_IN)
+       conffile=`echo $@ | sed 's/.out$$//'`; \
+       $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@
+
+# fake rule to stop make trying to compile moduli.o into a binary "moduli.o"
+moduli:
+       echo
+
+clean: regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core survey
+       (cd openbsd-compat && $(MAKE) clean)
+
+distclean:     regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core opensshd.init openssh.xml
+       rm -f Makefile buildpkg.sh config.h config.status
+       rm -f survey.sh openbsd-compat/regress/Makefile *~ 
+       rm -rf autom4te.cache
+       (cd openbsd-compat && $(MAKE) distclean)
+       if test -d pkg ; then \
+               rm -fr pkg ; \
+       fi
+
+veryclean: distclean
+       rm -f configure config.h.in *.0
+
+cleandir: veryclean
+
+mrproper: veryclean
+
+realclean: veryclean
+
+catman-do:
+       @for f in $(MANPAGES_IN) ; do \
+               base=`echo $$f | sed 's/\..*$$//'` ; \
+               echo "$$f -> $$base.0" ; \
+               $(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \
+                       >$$base.0 ; \
+       done
+
+distprep: catman-do
+       $(AUTORECONF)
+       -rm -rf autom4te.cache
+
+install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
+install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf
+install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files
+
+check-config:
+       -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
+
+install-files:
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)5
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir)
+       (umask 022 ; $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH))
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       $(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       $(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5
+       $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
+       $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
+       $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+       ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+install-sysconf:
+       if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
+               $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \
+               $(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \
+               $(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \
+               if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \
+                       echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \
+                       mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \
+               else \
+                       $(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \
+               fi ; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \
+       fi
+
+host-key: ssh-keygen$(EXEEXT)
+       @if [ -z "$(DESTDIR)" ] ; then \
+               if [ -f "$(sysconfdir)/ssh_host_key" ] ; then \
+                       echo "$(sysconfdir)/ssh_host_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa1 -f $(sysconfdir)/ssh_host_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_dsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t dsa -f $(sysconfdir)/ssh_host_dsa_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_rsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa -f $(sysconfdir)/ssh_host_rsa_key -N "" ; \
+               fi ; \
+               if [ -z "@COMMENT_OUT_ECC@" ] ; then \
+                   if [ -f $(sysconfdir)/ssh_host_ecdsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_ecdsa_key already exists, skipping." ; \
+                   else \
+                       ./ssh-keygen -t ecdsa -f $(sysconfdir)/ssh_host_ecdsa_key -N "" ; \
+                   fi ; \
+               fi ; \
+       fi ;
+
+host-key-force: ssh-keygen$(EXEEXT)
+       ./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
+       ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
+       ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
+       test -z "@COMMENT_OUT_ECC@" && ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""
+
+uninstallall:  uninstall
+       -rm -f $(DESTDIR)$(sysconfdir)/ssh_config
+       -rm -f $(DESTDIR)$(sysconfdir)/sshd_config
+       -rmdir $(DESTDIR)$(sysconfdir)
+       -rmdir $(DESTDIR)$(bindir)
+       -rmdir $(DESTDIR)$(sbindir)
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)1
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)8
+       -rmdir $(DESTDIR)$(mandir)
+       -rmdir $(DESTDIR)$(libexecdir)
+
+uninstall:
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+tests interop-tests:   $(TARGETS)
+       BUILDDIR=`pwd`; \
+       [ -d `pwd`/regress ]  ||  mkdir -p `pwd`/regress; \
+       [ -f `pwd`/regress/Makefile ]  || \
+           ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile ; \
+       TEST_SHELL="@TEST_SHELL@"; \
+       TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
+       TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
+       TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
+       TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
+       TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
+       TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
+       TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
+       TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
+       TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
+       TEST_SSH_PLINK="plink"; \
+       TEST_SSH_PUTTYGEN="puttygen"; \
+       TEST_SSH_CONCH="conch"; \
+       TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
+       TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
+       TEST_SSH_SHA256="@TEST_SSH_SHA256@" ; \
+       cd $(srcdir)/regress || exit $$?; \
+       $(MAKE) \
+               .OBJDIR="$${BUILDDIR}/regress" \
+               .CURDIR="`pwd`" \
+               BUILDDIR="$${BUILDDIR}" \
+               OBJ="$${BUILDDIR}/regress/" \
+               PATH="$${BUILDDIR}:$${PATH}" \
+               TEST_SHELL="$${TEST_SHELL}" \
+               TEST_SSH_SSH="$${TEST_SSH_SSH}" \
+               TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
+               TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
+               TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
+               TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
+               TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
+               TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
+               TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
+               TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
+               TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
+               TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
+               TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
+               TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
+               TEST_SSH_ECC="$${TEST_SSH_ECC}" \
+               TEST_SSH_SHA256="$${TEST_SSH_SHA256}" \
+               EXEEXT="$(EXEEXT)" \
+               $@ && echo all tests passed
+
+compat-tests: $(LIBCOMPAT)
+       (cd openbsd-compat/regress && $(MAKE))
+
+regressclean:
+       if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \
+               (cd regress && $(MAKE) clean) \
+       fi
+
+survey: survey.sh ssh
+       @$(SHELL) ./survey.sh > survey
+       @echo 'The survey results have been placed in the file "survey" in the'
+       @echo 'current directory.  Please review the file then send with'
+       @echo '"make send-survey".'
+
+send-survey:   survey
+       mail portable-survey@mindrot.org <survey
+
+package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+       if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
+               sh buildpkg.sh; \
+       fi
+
diff --git a/.pc/gssapi.patch/auth-krb5.c b/.pc/gssapi.patch/auth-krb5.c
new file mode 100644 (file)
index 0000000..d019fe2
--- /dev/null
@@ -0,0 +1,256 @@
+/* $OpenBSD: auth-krb5.c,v 1.19 2006/08/03 03:34:41 deraadt Exp $ */
+/*
+ *    Kerberos v5 authentication and ticket-passing routines.
+ *
+ * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $
+ */
+/*
+ * Copyright (c) 2002 Daniel Kouril.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdarg.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "uidswap.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+
+#ifdef KRB5
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <krb5.h>
+
+extern ServerOptions    options;
+
+static int
+krb5_init(void *context)
+{
+       Authctxt *authctxt = (Authctxt *)context;
+       krb5_error_code problem;
+
+       if (authctxt->krb5_ctx == NULL) {
+               problem = krb5_init_context(&authctxt->krb5_ctx);
+               if (problem)
+                       return (problem);
+       }
+       return (0);
+}
+
+int
+auth_krb5_password(Authctxt *authctxt, const char *password)
+{
+#ifndef HEIMDAL
+       krb5_creds creds;
+       krb5_principal server;
+#endif
+       krb5_error_code problem;
+       krb5_ccache ccache = NULL;
+       int len;
+       char *client, *platform_client;
+
+       /* get platform-specific kerberos client principal name (if it exists) */
+       platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
+       client = platform_client ? platform_client : authctxt->pw->pw_name;
+
+       temporarily_use_uid(authctxt->pw);
+
+       problem = krb5_init(authctxt);
+       if (problem)
+               goto out;
+
+       problem = krb5_parse_name(authctxt->krb5_ctx, client,
+                   &authctxt->krb5_user);
+       if (problem)
+               goto out;
+
+#ifdef HEIMDAL
+       problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
+       if (problem)
+               goto out;
+
+       problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
+               authctxt->krb5_user);
+       if (problem)
+               goto out;
+
+       restore_uid();
+
+       problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
+           ccache, password, 1, NULL);
+
+       temporarily_use_uid(authctxt->pw);
+
+       if (problem)
+               goto out;
+
+       problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
+           &authctxt->krb5_fwd_ccache);
+       if (problem)
+               goto out;
+
+       problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
+           authctxt->krb5_fwd_ccache);
+       krb5_cc_destroy(authctxt->krb5_ctx, ccache);
+       ccache = NULL;
+       if (problem)
+               goto out;
+
+#else
+       problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
+           authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
+       if (problem)
+               goto out;
+
+       problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
+           KRB5_NT_SRV_HST, &server);
+       if (problem)
+               goto out;
+
+       restore_uid();
+       problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
+           NULL, NULL, NULL);
+       krb5_free_principal(authctxt->krb5_ctx, server);
+       temporarily_use_uid(authctxt->pw);
+       if (problem)
+               goto out;
+
+       if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
+               problem = -1;
+               goto out;
+       }
+
+       problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
+       if (problem)
+               goto out;
+
+       problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
+                                    authctxt->krb5_user);
+       if (problem)
+               goto out;
+
+       problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
+                                &creds);
+       if (problem)
+               goto out;
+#endif
+
+       authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
+
+       len = strlen(authctxt->krb5_ticket_file) + 6;
+       authctxt->krb5_ccname = xmalloc(len);
+       snprintf(authctxt->krb5_ccname, len, "FILE:%s",
+           authctxt->krb5_ticket_file);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
+#endif
+
+ out:
+       restore_uid();
+       
+       if (platform_client != NULL)
+               xfree(platform_client);
+
+       if (problem) {
+               if (ccache)
+                       krb5_cc_destroy(authctxt->krb5_ctx, ccache);
+
+               if (authctxt->krb5_ctx != NULL && problem!=-1)
+                       debug("Kerberos password authentication failed: %s",
+                           krb5_get_err_text(authctxt->krb5_ctx, problem));
+               else
+                       debug("Kerberos password authentication failed: %d",
+                           problem);
+
+               krb5_cleanup_proc(authctxt);
+
+               if (options.kerberos_or_local_passwd)
+                       return (-1);
+               else
+                       return (0);
+       }
+       return (authctxt->valid ? 1 : 0);
+}
+
+void
+krb5_cleanup_proc(Authctxt *authctxt)
+{
+       debug("krb5_cleanup_proc called");
+       if (authctxt->krb5_fwd_ccache) {
+               krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
+               authctxt->krb5_fwd_ccache = NULL;
+       }
+       if (authctxt->krb5_user) {
+               krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
+               authctxt->krb5_user = NULL;
+       }
+       if (authctxt->krb5_ctx) {
+               krb5_free_context(authctxt->krb5_ctx);
+               authctxt->krb5_ctx = NULL;
+       }
+}
+
+#ifndef HEIMDAL
+krb5_error_code
+ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
+       int tmpfd, ret;
+       char ccname[40];
+       mode_t old_umask;
+
+       ret = snprintf(ccname, sizeof(ccname),
+           "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
+       if (ret < 0 || (size_t)ret >= sizeof(ccname))
+               return ENOMEM;
+
+       old_umask = umask(0177);
+       tmpfd = mkstemp(ccname + strlen("FILE:"));
+       umask(old_umask);
+       if (tmpfd == -1) {
+               logit("mkstemp(): %.100s", strerror(errno));
+               return errno;
+       }
+
+       if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+               logit("fchmod(): %.100s", strerror(errno));
+               close(tmpfd);
+               return errno;
+       }
+       close(tmpfd);
+
+       return (krb5_cc_resolve(ctx, ccname, ccache));
+}
+#endif /* !HEIMDAL */
+#endif /* KRB5 */
diff --git a/.pc/gssapi.patch/auth2-gss.c b/.pc/gssapi.patch/auth2-gss.c
new file mode 100644 (file)
index 0000000..0d59b21
--- /dev/null
@@ -0,0 +1,303 @@
+/* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
+
+/*
+ * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#ifdef GSSAPI
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "ssh2.h"
+#include "log.h"
+#include "dispatch.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "packet.h"
+#include "ssh-gss.h"
+#include "monitor_wrap.h"
+
+extern ServerOptions options;
+
+static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
+static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
+static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
+static void input_gssapi_errtok(int, u_int32_t, void *);
+
+/*
+ * We only support those mechanisms that we know about (ie ones that we know
+ * how to check local user kuserok and the like)
+ */
+static int
+userauth_gssapi(Authctxt *authctxt)
+{
+       gss_OID_desc goid = {0, NULL};
+       Gssctxt *ctxt = NULL;
+       int mechs;
+       gss_OID_set supported;
+       int present;
+       OM_uint32 ms;
+       u_int len;
+       u_char *doid = NULL;
+
+       if (!authctxt->valid || authctxt->user == NULL)
+               return (0);
+
+       mechs = packet_get_int();
+       if (mechs == 0) {
+               debug("Mechanism negotiation is not supported");
+               return (0);
+       }
+
+       ssh_gssapi_supported_oids(&supported);
+       do {
+               mechs--;
+
+               if (doid)
+                       xfree(doid);
+
+               present = 0;
+               doid = packet_get_string(&len);
+
+               if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
+                   doid[1] == len - 2) {
+                       goid.elements = doid + 2;
+                       goid.length   = len - 2;
+                       gss_test_oid_set_member(&ms, &goid, supported,
+                           &present);
+               } else {
+                       logit("Badly formed OID received");
+               }
+       } while (mechs > 0 && !present);
+
+       gss_release_oid_set(&ms, &supported);
+
+       if (!present) {
+               xfree(doid);
+               authctxt->server_caused_failure = 1;
+               return (0);
+       }
+
+       if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
+               if (ctxt != NULL)
+                       ssh_gssapi_delete_ctx(&ctxt);
+               xfree(doid);
+               authctxt->server_caused_failure = 1;
+               return (0);
+       }
+
+       authctxt->methoddata = (void *)ctxt;
+
+       packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
+
+       /* Return the OID that we received */
+       packet_put_string(doid, len);
+
+       packet_send();
+       xfree(doid);
+
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
+       authctxt->postponed = 1;
+
+       return (0);
+}
+
+static void
+input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc recv_tok;
+       OM_uint32 maj_status, min_status, flags;
+       u_int len;
+
+       if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+               fatal("No authentication or GSSAPI context");
+
+       gssctxt = authctxt->methoddata;
+       recv_tok.value = packet_get_string(&len);
+       recv_tok.length = len; /* u_int vs. size_t */
+
+       packet_check_eom();
+
+       maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
+           &send_tok, &flags));
+
+       xfree(recv_tok.value);
+
+       if (GSS_ERROR(maj_status)) {
+               if (send_tok.length != 0) {
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+                       packet_put_string(send_tok.value, send_tok.length);
+                       packet_send();
+               }
+               authctxt->postponed = 0;
+               dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+               userauth_finish(authctxt, 0, "gssapi-with-mic");
+       } else {
+               if (send_tok.length != 0) {
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+                       packet_put_string(send_tok.value, send_tok.length);
+                       packet_send();
+               }
+               if (maj_status == GSS_S_COMPLETE) {
+                       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+                       if (flags & GSS_C_INTEG_FLAG)
+                               dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
+                                   &input_gssapi_mic);
+                       else
+                               dispatch_set(
+                                   SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
+                                   &input_gssapi_exchange_complete);
+               }
+       }
+
+       gss_release_buffer(&min_status, &send_tok);
+}
+
+static void
+input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc recv_tok;
+       OM_uint32 maj_status;
+       u_int len;
+
+       if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+               fatal("No authentication or GSSAPI context");
+
+       gssctxt = authctxt->methoddata;
+       recv_tok.value = packet_get_string(&len);
+       recv_tok.length = len;
+
+       packet_check_eom();
+
+       /* Push the error token into GSSAPI to see what it says */
+       maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
+           &send_tok, NULL));
+
+       xfree(recv_tok.value);
+
+       /* We can't return anything to the client, even if we wanted to */
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
+
+       /* The client will have already moved on to the next auth */
+
+       gss_release_buffer(&maj_status, &send_tok);
+}
+
+/*
+ * This is called when the client thinks we've completed authentication.
+ * It should only be enabled in the dispatch handler by the function above,
+ * which only enables it once the GSSAPI exchange is complete.
+ */
+
+static void
+input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       int authenticated;
+
+       if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+               fatal("No authentication or GSSAPI context");
+
+       gssctxt = authctxt->methoddata;
+
+       /*
+        * We don't need to check the status, because we're only enabled in
+        * the dispatcher once the exchange is complete
+        */
+
+       packet_check_eom();
+
+       authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+
+       authctxt->postponed = 0;
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+       userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+}
+
+static void
+input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       int authenticated = 0;
+       Buffer b;
+       gss_buffer_desc mic, gssbuf;
+       u_int len;
+
+       if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+               fatal("No authentication or GSSAPI context");
+
+       gssctxt = authctxt->methoddata;
+
+       mic.value = packet_get_string(&len);
+       mic.length = len;
+
+       ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
+           "gssapi-with-mic");
+
+       gssbuf.value = buffer_ptr(&b);
+       gssbuf.length = buffer_len(&b);
+
+       if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
+               authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+       else
+               logit("GSSAPI MIC check failed");
+
+       buffer_free(&b);
+       xfree(mic.value);
+
+       authctxt->postponed = 0;
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+       userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+}
+
+Authmethod method_gssapi = {
+       "gssapi-with-mic",
+       userauth_gssapi,
+       &options.gss_authentication
+};
+
+#endif /* GSSAPI */
diff --git a/.pc/gssapi.patch/auth2.c b/.pc/gssapi.patch/auth2.c
new file mode 100644 (file)
index 0000000..c06c95f
--- /dev/null
@@ -0,0 +1,409 @@
+/* $OpenBSD: auth2.c,v 1.123 2011/03/10 02:52:57 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "atomicio.h"
+#include "xmalloc.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "compat.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "dispatch.h"
+#include "pathnames.h"
+#include "buffer.h"
+
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern u_int session_id2_len;
+extern Buffer loginmsg;
+
+/* methods */
+
+extern Authmethod method_none;
+extern Authmethod method_pubkey;
+extern Authmethod method_passwd;
+extern Authmethod method_kbdint;
+extern Authmethod method_hostbased;
+#ifdef GSSAPI
+extern Authmethod method_gssapi;
+#endif
+#ifdef JPAKE
+extern Authmethod method_jpake;
+#endif
+
+Authmethod *authmethods[] = {
+       &method_none,
+       &method_pubkey,
+#ifdef GSSAPI
+       &method_gssapi,
+#endif
+#ifdef JPAKE
+       &method_jpake,
+#endif
+       &method_passwd,
+       &method_kbdint,
+       &method_hostbased,
+       NULL
+};
+
+/* protocol */
+
+static void input_service_request(int, u_int32_t, void *);
+static void input_userauth_request(int, u_int32_t, void *);
+
+/* helper */
+static Authmethod *authmethod_lookup(const char *);
+static char *authmethods_get(void);
+
+char *
+auth2_read_banner(void)
+{
+       struct stat st;
+       char *banner = NULL;
+       size_t len, n;
+       int fd;
+
+       if ((fd = open(options.banner, O_RDONLY)) == -1)
+               return (NULL);
+       if (fstat(fd, &st) == -1) {
+               close(fd);
+               return (NULL);
+       }
+       if (st.st_size > 1*1024*1024) {
+               close(fd);
+               return (NULL);
+       }
+
+       len = (size_t)st.st_size;               /* truncate */
+       banner = xmalloc(len + 1);
+       n = atomicio(read, fd, banner, len);
+       close(fd);
+
+       if (n != len) {
+               xfree(banner);
+               return (NULL);
+       }
+       banner[n] = '\0';
+
+       return (banner);
+}
+
+void
+userauth_send_banner(const char *msg)
+{
+       if (datafellows & SSH_BUG_BANNER)
+               return;
+
+       packet_start(SSH2_MSG_USERAUTH_BANNER);
+       packet_put_cstring(msg);
+       packet_put_cstring("");         /* language, unused */
+       packet_send();
+       debug("%s: sent", __func__);
+}
+
+static void
+userauth_banner(void)
+{
+       char *banner = NULL;
+
+       if (options.banner == NULL ||
+           strcasecmp(options.banner, "none") == 0 ||
+           (datafellows & SSH_BUG_BANNER) != 0)
+               return;
+
+       if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
+               goto done;
+       userauth_send_banner(banner);
+
+done:
+       if (banner)
+               xfree(banner);
+}
+
+/*
+ * loop until authctxt->success == TRUE
+ */
+void
+do_authentication2(Authctxt *authctxt)
+{
+       dispatch_init(&dispatch_protocol_error);
+       dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
+       dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
+}
+
+/*ARGSUSED*/
+static void
+input_service_request(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       u_int len;
+       int acceptit = 0;
+       char *service = packet_get_cstring(&len);
+       packet_check_eom();
+
+       if (authctxt == NULL)
+               fatal("input_service_request: no authctxt");
+
+       if (strcmp(service, "ssh-userauth") == 0) {
+               if (!authctxt->success) {
+                       acceptit = 1;
+                       /* now we can handle user-auth requests */
+                       dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
+               }
+       }
+       /* XXX all other service requests are denied */
+
+       if (acceptit) {
+               packet_start(SSH2_MSG_SERVICE_ACCEPT);
+               packet_put_cstring(service);
+               packet_send();
+               packet_write_wait();
+       } else {
+               debug("bad service request %s", service);
+               packet_disconnect("bad service request %s", service);
+       }
+       xfree(service);
+}
+
+/*ARGSUSED*/
+static void
+input_userauth_request(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Authmethod *m = NULL;
+       char *user, *service, *method, *style = NULL;
+       int authenticated = 0;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_request: no authctxt");
+
+       user = packet_get_cstring(NULL);
+       service = packet_get_cstring(NULL);
+       method = packet_get_cstring(NULL);
+       debug("userauth-request for user %s service %s method %s", user, service, method);
+       debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
+
+       if ((style = strchr(user, ':')) != NULL)
+               *style++ = 0;
+
+       if (authctxt->attempt++ == 0) {
+               /* setup auth context */
+               authctxt->pw = PRIVSEP(getpwnamallow(user));
+               authctxt->user = xstrdup(user);
+               if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
+                       authctxt->valid = 1;
+                       debug2("input_userauth_request: setting up authctxt for %s", user);
+               } else {
+                       logit("input_userauth_request: invalid user %s", user);
+                       authctxt->pw = fakepw();
+#ifdef SSH_AUDIT_EVENTS
+                       PRIVSEP(audit_event(SSH_INVALID_USER));
+#endif
+               }
+#ifdef USE_PAM
+               if (options.use_pam)
+                       PRIVSEP(start_pam(authctxt));
+#endif
+               setproctitle("%s%s", authctxt->valid ? user : "unknown",
+                   use_privsep ? " [net]" : "");
+               authctxt->service = xstrdup(service);
+               authctxt->style = style ? xstrdup(style) : NULL;
+               if (use_privsep)
+                       mm_inform_authserv(service, style);
+               userauth_banner();
+       } else if (strcmp(user, authctxt->user) != 0 ||
+           strcmp(service, authctxt->service) != 0) {
+               packet_disconnect("Change of username or service not allowed: "
+                   "(%s,%s) -> (%s,%s)",
+                   authctxt->user, authctxt->service, user, service);
+       }
+       /* reset state */
+       auth2_challenge_stop(authctxt);
+#ifdef JPAKE
+       auth2_jpake_stop(authctxt);
+#endif
+
+#ifdef GSSAPI
+       /* XXX move to auth2_gssapi_stop() */
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+#endif
+
+       authctxt->postponed = 0;
+       authctxt->server_caused_failure = 0;
+
+       /* try to authenticate user */
+       m = authmethod_lookup(method);
+       if (m != NULL && authctxt->failures < options.max_authtries) {
+               debug2("input_userauth_request: try method %s", method);
+               authenticated = m->userauth(authctxt);
+       }
+       userauth_finish(authctxt, authenticated, method);
+
+       xfree(service);
+       xfree(user);
+       xfree(method);
+}
+
+void
+userauth_finish(Authctxt *authctxt, int authenticated, char *method)
+{
+       char *methods;
+
+       if (!authctxt->valid && authenticated)
+               fatal("INTERNAL ERROR: authenticated invalid user %s",
+                   authctxt->user);
+
+       /* Special handling for root */
+       if (authenticated && authctxt->pw->pw_uid == 0 &&
+           !auth_root_allowed(method)) {
+               authenticated = 0;
+#ifdef SSH_AUDIT_EVENTS
+               PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
+#endif
+       }
+
+#ifdef USE_PAM
+       if (options.use_pam && authenticated) {
+               if (!PRIVSEP(do_pam_account())) {
+                       /* if PAM returned a message, send it to the user */
+                       if (buffer_len(&loginmsg) > 0) {
+                               buffer_append(&loginmsg, "\0", 1);
+                               userauth_send_banner(buffer_ptr(&loginmsg));
+                               packet_write_wait();
+                       }
+                       fatal("Access denied for user %s by PAM account "
+                           "configuration", authctxt->user);
+               }
+       }
+#endif
+
+#ifdef _UNICOS
+       if (authenticated && cray_access_denied(authctxt->user)) {
+               authenticated = 0;
+               fatal("Access denied for user %s.",authctxt->user);
+       }
+#endif /* _UNICOS */
+
+       /* Log before sending the reply */
+       auth_log(authctxt, authenticated, method, " ssh2");
+
+       if (authctxt->postponed)
+               return;
+
+       /* XXX todo: check if multiple auth methods are needed */
+       if (authenticated == 1) {
+               /* turn off userauth */
+               dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
+               packet_start(SSH2_MSG_USERAUTH_SUCCESS);
+               packet_send();
+               packet_write_wait();
+               /* now we can break out */
+               authctxt->success = 1;
+       } else {
+
+               /* Allow initial try of "none" auth without failure penalty */
+               if (!authctxt->server_caused_failure &&
+                   (authctxt->attempt > 1 || strcmp(method, "none") != 0))
+                       authctxt->failures++;
+               if (authctxt->failures >= options.max_authtries) {
+#ifdef SSH_AUDIT_EVENTS
+                       PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
+#endif
+                       packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+               }
+               methods = authmethods_get();
+               packet_start(SSH2_MSG_USERAUTH_FAILURE);
+               packet_put_cstring(methods);
+               packet_put_char(0);     /* XXX partial success, unused */
+               packet_send();
+               packet_write_wait();
+               xfree(methods);
+       }
+}
+
+static char *
+authmethods_get(void)
+{
+       Buffer b;
+       char *list;
+       int i;
+
+       buffer_init(&b);
+       for (i = 0; authmethods[i] != NULL; i++) {
+               if (strcmp(authmethods[i]->name, "none") == 0)
+                       continue;
+               if (authmethods[i]->enabled != NULL &&
+                   *(authmethods[i]->enabled) != 0) {
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       buffer_append(&b, authmethods[i]->name,
+                           strlen(authmethods[i]->name));
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       list = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       return list;
+}
+
+static Authmethod *
+authmethod_lookup(const char *name)
+{
+       int i;
+
+       if (name != NULL)
+               for (i = 0; authmethods[i] != NULL; i++)
+                       if (authmethods[i]->enabled != NULL &&
+                           *(authmethods[i]->enabled) != 0 &&
+                           strcmp(name, authmethods[i]->name) == 0)
+                               return authmethods[i];
+       debug2("Unrecognized authentication method name: %s",
+           name ? name : "NULL");
+       return NULL;
+}
+
diff --git a/.pc/gssapi.patch/clientloop.c b/.pc/gssapi.patch/clientloop.c
new file mode 100644 (file)
index 0000000..c19b01f
--- /dev/null
@@ -0,0 +1,2175 @@
+/* $OpenBSD: clientloop.c,v 1.236 2011/06/22 22:08:42 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * The main loop for the interactive session (client side).
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ *
+ * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * SSH2 support added by Markus Friedl.
+ * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <errno.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "buffer.h"
+#include "compat.h"
+#include "channels.h"
+#include "dispatch.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "readconf.h"
+#include "clientloop.h"
+#include "sshconnect.h"
+#include "authfd.h"
+#include "atomicio.h"
+#include "sshpty.h"
+#include "misc.h"
+#include "match.h"
+#include "msg.h"
+#include "roaming.h"
+
+/* import options */
+extern Options options;
+
+/* Flag indicating that stdin should be redirected from /dev/null. */
+extern int stdin_null_flag;
+
+/* Flag indicating that no shell has been requested */
+extern int no_shell_flag;
+
+/* Control socket */
+extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
+
+/*
+ * Name of the host we are connecting to.  This is the name given on the
+ * command line, or the HostName specified for the user-supplied name in a
+ * configuration file.
+ */
+extern char *host;
+
+/*
+ * Flag to indicate that we have received a window change signal which has
+ * not yet been processed.  This will cause a message indicating the new
+ * window size to be sent to the server a little later.  This is volatile
+ * because this is updated in a signal handler.
+ */
+static volatile sig_atomic_t received_window_change_signal = 0;
+static volatile sig_atomic_t received_signal = 0;
+
+/* Flag indicating whether the user's terminal is in non-blocking mode. */
+static int in_non_blocking_mode = 0;
+
+/* Time when backgrounded control master using ControlPersist should exit */
+static time_t control_persist_exit_time = 0;
+
+/* Common data for the client loop code. */
+volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
+static int escape_char1;       /* Escape character. (proto1 only) */
+static int escape_pending1;    /* Last character was an escape (proto1 only) */
+static int last_was_cr;                /* Last character was a newline. */
+static int exit_status;                /* Used to store the command exit status. */
+static int stdin_eof;          /* EOF has been encountered on stderr. */
+static Buffer stdin_buffer;    /* Buffer for stdin data. */
+static Buffer stdout_buffer;   /* Buffer for stdout data. */
+static Buffer stderr_buffer;   /* Buffer for stderr data. */
+static u_int buffer_high;      /* Soft max buffer size. */
+static int connection_in;      /* Connection to server (input). */
+static int connection_out;     /* Connection to server (output). */
+static int need_rekeying;      /* Set to non-zero if rekeying is requested. */
+static int session_closed;     /* In SSH2: login session closed. */
+static int x11_refuse_time;    /* If >0, refuse x11 opens after this time. */
+
+static void client_init_dispatch(void);
+int    session_ident = -1;
+
+int    session_resumed = 0;
+
+/* Track escape per proto2 channel */
+struct escape_filter_ctx {
+       int escape_pending;
+       int escape_char;
+};
+
+/* Context for channel confirmation replies */
+struct channel_reply_ctx {
+       const char *request_type;
+       int id;
+       enum confirm_action action;
+};
+
+/* Global request success/failure callbacks */
+struct global_confirm {
+       TAILQ_ENTRY(global_confirm) entry;
+       global_confirm_cb *cb;
+       void *ctx;
+       int ref_count;
+};
+TAILQ_HEAD(global_confirms, global_confirm);
+static struct global_confirms global_confirms =
+    TAILQ_HEAD_INITIALIZER(global_confirms);
+
+/*XXX*/
+extern Kex *xxx_kex;
+
+void ssh_process_session2_setup(int, int, int, Buffer *);
+
+/* Restores stdin to blocking mode. */
+
+static void
+leave_non_blocking(void)
+{
+       if (in_non_blocking_mode) {
+               unset_nonblock(fileno(stdin));
+               in_non_blocking_mode = 0;
+       }
+}
+
+/* Puts stdin terminal in non-blocking mode. */
+
+static void
+enter_non_blocking(void)
+{
+       in_non_blocking_mode = 1;
+       set_nonblock(fileno(stdin));
+}
+
+/*
+ * Signal handler for the window change signal (SIGWINCH).  This just sets a
+ * flag indicating that the window has changed.
+ */
+/*ARGSUSED */
+static void
+window_change_handler(int sig)
+{
+       received_window_change_signal = 1;
+       signal(SIGWINCH, window_change_handler);
+}
+
+/*
+ * Signal handler for signals that cause the program to terminate.  These
+ * signals must be trapped to restore terminal modes.
+ */
+/*ARGSUSED */
+static void
+signal_handler(int sig)
+{
+       received_signal = sig;
+       quit_pending = 1;
+}
+
+/*
+ * Returns current time in seconds from Jan 1, 1970 with the maximum
+ * available resolution.
+ */
+
+static double
+get_current_time(void)
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+}
+
+/*
+ * Sets control_persist_exit_time to the absolute time when the
+ * backgrounded control master should exit due to expiry of the
+ * ControlPersist timeout.  Sets it to 0 if we are not a backgrounded
+ * control master process, or if there is no ControlPersist timeout.
+ */
+static void
+set_control_persist_exit_time(void)
+{
+       if (muxserver_sock == -1 || !options.control_persist
+           || options.control_persist_timeout == 0) {
+               /* not using a ControlPersist timeout */
+               control_persist_exit_time = 0;
+       } else if (channel_still_open()) {
+               /* some client connections are still open */
+               if (control_persist_exit_time > 0)
+                       debug2("%s: cancel scheduled exit", __func__);
+               control_persist_exit_time = 0;
+       } else if (control_persist_exit_time <= 0) {
+               /* a client connection has recently closed */
+               control_persist_exit_time = time(NULL) +
+                       (time_t)options.control_persist_timeout;
+               debug2("%s: schedule exit in %d seconds", __func__,
+                   options.control_persist_timeout);
+       }
+       /* else we are already counting down to the timeout */
+}
+
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+void
+client_x11_get_proto(const char *display, const char *xauth_path,
+    u_int trusted, u_int timeout, char **_proto, char **_data)
+{
+       char cmd[1024];
+       char line[512];
+       char xdisplay[512];
+       static char proto[512], data[512];
+       FILE *f;
+       int got_data = 0, generated = 0, do_unlink = 0, i;
+       char *xauthdir, *xauthfile;
+       struct stat st;
+       u_int now;
+
+       xauthdir = xauthfile = NULL;
+       *_proto = proto;
+       *_data = data;
+       proto[0] = data[0] = '\0';
+
+       if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
+               debug("No xauth program.");
+       } else {
+               if (display == NULL) {
+                       debug("x11_get_proto: DISPLAY not set");
+                       return;
+               }
+               /*
+                * Handle FamilyLocal case where $DISPLAY does
+                * not match an authorization entry.  For this we
+                * just try "xauth list unix:displaynum.screennum".
+                * XXX: "localhost" match to determine FamilyLocal
+                *      is not perfect.
+                */
+               if (strncmp(display, "localhost:", 10) == 0) {
+                       snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
+                           display + 10);
+                       display = xdisplay;
+               }
+               if (trusted == 0) {
+                       xauthdir = xmalloc(MAXPATHLEN);
+                       xauthfile = xmalloc(MAXPATHLEN);
+                       mktemp_proto(xauthdir, MAXPATHLEN);
+                       if (mkdtemp(xauthdir) != NULL) {
+                               do_unlink = 1;
+                               snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
+                                   xauthdir);
+                               snprintf(cmd, sizeof(cmd),
+                                   "%s -f %s generate %s " SSH_X11_PROTO
+                                   " untrusted timeout %u 2>" _PATH_DEVNULL,
+                                   xauth_path, xauthfile, display, timeout);
+                               debug2("x11_get_proto: %s", cmd);
+                               if (system(cmd) == 0)
+                                       generated = 1;
+                               if (x11_refuse_time == 0) {
+                                       now = time(NULL) + 1;
+                                       if (UINT_MAX - timeout < now)
+                                               x11_refuse_time = UINT_MAX;
+                                       else
+                                               x11_refuse_time = now + timeout;
+                               }
+                       }
+               }
+
+               /*
+                * When in untrusted mode, we read the cookie only if it was
+                * successfully generated as an untrusted one in the step
+                * above.
+                */
+               if (trusted || generated) {
+                       snprintf(cmd, sizeof(cmd),
+                           "%s %s%s list %s 2>" _PATH_DEVNULL,
+                           xauth_path,
+                           generated ? "-f " : "" ,
+                           generated ? xauthfile : "",
+                           display);
+                       debug2("x11_get_proto: %s", cmd);
+                       f = popen(cmd, "r");
+                       if (f && fgets(line, sizeof(line), f) &&
+                           sscanf(line, "%*s %511s %511s", proto, data) == 2)
+                               got_data = 1;
+                       if (f)
+                               pclose(f);
+               } else
+                       error("Warning: untrusted X11 forwarding setup failed: "
+                           "xauth key data not generated");
+       }
+
+       if (do_unlink) {
+               unlink(xauthfile);
+               rmdir(xauthdir);
+       }
+       if (xauthdir)
+               xfree(xauthdir);
+       if (xauthfile)
+               xfree(xauthfile);
+
+       /*
+        * If we didn't get authentication data, just make up some
+        * data.  The forwarding code will check the validity of the
+        * response anyway, and substitute this data.  The X11
+        * server, however, will ignore this fake data and use
+        * whatever authentication mechanisms it was using otherwise
+        * for the local connection.
+        */
+       if (!got_data) {
+               u_int32_t rnd = 0;
+
+               logit("Warning: No xauth data; "
+                   "using fake authentication data for X11 forwarding.");
+               strlcpy(proto, SSH_X11_PROTO, sizeof proto);
+               for (i = 0; i < 16; i++) {
+                       if (i % 4 == 0)
+                               rnd = arc4random();
+                       snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
+                           rnd & 0xff);
+                       rnd >>= 8;
+               }
+       }
+}
+
+/*
+ * This is called when the interactive is entered.  This checks if there is
+ * an EOF coming on stdin.  We must check this explicitly, as select() does
+ * not appear to wake up when redirecting from /dev/null.
+ */
+
+static void
+client_check_initial_eof_on_stdin(void)
+{
+       int len;
+       char buf[1];
+
+       /*
+        * If standard input is to be "redirected from /dev/null", we simply
+        * mark that we have seen an EOF and send an EOF message to the
+        * server. Otherwise, we try to read a single character; it appears
+        * that for some files, such /dev/null, select() never wakes up for
+        * read for this descriptor, which means that we never get EOF.  This
+        * way we will get the EOF if stdin comes from /dev/null or similar.
+        */
+       if (stdin_null_flag) {
+               /* Fake EOF on stdin. */
+               debug("Sending eof.");
+               stdin_eof = 1;
+               packet_start(SSH_CMSG_EOF);
+               packet_send();
+       } else {
+               enter_non_blocking();
+
+               /* Check for immediate EOF on stdin. */
+               len = read(fileno(stdin), buf, 1);
+               if (len == 0) {
+                       /*
+                        * EOF.  Record that we have seen it and send
+                        * EOF to server.
+                        */
+                       debug("Sending eof.");
+                       stdin_eof = 1;
+                       packet_start(SSH_CMSG_EOF);
+                       packet_send();
+               } else if (len > 0) {
+                       /*
+                        * Got data.  We must store the data in the buffer,
+                        * and also process it as an escape character if
+                        * appropriate.
+                        */
+                       if ((u_char) buf[0] == escape_char1)
+                               escape_pending1 = 1;
+                       else
+                               buffer_append(&stdin_buffer, buf, 1);
+               }
+               leave_non_blocking();
+       }
+}
+
+
+/*
+ * Make packets from buffered stdin data, and buffer them for sending to the
+ * connection.
+ */
+
+static void
+client_make_packets_from_stdin_data(void)
+{
+       u_int len;
+
+       /* Send buffered stdin data to the server. */
+       while (buffer_len(&stdin_buffer) > 0 &&
+           packet_not_very_much_data_to_write()) {
+               len = buffer_len(&stdin_buffer);
+               /* Keep the packets at reasonable size. */
+               if (len > packet_get_maxsize())
+                       len = packet_get_maxsize();
+               packet_start(SSH_CMSG_STDIN_DATA);
+               packet_put_string(buffer_ptr(&stdin_buffer), len);
+               packet_send();
+               buffer_consume(&stdin_buffer, len);
+               /* If we have a pending EOF, send it now. */
+               if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
+                       packet_start(SSH_CMSG_EOF);
+                       packet_send();
+               }
+       }
+}
+
+/*
+ * Checks if the client window has changed, and sends a packet about it to
+ * the server if so.  The actual change is detected elsewhere (by a software
+ * interrupt on Unix); this just checks the flag and sends a message if
+ * appropriate.
+ */
+
+static void
+client_check_window_change(void)
+{
+       struct winsize ws;
+
+       if (! received_window_change_signal)
+               return;
+       /** XXX race */
+       received_window_change_signal = 0;
+
+       debug2("client_check_window_change: changed");
+
+       if (compat20) {
+               channel_send_window_changes();
+       } else {
+               if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
+                       return;
+               packet_start(SSH_CMSG_WINDOW_SIZE);
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+               packet_send();
+       }
+}
+
+static void
+client_global_request_reply(int type, u_int32_t seq, void *ctxt)
+{
+       struct global_confirm *gc;
+
+       if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
+               return;
+       if (gc->cb != NULL)
+               gc->cb(type, seq, gc->ctx);
+       if (--gc->ref_count <= 0) {
+               TAILQ_REMOVE(&global_confirms, gc, entry);
+               bzero(gc, sizeof(*gc));
+               xfree(gc);
+       }
+
+       packet_set_alive_timeouts(0);
+}
+
+static void
+server_alive_check(void)
+{
+       if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
+               logit("Timeout, server %s not responding.", host);
+               cleanup_exit(255);
+       }
+       packet_start(SSH2_MSG_GLOBAL_REQUEST);
+       packet_put_cstring("keepalive@openssh.com");
+       packet_put_char(1);     /* boolean: want reply */
+       packet_send();
+       /* Insert an empty placeholder to maintain ordering */
+       client_register_global_confirm(NULL, NULL);
+}
+
+/*
+ * Waits until the client can do something (some data becomes available on
+ * one of the file descriptors).
+ */
+static void
+client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
+    int *maxfdp, u_int *nallocp, int rekeying)
+{
+       struct timeval tv, *tvp;
+       int timeout_secs;
+       int ret;
+
+       /* Add any selections by the channel mechanism. */
+       channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
+
+       if (!compat20) {
+               /* Read from the connection, unless our buffers are full. */
+               if (buffer_len(&stdout_buffer) < buffer_high &&
+                   buffer_len(&stderr_buffer) < buffer_high &&
+                   channel_not_very_much_buffered_data())
+                       FD_SET(connection_in, *readsetp);
+               /*
+                * Read from stdin, unless we have seen EOF or have very much
+                * buffered data to send to the server.
+                */
+               if (!stdin_eof && packet_not_very_much_data_to_write())
+                       FD_SET(fileno(stdin), *readsetp);
+
+               /* Select stdout/stderr if have data in buffer. */
+               if (buffer_len(&stdout_buffer) > 0)
+                       FD_SET(fileno(stdout), *writesetp);
+               if (buffer_len(&stderr_buffer) > 0)
+                       FD_SET(fileno(stderr), *writesetp);
+       } else {
+               /* channel_prepare_select could have closed the last channel */
+               if (session_closed && !channel_still_open() &&
+                   !packet_have_data_to_write()) {
+                       /* clear mask since we did not call select() */
+                       memset(*readsetp, 0, *nallocp);
+                       memset(*writesetp, 0, *nallocp);
+                       return;
+               } else {
+                       FD_SET(connection_in, *readsetp);
+               }
+       }
+
+       /* Select server connection if have data to write to the server. */
+       if (packet_have_data_to_write())
+               FD_SET(connection_out, *writesetp);
+
+       /*
+        * Wait for something to happen.  This will suspend the process until
+        * some selected descriptor can be read, written, or has some other
+        * event pending, or a timeout expires.
+        */
+
+       timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
+       if (options.server_alive_interval > 0 && compat20)
+               timeout_secs = options.server_alive_interval;
+       set_control_persist_exit_time();
+       if (control_persist_exit_time > 0) {
+               timeout_secs = MIN(timeout_secs,
+                       control_persist_exit_time - time(NULL));
+               if (timeout_secs < 0)
+                       timeout_secs = 0;
+       }
+       if (timeout_secs == INT_MAX)
+               tvp = NULL;
+       else {
+               tv.tv_sec = timeout_secs;
+               tv.tv_usec = 0;
+               tvp = &tv;
+       }
+
+       ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+       if (ret < 0) {
+               char buf[100];
+
+               /*
+                * We have to clear the select masks, because we return.
+                * We have to return, because the mainloop checks for the flags
+                * set by the signal handlers.
+                */
+               memset(*readsetp, 0, *nallocp);
+               memset(*writesetp, 0, *nallocp);
+
+               if (errno == EINTR)
+                       return;
+               /* Note: we might still have data in the buffers. */
+               snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
+               buffer_append(&stderr_buffer, buf, strlen(buf));
+               quit_pending = 1;
+       } else if (ret == 0)
+               server_alive_check();
+}
+
+static void
+client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
+{
+       /* Flush stdout and stderr buffers. */
+       if (buffer_len(bout) > 0)
+               atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
+                   buffer_len(bout));
+       if (buffer_len(berr) > 0)
+               atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
+                   buffer_len(berr));
+
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       /*
+        * Free (and clear) the buffer to reduce the amount of data that gets
+        * written to swap.
+        */
+       buffer_free(bin);
+       buffer_free(bout);
+       buffer_free(berr);
+
+       /* Send the suspend signal to the program itself. */
+       kill(getpid(), SIGTSTP);
+
+       /* Reset window sizes in case they have changed */
+       received_window_change_signal = 1;
+
+       /* OK, we have been continued by the user. Reinitialize buffers. */
+       buffer_init(bin);
+       buffer_init(bout);
+       buffer_init(berr);
+
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+}
+
+static void
+client_process_net_input(fd_set *readset)
+{
+       int len, cont = 0;
+       char buf[SSH_IOBUFSZ];
+
+       /*
+        * Read input from the server, and add any such data to the buffer of
+        * the packet subsystem.
+        */
+       if (FD_ISSET(connection_in, readset)) {
+               /* Read as much as possible. */
+               len = roaming_read(connection_in, buf, sizeof(buf), &cont);
+               if (len == 0 && cont == 0) {
+                       /*
+                        * Received EOF.  The remote host has closed the
+                        * connection.
+                        */
+                       snprintf(buf, sizeof buf,
+                           "Connection to %.300s closed by remote host.\r\n",
+                           host);
+                       buffer_append(&stderr_buffer, buf, strlen(buf));
+                       quit_pending = 1;
+                       return;
+               }
+               /*
+                * There is a kernel bug on Solaris that causes select to
+                * sometimes wake up even though there is no data available.
+                */
+               if (len < 0 &&
+                   (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
+                       len = 0;
+
+               if (len < 0) {
+                       /*
+                        * An error has encountered.  Perhaps there is a
+                        * network problem.
+                        */
+                       snprintf(buf, sizeof buf,
+                           "Read from remote host %.300s: %.100s\r\n",
+                           host, strerror(errno));
+                       buffer_append(&stderr_buffer, buf, strlen(buf));
+                       quit_pending = 1;
+                       return;
+               }
+               packet_process_incoming(buf, len);
+       }
+}
+
+static void
+client_status_confirm(int type, Channel *c, void *ctx)
+{
+       struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
+       char errmsg[256];
+       int tochan;
+
+       /*
+        * If a TTY was explicitly requested, then a failure to allocate
+        * one is fatal.
+        */
+       if (cr->action == CONFIRM_TTY &&
+           (options.request_tty == REQUEST_TTY_FORCE ||
+           options.request_tty == REQUEST_TTY_YES))
+               cr->action = CONFIRM_CLOSE;
+
+       /* XXX supress on mux _client_ quietmode */
+       tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
+           c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
+
+       if (type == SSH2_MSG_CHANNEL_SUCCESS) {
+               debug2("%s request accepted on channel %d",
+                   cr->request_type, c->self);
+       } else if (type == SSH2_MSG_CHANNEL_FAILURE) {
+               if (tochan) {
+                       snprintf(errmsg, sizeof(errmsg),
+                           "%s request failed\r\n", cr->request_type);
+               } else {
+                       snprintf(errmsg, sizeof(errmsg),
+                           "%s request failed on channel %d",
+                           cr->request_type, c->self);
+               }
+               /* If error occurred on primary session channel, then exit */
+               if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
+                       fatal("%s", errmsg);
+               /*
+                * If error occurred on mux client, append to
+                * their stderr.
+                */
+               if (tochan) {
+                       buffer_append(&c->extended, errmsg,
+                           strlen(errmsg));
+               } else
+                       error("%s", errmsg);
+               if (cr->action == CONFIRM_TTY) {
+                       /*
+                        * If a TTY allocation error occurred, then arrange
+                        * for the correct TTY to leave raw mode.
+                        */
+                       if (c->self == session_ident)
+                               leave_raw_mode(0);
+                       else
+                               mux_tty_alloc_failed(c);
+               } else if (cr->action == CONFIRM_CLOSE) {
+                       chan_read_failed(c);
+                       chan_write_failed(c);
+               }
+       }
+       xfree(cr);
+}
+
+static void
+client_abandon_status_confirm(Channel *c, void *ctx)
+{
+       xfree(ctx);
+}
+
+void
+client_expect_confirm(int id, const char *request,
+    enum confirm_action action)
+{
+       struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
+
+       cr->request_type = request;
+       cr->action = action;
+
+       channel_register_status_confirm(id, client_status_confirm,
+           client_abandon_status_confirm, cr);
+}
+
+void
+client_register_global_confirm(global_confirm_cb *cb, void *ctx)
+{
+       struct global_confirm *gc, *last_gc;
+
+       /* Coalesce identical callbacks */
+       last_gc = TAILQ_LAST(&global_confirms, global_confirms);
+       if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
+               if (++last_gc->ref_count >= INT_MAX)
+                       fatal("%s: last_gc->ref_count = %d",
+                           __func__, last_gc->ref_count);
+               return;
+       }
+
+       gc = xmalloc(sizeof(*gc));
+       gc->cb = cb;
+       gc->ctx = ctx;
+       gc->ref_count = 1;
+       TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
+}
+
+static void
+process_cmdline(void)
+{
+       void (*handler)(int);
+       char *s, *cmd, *cancel_host;
+       int delete = 0;
+       int local = 0, remote = 0, dynamic = 0;
+       int cancel_port;
+       Forward fwd;
+
+       bzero(&fwd, sizeof(fwd));
+       fwd.listen_host = fwd.connect_host = NULL;
+
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       handler = signal(SIGINT, SIG_IGN);
+       cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
+       if (s == NULL)
+               goto out;
+       while (isspace(*s))
+               s++;
+       if (*s == '-')
+               s++;    /* Skip cmdline '-', if any */
+       if (*s == '\0')
+               goto out;
+
+       if (*s == 'h' || *s == 'H' || *s == '?') {
+               logit("Commands:");
+               logit("      -L[bind_address:]port:host:hostport    "
+                   "Request local forward");
+               logit("      -R[bind_address:]port:host:hostport    "
+                   "Request remote forward");
+               logit("      -D[bind_address:]port                  "
+                   "Request dynamic forward");
+               logit("      -KR[bind_address:]port                 "
+                   "Cancel remote forward");
+               if (!options.permit_local_command)
+                       goto out;
+               logit("      !args                                  "
+                   "Execute local command");
+               goto out;
+       }
+
+       if (*s == '!' && options.permit_local_command) {
+               s++;
+               ssh_local_cmd(s);
+               goto out;
+       }
+
+       if (*s == 'K') {
+               delete = 1;
+               s++;
+       }
+       if (*s == 'L')
+               local = 1;
+       else if (*s == 'R')
+               remote = 1;
+       else if (*s == 'D')
+               dynamic = 1;
+       else {
+               logit("Invalid command.");
+               goto out;
+       }
+
+       if ((local || dynamic) && delete) {
+               logit("Not supported.");
+               goto out;
+       }
+       if (remote && delete && !compat20) {
+               logit("Not supported for SSH protocol version 1.");
+               goto out;
+       }
+
+       while (isspace(*++s))
+               ;
+
+       /* XXX update list of forwards in options */
+       if (delete) {
+               cancel_port = 0;
+               cancel_host = hpdelim(&s);      /* may be NULL */
+               if (s != NULL) {
+                       cancel_port = a2port(s);
+                       cancel_host = cleanhostname(cancel_host);
+               } else {
+                       cancel_port = a2port(cancel_host);
+                       cancel_host = NULL;
+               }
+               if (cancel_port <= 0) {
+                       logit("Bad forwarding close port");
+                       goto out;
+               }
+               channel_request_rforward_cancel(cancel_host, cancel_port);
+       } else {
+               if (!parse_forward(&fwd, s, dynamic, remote)) {
+                       logit("Bad forwarding specification.");
+                       goto out;
+               }
+               if (local || dynamic) {
+                       if (channel_setup_local_fwd_listener(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port, options.gateway_ports) < 0) {
+                               logit("Port forwarding failed.");
+                               goto out;
+                       }
+               } else {
+                       if (channel_request_remote_forwarding(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port) < 0) {
+                               logit("Port forwarding failed.");
+                               goto out;
+                       }
+               }
+
+               logit("Forwarding port.");
+       }
+
+out:
+       signal(SIGINT, handler);
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       if (cmd)
+               xfree(cmd);
+       if (fwd.listen_host != NULL)
+               xfree(fwd.listen_host);
+       if (fwd.connect_host != NULL)
+               xfree(fwd.connect_host);
+}
+
+/* 
+ * Process the characters one by one, call with c==NULL for proto1 case.
+ */
+static int
+process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
+    char *buf, int len)
+{
+       char string[1024];
+       pid_t pid;
+       int bytes = 0;
+       u_int i;
+       u_char ch;
+       char *s;
+       int *escape_pendingp, escape_char;
+       struct escape_filter_ctx *efc;
+
+       if (c == NULL) {
+               escape_pendingp = &escape_pending1;
+               escape_char = escape_char1;
+       } else {
+               if (c->filter_ctx == NULL)
+                       return 0;
+               efc = (struct escape_filter_ctx *)c->filter_ctx;
+               escape_pendingp = &efc->escape_pending;
+               escape_char = efc->escape_char;
+       }
+       
+       if (len <= 0)
+               return (0);
+
+       for (i = 0; i < (u_int)len; i++) {
+               /* Get one character at a time. */
+               ch = buf[i];
+
+               if (*escape_pendingp) {
+                       /* We have previously seen an escape character. */
+                       /* Clear the flag now. */
+                       *escape_pendingp = 0;
+
+                       /* Process the escaped character. */
+                       switch (ch) {
+                       case '.':
+                               /* Terminate the connection. */
+                               snprintf(string, sizeof string, "%c.\r\n",
+                                   escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               if (c && c->ctl_chan != -1) {
+                                       chan_read_failed(c);
+                                       chan_write_failed(c);
+                                       return 0;
+                               } else
+                                       quit_pending = 1;
+                               return -1;
+
+                       case 'Z' - 64:
+                               /* XXX support this for mux clients */
+                               if (c && c->ctl_chan != -1) {
+ noescape:
+                                       snprintf(string, sizeof string,
+                                           "%c%c escape not available to "
+                                           "multiplexed sessions\r\n",
+                                           escape_char, ch);
+                                       buffer_append(berr, string,
+                                           strlen(string));
+                                       continue;
+                               }
+                               /* Suspend the program. Inform the user */
+                               snprintf(string, sizeof string,
+                                   "%c^Z [suspend ssh]\r\n", escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               /* Restore terminal modes and suspend. */
+                               client_suspend_self(bin, bout, berr);
+
+                               /* We have been continued. */
+                               continue;
+
+                       case 'B':
+                               if (compat20) {
+                                       snprintf(string, sizeof string,
+                                           "%cB\r\n", escape_char);
+                                       buffer_append(berr, string,
+                                           strlen(string));
+                                       channel_request_start(session_ident,
+                                           "break", 0);
+                                       packet_put_int(1000);
+                                       packet_send();
+                               }
+                               continue;
+
+                       case 'R':
+                               if (compat20) {
+                                       if (datafellows & SSH_BUG_NOREKEY)
+                                               logit("Server does not "
+                                                   "support re-keying");
+                                       else
+                                               need_rekeying = 1;
+                               }
+                               continue;
+
+                       case '&':
+                               if (c && c->ctl_chan != -1)
+                                       goto noescape;
+                               /*
+                                * Detach the program (continue to serve
+                                * connections, but put in background and no
+                                * more new connections).
+                                */
+                               /* Restore tty modes. */
+                               leave_raw_mode(
+                                   options.request_tty == REQUEST_TTY_FORCE);
+
+                               /* Stop listening for new connections. */
+                               channel_stop_listening();
+
+                               snprintf(string, sizeof string,
+                                   "%c& [backgrounded]\n", escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               /* Fork into background. */
+                               pid = fork();
+                               if (pid < 0) {
+                                       error("fork: %.100s", strerror(errno));
+                                       continue;
+                               }
+                               if (pid != 0) { /* This is the parent. */
+                                       /* The parent just exits. */
+                                       exit(0);
+                               }
+                               /* The child continues serving connections. */
+                               if (compat20) {
+                                       buffer_append(bin, "\004", 1);
+                                       /* fake EOF on stdin */
+                                       return -1;
+                               } else if (!stdin_eof) {
+                                       /*
+                                        * Sending SSH_CMSG_EOF alone does not
+                                        * always appear to be enough.  So we
+                                        * try to send an EOF character first.
+                                        */
+                                       packet_start(SSH_CMSG_STDIN_DATA);
+                                       packet_put_string("\004", 1);
+                                       packet_send();
+                                       /* Close stdin. */
+                                       stdin_eof = 1;
+                                       if (buffer_len(bin) == 0) {
+                                               packet_start(SSH_CMSG_EOF);
+                                               packet_send();
+                                       }
+                               }
+                               continue;
+
+                       case '?':
+                               if (c && c->ctl_chan != -1) {
+                                       snprintf(string, sizeof string,
+"%c?\r\n\
+Supported escape sequences:\r\n\
+  %c.  - terminate session\r\n\
+  %cB  - send a BREAK to the remote system\r\n\
+  %cR  - Request rekey (SSH protocol 2 only)\r\n\
+  %c#  - list forwarded connections\r\n\
+  %c?  - this message\r\n\
+  %c%c  - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char);
+                               } else {
+                                       snprintf(string, sizeof string,
+"%c?\r\n\
+Supported escape sequences:\r\n\
+  %c.  - terminate connection (and any multiplexed sessions)\r\n\
+  %cB  - send a BREAK to the remote system\r\n\
+  %cC  - open a command line\r\n\
+  %cR  - Request rekey (SSH protocol 2 only)\r\n\
+  %c^Z - suspend ssh\r\n\
+  %c#  - list forwarded connections\r\n\
+  %c&  - background ssh (when waiting for connections to terminate)\r\n\
+  %c?  - this message\r\n\
+  %c%c  - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char);
+                               }
+                               buffer_append(berr, string, strlen(string));
+                               continue;
+
+                       case '#':
+                               snprintf(string, sizeof string, "%c#\r\n",
+                                   escape_char);
+                               buffer_append(berr, string, strlen(string));
+                               s = channel_open_message();
+                               buffer_append(berr, s, strlen(s));
+                               xfree(s);
+                               continue;
+
+                       case 'C':
+                               if (c && c->ctl_chan != -1)
+                                       goto noescape;
+                               process_cmdline();
+                               continue;
+
+                       default:
+                               if (ch != escape_char) {
+                                       buffer_put_char(bin, escape_char);
+                                       bytes++;
+                               }
+                               /* Escaped characters fall through here */
+                               break;
+                       }
+               } else {
+                       /*
+                        * The previous character was not an escape char.
+                        * Check if this is an escape.
+                        */
+                       if (last_was_cr && ch == escape_char) {
+                               /*
+                                * It is. Set the flag and continue to
+                                * next character.
+                                */
+                               *escape_pendingp = 1;
+                               continue;
+                       }
+               }
+
+               /*
+                * Normal character.  Record whether it was a newline,
+                * and append it to the buffer.
+                */
+               last_was_cr = (ch == '\r' || ch == '\n');
+               buffer_put_char(bin, ch);
+               bytes++;
+       }
+       return bytes;
+}
+
+static void
+client_process_input(fd_set *readset)
+{
+       int len;
+       char buf[SSH_IOBUFSZ];
+
+       /* Read input from stdin. */
+       if (FD_ISSET(fileno(stdin), readset)) {
+               /* Read as much as possible. */
+               len = read(fileno(stdin), buf, sizeof(buf));
+               if (len < 0 &&
+                   (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
+                       return;         /* we'll try again later */
+               if (len <= 0) {
+                       /*
+                        * Received EOF or error.  They are treated
+                        * similarly, except that an error message is printed
+                        * if it was an error condition.
+                        */
+                       if (len < 0) {
+                               snprintf(buf, sizeof buf, "read: %.100s\r\n",
+                                   strerror(errno));
+                               buffer_append(&stderr_buffer, buf, strlen(buf));
+                       }
+                       /* Mark that we have seen EOF. */
+                       stdin_eof = 1;
+                       /*
+                        * Send an EOF message to the server unless there is
+                        * data in the buffer.  If there is data in the
+                        * buffer, no message will be sent now.  Code
+                        * elsewhere will send the EOF when the buffer
+                        * becomes empty if stdin_eof is set.
+                        */
+                       if (buffer_len(&stdin_buffer) == 0) {
+                               packet_start(SSH_CMSG_EOF);
+                               packet_send();
+                       }
+               } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
+                       /*
+                        * Normal successful read, and no escape character.
+                        * Just append the data to buffer.
+                        */
+                       buffer_append(&stdin_buffer, buf, len);
+               } else {
+                       /*
+                        * Normal, successful read.  But we have an escape
+                        * character and have to process the characters one
+                        * by one.
+                        */
+                       if (process_escapes(NULL, &stdin_buffer,
+                           &stdout_buffer, &stderr_buffer, buf, len) == -1)
+                               return;
+               }
+       }
+}
+
+static void
+client_process_output(fd_set *writeset)
+{
+       int len;
+       char buf[100];
+
+       /* Write buffered output to stdout. */
+       if (FD_ISSET(fileno(stdout), writeset)) {
+               /* Write as much data as possible. */
+               len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
+                   buffer_len(&stdout_buffer));
+               if (len <= 0) {
+                       if (errno == EINTR || errno == EAGAIN ||
+                           errno == EWOULDBLOCK)
+                               len = 0;
+                       else {
+                               /*
+                                * An error or EOF was encountered.  Put an
+                                * error message to stderr buffer.
+                                */
+                               snprintf(buf, sizeof buf,
+                                   "write stdout: %.50s\r\n", strerror(errno));
+                               buffer_append(&stderr_buffer, buf, strlen(buf));
+                               quit_pending = 1;
+                               return;
+                       }
+               }
+               /* Consume printed data from the buffer. */
+               buffer_consume(&stdout_buffer, len);
+       }
+       /* Write buffered output to stderr. */
+       if (FD_ISSET(fileno(stderr), writeset)) {
+               /* Write as much data as possible. */
+               len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
+                   buffer_len(&stderr_buffer));
+               if (len <= 0) {
+                       if (errno == EINTR || errno == EAGAIN ||
+                           errno == EWOULDBLOCK)
+                               len = 0;
+                       else {
+                               /*
+                                * EOF or error, but can't even print
+                                * error message.
+                                */
+                               quit_pending = 1;
+                               return;
+                       }
+               }
+               /* Consume printed characters from the buffer. */
+               buffer_consume(&stderr_buffer, len);
+       }
+}
+
+/*
+ * Get packets from the connection input buffer, and process them as long as
+ * there are packets available.
+ *
+ * Any unknown packets received during the actual
+ * session cause the session to terminate.  This is
+ * intended to make debugging easier since no
+ * confirmations are sent.  Any compatible protocol
+ * extensions must be negotiated during the
+ * preparatory phase.
+ */
+
+static void
+client_process_buffered_input_packets(void)
+{
+       dispatch_run(DISPATCH_NONBLOCK, &quit_pending,
+           compat20 ? xxx_kex : NULL);
+}
+
+/* scan buf[] for '~' before sending data to the peer */
+
+/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
+void *
+client_new_escape_filter_ctx(int escape_char)
+{
+       struct escape_filter_ctx *ret;
+
+       ret = xmalloc(sizeof(*ret));
+       ret->escape_pending = 0;
+       ret->escape_char = escape_char;
+       return (void *)ret;
+}
+
+/* Free the escape filter context on channel free */
+void
+client_filter_cleanup(int cid, void *ctx)
+{
+       xfree(ctx);
+}
+
+int
+client_simple_escape_filter(Channel *c, char *buf, int len)
+{
+       if (c->extended_usage != CHAN_EXTENDED_WRITE)
+               return 0;
+
+       return process_escapes(c, &c->input, &c->output, &c->extended,
+           buf, len);
+}
+
+static void
+client_channel_closed(int id, void *arg)
+{
+       channel_cancel_cleanup(id);
+       session_closed = 1;
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+}
+
+/*
+ * Implements the interactive session with the server.  This is called after
+ * the user has been authenticated, and a command has been started on the
+ * remote host.  If escape_char != SSH_ESCAPECHAR_NONE, it is the character
+ * used as an escape character for terminating or suspending the session.
+ */
+
+int
+client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
+{
+       fd_set *readset = NULL, *writeset = NULL;
+       double start_time, total_time;
+       int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
+       u_int64_t ibytes, obytes;
+       u_int nalloc = 0;
+       char buf[100];
+
+       debug("Entering interactive session.");
+
+       start_time = get_current_time();
+
+       /* Initialize variables. */
+       escape_pending1 = 0;
+       last_was_cr = 1;
+       exit_status = -1;
+       stdin_eof = 0;
+       buffer_high = 64 * 1024;
+       connection_in = packet_get_connection_in();
+       connection_out = packet_get_connection_out();
+       max_fd = MAX(connection_in, connection_out);
+
+       if (!compat20) {
+               /* enable nonblocking unless tty */
+               if (!isatty(fileno(stdin)))
+                       set_nonblock(fileno(stdin));
+               if (!isatty(fileno(stdout)))
+                       set_nonblock(fileno(stdout));
+               if (!isatty(fileno(stderr)))
+                       set_nonblock(fileno(stderr));
+               max_fd = MAX(max_fd, fileno(stdin));
+               max_fd = MAX(max_fd, fileno(stdout));
+               max_fd = MAX(max_fd, fileno(stderr));
+       }
+       quit_pending = 0;
+       escape_char1 = escape_char_arg;
+
+       /* Initialize buffers. */
+       buffer_init(&stdin_buffer);
+       buffer_init(&stdout_buffer);
+       buffer_init(&stderr_buffer);
+
+       client_init_dispatch();
+
+       /*
+        * Set signal handlers, (e.g. to restore non-blocking mode)
+        * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
+        */
+       if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+               signal(SIGHUP, signal_handler);
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, signal_handler);
+       if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+               signal(SIGQUIT, signal_handler);
+       if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+               signal(SIGTERM, signal_handler);
+       signal(SIGWINCH, window_change_handler);
+
+       if (have_pty)
+               enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       if (compat20) {
+               session_ident = ssh2_chan_id;
+               if (session_ident != -1) {
+                       if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
+                               channel_register_filter(session_ident,
+                                   client_simple_escape_filter, NULL,
+                                   client_filter_cleanup,
+                                   client_new_escape_filter_ctx(
+                                   escape_char_arg));
+                       }
+                       channel_register_cleanup(session_ident,
+                           client_channel_closed, 0);
+               }
+       } else {
+               /* Check if we should immediately send eof on stdin. */
+               client_check_initial_eof_on_stdin();
+       }
+
+       /* Main loop of the client for the interactive session mode. */
+       while (!quit_pending) {
+
+               /* Process buffered packets sent by the server. */
+               client_process_buffered_input_packets();
+
+               if (compat20 && session_closed && !channel_still_open())
+                       break;
+
+               rekeying = (xxx_kex != NULL && !xxx_kex->done);
+
+               if (rekeying) {
+                       debug("rekeying in progress");
+               } else {
+                       /*
+                        * Make packets of buffered stdin data, and buffer
+                        * them for sending to the server.
+                        */
+                       if (!compat20)
+                               client_make_packets_from_stdin_data();
+
+                       /*
+                        * Make packets from buffered channel data, and
+                        * enqueue them for sending to the server.
+                        */
+                       if (packet_not_very_much_data_to_write())
+                               channel_output_poll();
+
+                       /*
+                        * Check if the window size has changed, and buffer a
+                        * message about it to the server if so.
+                        */
+                       client_check_window_change();
+
+                       if (quit_pending)
+                               break;
+               }
+               /*
+                * Wait until we have something to do (something becomes
+                * available on one of the descriptors).
+                */
+               max_fd2 = max_fd;
+               client_wait_until_can_do_something(&readset, &writeset,
+                   &max_fd2, &nalloc, rekeying);
+
+               if (quit_pending)
+                       break;
+
+               /* Do channel operations unless rekeying in progress. */
+               if (!rekeying) {
+                       channel_after_select(readset, writeset);
+                       if (need_rekeying || packet_need_rekeying()) {
+                               debug("need rekeying");
+                               xxx_kex->done = 0;
+                               kex_send_kexinit(xxx_kex);
+                               need_rekeying = 0;
+                       }
+               }
+
+               /* Buffer input from the connection.  */
+               client_process_net_input(readset);
+
+               if (quit_pending)
+                       break;
+
+               if (!compat20) {
+                       /* Buffer data from stdin */
+                       client_process_input(readset);
+                       /*
+                        * Process output to stdout and stderr.  Output to
+                        * the connection is processed elsewhere (above).
+                        */
+                       client_process_output(writeset);
+               }
+
+               if (session_resumed) {
+                       connection_in = packet_get_connection_in();
+                       connection_out = packet_get_connection_out();
+                       max_fd = MAX(max_fd, connection_out);
+                       max_fd = MAX(max_fd, connection_in);
+                       session_resumed = 0;
+               }
+
+               /*
+                * Send as much buffered packet data as possible to the
+                * sender.
+                */
+               if (FD_ISSET(connection_out, writeset))
+                       packet_write_poll();
+
+               /*
+                * If we are a backgrounded control master, and the
+                * timeout has expired without any active client
+                * connections, then quit.
+                */
+               if (control_persist_exit_time > 0) {
+                       if (time(NULL) >= control_persist_exit_time) {
+                               debug("ControlPersist timeout expired");
+                               break;
+                       }
+               }
+       }
+       if (readset)
+               xfree(readset);
+       if (writeset)
+               xfree(writeset);
+
+       /* Terminate the session. */
+
+       /* Stop watching for window change. */
+       signal(SIGWINCH, SIG_DFL);
+
+       if (compat20) {
+               packet_start(SSH2_MSG_DISCONNECT);
+               packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
+               packet_put_cstring("disconnected by user");
+               packet_put_cstring(""); /* language tag */
+               packet_send();
+               packet_write_wait();
+       }
+
+       channel_free_all();
+
+       if (have_pty)
+               leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       /* restore blocking io */
+       if (!isatty(fileno(stdin)))
+               unset_nonblock(fileno(stdin));
+       if (!isatty(fileno(stdout)))
+               unset_nonblock(fileno(stdout));
+       if (!isatty(fileno(stderr)))
+               unset_nonblock(fileno(stderr));
+
+       /*
+        * If there was no shell or command requested, there will be no remote
+        * exit status to be returned.  In that case, clear error code if the
+        * connection was deliberately terminated at this end.
+        */
+       if (no_shell_flag && received_signal == SIGTERM) {
+               received_signal = 0;
+               exit_status = 0;
+       }
+
+       if (received_signal)
+               fatal("Killed by signal %d.", (int) received_signal);
+
+       /*
+        * In interactive mode (with pseudo tty) display a message indicating
+        * that the connection has been closed.
+        */
+       if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
+               snprintf(buf, sizeof buf,
+                   "Connection to %.64s closed.\r\n", host);
+               buffer_append(&stderr_buffer, buf, strlen(buf));
+       }
+
+       /* Output any buffered data for stdout. */
+       if (buffer_len(&stdout_buffer) > 0) {
+               len = atomicio(vwrite, fileno(stdout),
+                   buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer));
+               if (len < 0 || (u_int)len != buffer_len(&stdout_buffer))
+                       error("Write failed flushing stdout buffer.");
+               else
+                       buffer_consume(&stdout_buffer, len);
+       }
+
+       /* Output any buffered data for stderr. */
+       if (buffer_len(&stderr_buffer) > 0) {
+               len = atomicio(vwrite, fileno(stderr),
+                   buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer));
+               if (len < 0 || (u_int)len != buffer_len(&stderr_buffer))
+                       error("Write failed flushing stderr buffer.");
+               else
+                       buffer_consume(&stderr_buffer, len);
+       }
+
+       /* Clear and free any buffers. */
+       memset(buf, 0, sizeof(buf));
+       buffer_free(&stdin_buffer);
+       buffer_free(&stdout_buffer);
+       buffer_free(&stderr_buffer);
+
+       /* Report bytes transferred, and transfer rates. */
+       total_time = get_current_time() - start_time;
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
+           (unsigned long long)obytes, (unsigned long long)ibytes, total_time);
+       if (total_time > 0)
+               verbose("Bytes per second: sent %.1f, received %.1f",
+                   obytes / total_time, ibytes / total_time);
+       /* Return the exit status of the program. */
+       debug("Exit status %d", exit_status);
+       return exit_status;
+}
+
+/*********/
+
+static void
+client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
+{
+       u_int data_len;
+       char *data = packet_get_string(&data_len);
+       packet_check_eom();
+       buffer_append(&stdout_buffer, data, data_len);
+       memset(data, 0, data_len);
+       xfree(data);
+}
+static void
+client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
+{
+       u_int data_len;
+       char *data = packet_get_string(&data_len);
+       packet_check_eom();
+       buffer_append(&stderr_buffer, data, data_len);
+       memset(data, 0, data_len);
+       xfree(data);
+}
+static void
+client_input_exit_status(int type, u_int32_t seq, void *ctxt)
+{
+       exit_status = packet_get_int();
+       packet_check_eom();
+       /* Acknowledge the exit. */
+       packet_start(SSH_CMSG_EXIT_CONFIRMATION);
+       packet_send();
+       /*
+        * Must wait for packet to be sent since we are
+        * exiting the loop.
+        */
+       packet_write_wait();
+       /* Flag that we want to exit. */
+       quit_pending = 1;
+}
+static void
+client_input_agent_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       int remote_id, sock;
+
+       /* Read the remote channel number from the message. */
+       remote_id = packet_get_int();
+       packet_check_eom();
+
+       /*
+        * Get a connection to the local authentication agent (this may again
+        * get forwarded).
+        */
+       sock = ssh_get_authentication_socket();
+
+       /*
+        * If we could not connect the agent, send an error message back to
+        * the server. This should never happen unless the agent dies,
+        * because authentication forwarding is only enabled if we have an
+        * agent.
+        */
+       if (sock >= 0) {
+               c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
+                   -1, 0, 0, 0, "authentication agent connection", 1);
+               c->remote_id = remote_id;
+               c->force_drain = 1;
+       }
+       if (c == NULL) {
+               packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(remote_id);
+       } else {
+               /* Send a confirmation to the remote host. */
+               debug("Forwarding authentication connection.");
+               packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+               packet_put_int(remote_id);
+               packet_put_int(c->self);
+       }
+       packet_send();
+}
+
+static Channel *
+client_request_forwarded_tcpip(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       char *listen_address, *originator_address;
+       u_short listen_port, originator_port;
+
+       /* Get rest of the packet */
+       listen_address = packet_get_string(NULL);
+       listen_port = packet_get_int();
+       originator_address = packet_get_string(NULL);
+       originator_port = packet_get_int();
+       packet_check_eom();
+
+       debug("client_request_forwarded_tcpip: listen %s port %d, "
+           "originator %s port %d", listen_address, listen_port,
+           originator_address, originator_port);
+
+       c = channel_connect_by_listen_address(listen_port,
+           "forwarded-tcpip", originator_address);
+
+       xfree(originator_address);
+       xfree(listen_address);
+       return c;
+}
+
+static Channel *
+client_request_x11(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       char *originator;
+       u_short originator_port;
+       int sock;
+
+       if (!options.forward_x11) {
+               error("Warning: ssh server tried X11 forwarding.");
+               error("Warning: this is probably a break-in attempt by a "
+                   "malicious server.");
+               return NULL;
+       }
+       if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) {
+               verbose("Rejected X11 connection after ForwardX11Timeout "
+                   "expired");
+               return NULL;
+       }
+       originator = packet_get_string(NULL);
+       if (datafellows & SSH_BUG_X11FWD) {
+               debug2("buggy server: x11 request w/o originator_port");
+               originator_port = 0;
+       } else {
+               originator_port = packet_get_int();
+       }
+       packet_check_eom();
+       /* XXX check permission */
+       debug("client_request_x11: request from %s %d", originator,
+           originator_port);
+       xfree(originator);
+       sock = x11_connect_display();
+       if (sock < 0)
+               return NULL;
+       c = channel_new("x11",
+           SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+           CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
+       c->force_drain = 1;
+       return c;
+}
+
+static Channel *
+client_request_agent(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       int sock;
+
+       if (!options.forward_agent) {
+               error("Warning: ssh server tried agent forwarding.");
+               error("Warning: this is probably a break-in attempt by a "
+                   "malicious server.");
+               return NULL;
+       }
+       sock = ssh_get_authentication_socket();
+       if (sock < 0)
+               return NULL;
+       c = channel_new("authentication agent connection",
+           SSH_CHANNEL_OPEN, sock, sock, -1,
+           CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
+           "authentication agent connection", 1);
+       c->force_drain = 1;
+       return c;
+}
+
+int
+client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
+{
+       Channel *c;
+       int fd;
+
+       if (tun_mode == SSH_TUNMODE_NO)
+               return 0;
+
+       if (!compat20) {
+               error("Tunnel forwarding is not supported for protocol 1");
+               return -1;
+       }
+
+       debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
+
+       /* Open local tunnel device */
+       if ((fd = tun_open(local_tun, tun_mode)) == -1) {
+               error("Tunnel device open failed.");
+               return -1;
+       }
+
+       c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+           CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+       c->datagram = 1;
+
+#if defined(SSH_TUN_FILTER)
+       if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
+               channel_register_filter(c->self, sys_tun_infilter,
+                   sys_tun_outfilter, NULL, NULL);
+#endif
+
+       packet_start(SSH2_MSG_CHANNEL_OPEN);
+       packet_put_cstring("tun@openssh.com");
+       packet_put_int(c->self);
+       packet_put_int(c->local_window_max);
+       packet_put_int(c->local_maxpacket);
+       packet_put_int(tun_mode);
+       packet_put_int(remote_tun);
+       packet_send();
+
+       return 0;
+}
+
+/* XXXX move to generic input handler */
+static void
+client_input_channel_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       char *ctype;
+       int rchan;
+       u_int rmaxpack, rwindow, len;
+
+       ctype = packet_get_string(&len);
+       rchan = packet_get_int();
+       rwindow = packet_get_int();
+       rmaxpack = packet_get_int();
+
+       debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
+           ctype, rchan, rwindow, rmaxpack);
+
+       if (strcmp(ctype, "forwarded-tcpip") == 0) {
+               c = client_request_forwarded_tcpip(ctype, rchan);
+       } else if (strcmp(ctype, "x11") == 0) {
+               c = client_request_x11(ctype, rchan);
+       } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
+               c = client_request_agent(ctype, rchan);
+       }
+/* XXX duplicate : */
+       if (c != NULL) {
+               debug("confirm %s", ctype);
+               c->remote_id = rchan;
+               c->remote_window = rwindow;
+               c->remote_maxpacket = rmaxpack;
+               if (c->type != SSH_CHANNEL_CONNECTING) {
+                       packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
+                       packet_put_int(c->remote_id);
+                       packet_put_int(c->self);
+                       packet_put_int(c->local_window);
+                       packet_put_int(c->local_maxpacket);
+                       packet_send();
+               }
+       } else {
+               debug("failure %s", ctype);
+               packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(rchan);
+               packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
+               if (!(datafellows & SSH_BUG_OPENFAILURE)) {
+                       packet_put_cstring("open failed");
+                       packet_put_cstring("");
+               }
+               packet_send();
+       }
+       xfree(ctype);
+}
+static void
+client_input_channel_req(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       int exitval, id, reply, success = 0;
+       char *rtype;
+
+       id = packet_get_int();
+       rtype = packet_get_string(NULL);
+       reply = packet_get_char();
+
+       debug("client_input_channel_req: channel %d rtype %s reply %d",
+           id, rtype, reply);
+
+       if (id == -1) {
+               error("client_input_channel_req: request for channel -1");
+       } else if ((c = channel_lookup(id)) == NULL) {
+               error("client_input_channel_req: channel %d: "
+                   "unknown channel", id);
+       } else if (strcmp(rtype, "eow@openssh.com") == 0) {
+               packet_check_eom();
+               chan_rcvd_eow(c);
+       } else if (strcmp(rtype, "exit-status") == 0) {
+               exitval = packet_get_int();
+               if (c->ctl_chan != -1) {
+                       mux_exit_message(c, exitval);
+                       success = 1;
+               } else if (id == session_ident) {
+                       /* Record exit value of local session */
+                       success = 1;
+                       exit_status = exitval;
+               } else {
+                       /* Probably for a mux channel that has already closed */
+                       debug("%s: no sink for exit-status on channel %d",
+                           __func__, id);
+               }
+               packet_check_eom();
+       }
+       if (reply && c != NULL) {
+               packet_start(success ?
+                   SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
+               packet_put_int(c->remote_id);
+               packet_send();
+       }
+       xfree(rtype);
+}
+static void
+client_input_global_request(int type, u_int32_t seq, void *ctxt)
+{
+       char *rtype;
+       int want_reply;
+       int success = 0;
+
+       rtype = packet_get_string(NULL);
+       want_reply = packet_get_char();
+       debug("client_input_global_request: rtype %s want_reply %d",
+           rtype, want_reply);
+       if (want_reply) {
+               packet_start(success ?
+                   SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
+               packet_send();
+               packet_write_wait();
+       }
+       xfree(rtype);
+}
+
+void
+client_session2_setup(int id, int want_tty, int want_subsystem,
+    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
+{
+       int len;
+       Channel *c = NULL;
+
+       debug2("%s: id %d", __func__, id);
+
+       if ((c = channel_lookup(id)) == NULL)
+               fatal("client_session2_setup: channel %d: unknown channel", id);
+
+       packet_set_interactive(want_tty,
+           options.ip_qos_interactive, options.ip_qos_bulk);
+
+       if (want_tty) {
+               struct winsize ws;
+
+               /* Store window size in the packet. */
+               if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
+                       memset(&ws, 0, sizeof(ws));
+
+               channel_request_start(id, "pty-req", 1);
+               client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
+               packet_put_cstring(term != NULL ? term : "");
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+               if (tiop == NULL)
+                       tiop = get_saved_tio();
+               tty_make_modes(-1, tiop);
+               packet_send();
+               /* XXX wait for reply */
+               c->client_tty = 1;
+       }
+
+       /* Transfer any environment variables from client to server */
+       if (options.num_send_env != 0 && env != NULL) {
+               int i, j, matched;
+               char *name, *val;
+
+               debug("Sending environment.");
+               for (i = 0; env[i] != NULL; i++) {
+                       /* Split */
+                       name = xstrdup(env[i]);
+                       if ((val = strchr(name, '=')) == NULL) {
+                               xfree(name);
+                               continue;
+                       }
+                       *val++ = '\0';
+
+                       matched = 0;
+                       for (j = 0; j < options.num_send_env; j++) {
+                               if (match_pattern(name, options.send_env[j])) {
+                                       matched = 1;
+                                       break;
+                               }
+                       }
+                       if (!matched) {
+                               debug3("Ignored env %s", name);
+                               xfree(name);
+                               continue;
+                       }
+
+                       debug("Sending env %s = %s", name, val);
+                       channel_request_start(id, "env", 0);
+                       packet_put_cstring(name);
+                       packet_put_cstring(val);
+                       packet_send();
+                       xfree(name);
+               }
+       }
+
+       len = buffer_len(cmd);
+       if (len > 0) {
+               if (len > 900)
+                       len = 900;
+               if (want_subsystem) {
+                       debug("Sending subsystem: %.*s",
+                           len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "subsystem", 1);
+                       client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
+               } else {
+                       debug("Sending command: %.*s",
+                           len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "exec", 1);
+                       client_expect_confirm(id, "exec", CONFIRM_CLOSE);
+               }
+               packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
+               packet_send();
+       } else {
+               channel_request_start(id, "shell", 1);
+               client_expect_confirm(id, "shell", CONFIRM_CLOSE);
+               packet_send();
+       }
+}
+
+static void
+client_init_dispatch_20(void)
+{
+       dispatch_init(&dispatch_protocol_error);
+
+       dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+       dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+       dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
+       dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+       dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
+       dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
+       dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
+
+       /* rekeying */
+       dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+
+       /* global request reply messages */
+       dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
+       dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
+}
+
+static void
+client_init_dispatch_13(void)
+{
+       dispatch_init(NULL);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
+       dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
+       dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
+       dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
+
+       dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
+           &client_input_agent_open : &deny_input_open);
+       dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
+           &x11_input_open : &deny_input_open);
+}
+
+static void
+client_init_dispatch_15(void)
+{
+       client_init_dispatch_13();
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
+}
+
+static void
+client_init_dispatch(void)
+{
+       if (compat20)
+               client_init_dispatch_20();
+       else if (compat13)
+               client_init_dispatch_13();
+       else
+               client_init_dispatch_15();
+}
+
+void
+client_stop_mux(void)
+{
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+       /*
+        * If we are in persist mode, signal that we should close when all
+        * active channels are closed.
+        */
+       if (options.control_persist) {
+               session_closed = 1;
+               setproctitle("[stopped mux]");
+       }
+}
+
+/* client specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       leave_non_blocking();
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+       ssh_kill_proxy_command();
+       _exit(i);
+}
diff --git a/.pc/gssapi.patch/config.h.in b/.pc/gssapi.patch/config.h.in
new file mode 100644 (file)
index 0000000..baf0011
--- /dev/null
@@ -0,0 +1,1527 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address
+   */
+#undef AIX_GETNAMEINFO_HACK
+
+/* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */
+#undef AIX_LOGINFAILED_4ARG
+
+/* System only supports IPv4 audit records */
+#undef AU_IPv4
+
+/* Define if your resolver libs need this for getrrsetbyname */
+#undef BIND_8_COMPAT
+
+/* Define if cmsg_type is not passed correctly */
+#undef BROKEN_CMSG_TYPE
+
+/* getaddrinfo is broken (if present) */
+#undef BROKEN_GETADDRINFO
+
+/* getgroups(0,NULL) will return -1 */
+#undef BROKEN_GETGROUPS
+
+/* FreeBSD glob does not do what we need */
+#undef BROKEN_GLOB
+
+/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */
+#undef BROKEN_INET_NTOA
+
+/* ia_uinfo routines not supported by OS yet */
+#undef BROKEN_LIBIAF
+
+/* Ultrix mmap can't map files */
+#undef BROKEN_MMAP
+
+/* Define if your struct dirent expects you to allocate extra space for d_name
+   */
+#undef BROKEN_ONE_BYTE_DIRENT_D_NAME
+
+/* Can't do comparisons on readv */
+#undef BROKEN_READV_COMPARISON
+
+/* Define if you have a broken realpath. */
+#undef BROKEN_REALPATH
+
+/* Needed for NeXT */
+#undef BROKEN_SAVED_UIDS
+
+/* Define if your setregid() is broken */
+#undef BROKEN_SETREGID
+
+/* Define if your setresgid() is broken */
+#undef BROKEN_SETRESGID
+
+/* Define if your setresuid() is broken */
+#undef BROKEN_SETRESUID
+
+/* Define if your setreuid() is broken */
+#undef BROKEN_SETREUID
+
+/* LynxOS has broken setvbuf() implementation */
+#undef BROKEN_SETVBUF
+
+/* QNX shadow support is broken */
+#undef BROKEN_SHADOW_EXPIRE
+
+/* Define if your snprintf is busted */
+#undef BROKEN_SNPRINTF
+
+/* tcgetattr with ICANON may hang */
+#undef BROKEN_TCGETATTR_ICANON
+
+/* updwtmpx is broken (if present) */
+#undef BROKEN_UPDWTMPX
+
+/* Define if you have BSD auth support */
+#undef BSD_AUTH
+
+/* Define if you want to specify the path to your lastlog file */
+#undef CONF_LASTLOG_FILE
+
+/* Define if you want to specify the path to your utmp file */
+#undef CONF_UTMP_FILE
+
+/* Define if you want to specify the path to your wtmpx file */
+#undef CONF_WTMPX_FILE
+
+/* Define if you want to specify the path to your wtmp file */
+#undef CONF_WTMP_FILE
+
+/* Define if your platform needs to skip post auth file descriptor passing */
+#undef DISABLE_FD_PASSING
+
+/* Define if you don't want to use lastlog */
+#undef DISABLE_LASTLOG
+
+/* Define if you don't want to use your system's login() call */
+#undef DISABLE_LOGIN
+
+/* Define if you don't want to use pututline() etc. to write [uw]tmp */
+#undef DISABLE_PUTUTLINE
+
+/* Define if you don't want to use pututxline() etc. to write [uw]tmpx */
+#undef DISABLE_PUTUTXLINE
+
+/* Define if you want to disable shadow passwords */
+#undef DISABLE_SHADOW
+
+/* Define if you don't want to use utmp */
+#undef DISABLE_UTMP
+
+/* Define if you don't want to use utmpx */
+#undef DISABLE_UTMPX
+
+/* Define if you don't want to use wtmp */
+#undef DISABLE_WTMP
+
+/* Define if you don't want to use wtmpx */
+#undef DISABLE_WTMPX
+
+/* Enable for PKCS#11 support */
+#undef ENABLE_PKCS11
+
+/* File names may not contain backslash characters */
+#undef FILESYSTEM_NO_BACKSLASH
+
+/* fsid_t has member val */
+#undef FSID_HAS_VAL
+
+/* fsid_t has member __val */
+#undef FSID_HAS___VAL
+
+/* Define to 1 if the `getpgrp' function requires zero arguments. */
+#undef GETPGRP_VOID
+
+/* Conflicting defs for getspnam */
+#undef GETSPNAM_CONFLICTING_DEFS
+
+/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */
+#undef GLOB_HAS_ALTDIRFUNC
+
+/* Define if your system glob() function has gl_matchc options in glob_t */
+#undef GLOB_HAS_GL_MATCHC
+
+/* Define if your system glob() function has gl_statv options in glob_t */
+#undef GLOB_HAS_GL_STATV
+
+/* Define this if you want GSSAPI support in the version 2 protocol */
+#undef GSSAPI
+
+/* Define if you want to use shadow password expire field */
+#undef HAS_SHADOW_EXPIRE
+
+/* Define if your system uses access rights style file descriptor passing */
+#undef HAVE_ACCRIGHTS_IN_MSGHDR
+
+/* Define if you have ut_addr in utmp.h */
+#undef HAVE_ADDR_IN_UTMP
+
+/* Define if you have ut_addr in utmpx.h */
+#undef HAVE_ADDR_IN_UTMPX
+
+/* Define if you have ut_addr_v6 in utmp.h */
+#undef HAVE_ADDR_V6_IN_UTMP
+
+/* Define if you have ut_addr_v6 in utmpx.h */
+#undef HAVE_ADDR_V6_IN_UTMPX
+
+/* Define to 1 if you have the `arc4random' function. */
+#undef HAVE_ARC4RANDOM
+
+/* Define to 1 if you have the `arc4random_buf' function. */
+#undef HAVE_ARC4RANDOM_BUF
+
+/* Define to 1 if you have the `arc4random_uniform' function. */
+#undef HAVE_ARC4RANDOM_UNIFORM
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* OpenBSD's gcc has bounded */
+#undef HAVE_ATTRIBUTE__BOUNDED__
+
+/* Have attribute nonnull */
+#undef HAVE_ATTRIBUTE__NONNULL__
+
+/* OpenBSD's gcc has sentinel */
+#undef HAVE_ATTRIBUTE__SENTINEL__
+
+/* Define to 1 if you have the `aug_get_machine' function. */
+#undef HAVE_AUG_GET_MACHINE
+
+/* Define to 1 if you have the `b64_ntop' function. */
+#undef HAVE_B64_NTOP
+
+/* Define to 1 if you have the `b64_pton' function. */
+#undef HAVE_B64_PTON
+
+/* Define if you have the basename function. */
+#undef HAVE_BASENAME
+
+/* Define to 1 if you have the `bcopy' function. */
+#undef HAVE_BCOPY
+
+/* Define to 1 if you have the `bindresvport_sa' function. */
+#undef HAVE_BINDRESVPORT_SA
+
+/* Define to 1 if you have the `BN_is_prime_ex' function. */
+#undef HAVE_BN_IS_PRIME_EX
+
+/* Define to 1 if you have the <bsm/audit.h> header file. */
+#undef HAVE_BSM_AUDIT_H
+
+/* Define to 1 if you have the <bstring.h> header file. */
+#undef HAVE_BSTRING_H
+
+/* Define to 1 if you have the `clock' function. */
+#undef HAVE_CLOCK
+
+/* define if you have clock_t data type */
+#undef HAVE_CLOCK_T
+
+/* Define to 1 if you have the `closefrom' function. */
+#undef HAVE_CLOSEFROM
+
+/* Define if gai_strerror() returns const char * */
+#undef HAVE_CONST_GAI_STRERROR_PROTO
+
+/* Define if your system uses ancillary data style file descriptor passing */
+#undef HAVE_CONTROL_IN_MSGHDR
+
+/* Define to 1 if you have the <crypto/sha2.h> header file. */
+#undef HAVE_CRYPTO_SHA2_H
+
+/* Define to 1 if you have the <crypt.h> header file. */
+#undef HAVE_CRYPT_H
+
+/* Define if you are on Cygwin */
+#undef HAVE_CYGWIN
+
+/* Define if your libraries define daemon() */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the declaration of `authenticate', and to 0 if you
+   don't. */
+#undef HAVE_DECL_AUTHENTICATE
+
+/* Define to 1 if you have the declaration of `GLOB_NOMATCH', and to 0 if you
+   don't. */
+#undef HAVE_DECL_GLOB_NOMATCH
+
+/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
+   don't. */
+#undef HAVE_DECL_H_ERRNO
+
+/* Define to 1 if you have the declaration of `loginfailed', and to 0 if you
+   don't. */
+#undef HAVE_DECL_LOGINFAILED
+
+/* Define to 1 if you have the declaration of `loginrestrictions', and to 0 if
+   you don't. */
+#undef HAVE_DECL_LOGINRESTRICTIONS
+
+/* Define to 1 if you have the declaration of `loginsuccess', and to 0 if you
+   don't. */
+#undef HAVE_DECL_LOGINSUCCESS
+
+/* Define to 1 if you have the declaration of `MAXSYMLINKS', and to 0 if you
+   don't. */
+#undef HAVE_DECL_MAXSYMLINKS
+
+/* Define to 1 if you have the declaration of `offsetof', and to 0 if you
+   don't. */
+#undef HAVE_DECL_OFFSETOF
+
+/* Define to 1 if you have the declaration of `O_NONBLOCK', and to 0 if you
+   don't. */
+#undef HAVE_DECL_O_NONBLOCK
+
+/* Define to 1 if you have the declaration of `passwdexpired', and to 0 if you
+   don't. */
+#undef HAVE_DECL_PASSWDEXPIRED
+
+/* Define to 1 if you have the declaration of `setauthdb', and to 0 if you
+   don't. */
+#undef HAVE_DECL_SETAUTHDB
+
+/* Define to 1 if you have the declaration of `SHUT_RD', and to 0 if you
+   don't. */
+#undef HAVE_DECL_SHUT_RD
+
+/* Define to 1 if you have the declaration of `writev', and to 0 if you don't.
+   */
+#undef HAVE_DECL_WRITEV
+
+/* Define to 1 if you have the declaration of `_getlong', and to 0 if you
+   don't. */
+#undef HAVE_DECL__GETLONG
+
+/* Define to 1 if you have the declaration of `_getshort', and to 0 if you
+   don't. */
+#undef HAVE_DECL__GETSHORT
+
+/* Define if you have /dev/ptmx */
+#undef HAVE_DEV_PTMX
+
+/* Define if you have /dev/ptc */
+#undef HAVE_DEV_PTS_AND_PTC
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the `dirfd' function. */
+#undef HAVE_DIRFD
+
+/* Define to 1 if you have the `dirname' function. */
+#undef HAVE_DIRNAME
+
+/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */
+#undef HAVE_DSA_GENERATE_PARAMETERS_EX
+
+/* Define to 1 if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define to 1 if you have the `endutent' function. */
+#undef HAVE_ENDUTENT
+
+/* Define to 1 if you have the `endutxent' function. */
+#undef HAVE_ENDUTXENT
+
+/* Define if your system has /etc/default/login */
+#undef HAVE_ETC_DEFAULT_LOGIN
+
+/* Define to 1 if you have the `EVP_sha256' function. */
+#undef HAVE_EVP_SHA256
+
+/* Define if you have ut_exit in utmp.h */
+#undef HAVE_EXIT_IN_UTMP
+
+/* Define to 1 if you have the `fchmod' function. */
+#undef HAVE_FCHMOD
+
+/* Define to 1 if you have the `fchown' function. */
+#undef HAVE_FCHOWN
+
+/* Use F_CLOSEM fcntl for closefrom */
+#undef HAVE_FCNTL_CLOSEM
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <features.h> header file. */
+#undef HAVE_FEATURES_H
+
+/* Define to 1 if you have the <floatingpoint.h> header file. */
+#undef HAVE_FLOATINGPOINT_H
+
+/* Define to 1 if you have the `fmt_scaled' function. */
+#undef HAVE_FMT_SCALED
+
+/* Define to 1 if you have the `freeaddrinfo' function. */
+#undef HAVE_FREEADDRINFO
+
+/* Define to 1 if the system has the type `fsblkcnt_t'. */
+#undef HAVE_FSBLKCNT_T
+
+/* Define to 1 if the system has the type `fsfilcnt_t'. */
+#undef HAVE_FSFILCNT_T
+
+/* Define to 1 if you have the `fstatvfs' function. */
+#undef HAVE_FSTATVFS
+
+/* Define to 1 if you have the `futimes' function. */
+#undef HAVE_FUTIMES
+
+/* Define to 1 if you have the `gai_strerror' function. */
+#undef HAVE_GAI_STRERROR
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getaudit' function. */
+#undef HAVE_GETAUDIT
+
+/* Define to 1 if you have the `getaudit_addr' function. */
+#undef HAVE_GETAUDIT_ADDR
+
+/* Define to 1 if you have the `getcwd' function. */
+#undef HAVE_GETCWD
+
+/* Define to 1 if you have the `getgrouplist' function. */
+#undef HAVE_GETGROUPLIST
+
+/* Define to 1 if you have the `getgrset' function. */
+#undef HAVE_GETGRSET
+
+/* Define to 1 if you have the `getlastlogxbyname' function. */
+#undef HAVE_GETLASTLOGXBYNAME
+
+/* Define to 1 if you have the `getluid' function. */
+#undef HAVE_GETLUID
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if you have the `getopt' function. */
+#undef HAVE_GETOPT
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define if your getopt(3) defines and uses optreset */
+#undef HAVE_GETOPT_OPTRESET
+
+/* Define if your libraries define getpagesize() */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the `getpeereid' function. */
+#undef HAVE_GETPEEREID
+
+/* Define to 1 if you have the `getpeerucred' function. */
+#undef HAVE_GETPEERUCRED
+
+/* Define to 1 if you have the `getpwanam' function. */
+#undef HAVE_GETPWANAM
+
+/* Define to 1 if you have the `getrlimit' function. */
+#undef HAVE_GETRLIMIT
+
+/* Define if getrrsetbyname() exists */
+#undef HAVE_GETRRSETBYNAME
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define to 1 if you have the `getseuserbyname' function. */
+#undef HAVE_GETSEUSERBYNAME
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `getttyent' function. */
+#undef HAVE_GETTTYENT
+
+/* Define to 1 if you have the `getutent' function. */
+#undef HAVE_GETUTENT
+
+/* Define to 1 if you have the `getutid' function. */
+#undef HAVE_GETUTID
+
+/* Define to 1 if you have the `getutline' function. */
+#undef HAVE_GETUTLINE
+
+/* Define to 1 if you have the `getutxent' function. */
+#undef HAVE_GETUTXENT
+
+/* Define to 1 if you have the `getutxid' function. */
+#undef HAVE_GETUTXID
+
+/* Define to 1 if you have the `getutxline' function. */
+#undef HAVE_GETUTXLINE
+
+/* Define to 1 if you have the `getutxuser' function. */
+#undef HAVE_GETUTXUSER
+
+/* Define to 1 if you have the `get_default_context_with_level' function. */
+#undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+
+/* Define to 1 if you have the `glob' function. */
+#undef HAVE_GLOB
+
+/* Define to 1 if you have the <glob.h> header file. */
+#undef HAVE_GLOB_H
+
+/* Define to 1 if you have the `group_from_gid' function. */
+#undef HAVE_GROUP_FROM_GID
+
+/* Define to 1 if you have the <gssapi_generic.h> header file. */
+#undef HAVE_GSSAPI_GENERIC_H
+
+/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_KRB5_H
+
+/* Define to 1 if you have the <gssapi.h> header file. */
+#undef HAVE_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi_krb5.h> header file. */
+#undef HAVE_GSSAPI_KRB5_H
+
+/* Define if HEADER.ad exists in arpa/nameser.h */
+#undef HAVE_HEADER_AD
+
+/* Define if you have ut_host in utmp.h */
+#undef HAVE_HOST_IN_UTMP
+
+/* Define if you have ut_host in utmpx.h */
+#undef HAVE_HOST_IN_UTMPX
+
+/* Define to 1 if you have the <iaf.h> header file. */
+#undef HAVE_IAF_H
+
+/* Define to 1 if you have the <ia.h> header file. */
+#undef HAVE_IA_H
+
+/* Define if you have ut_id in utmp.h */
+#undef HAVE_ID_IN_UTMP
+
+/* Define if you have ut_id in utmpx.h */
+#undef HAVE_ID_IN_UTMPX
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#undef HAVE_INET_NTOA
+
+/* Define to 1 if you have the `inet_ntop' function. */
+#undef HAVE_INET_NTOP
+
+/* Define to 1 if you have the `innetgr' function. */
+#undef HAVE_INNETGR
+
+/* define if you have int64_t data type */
+#undef HAVE_INT64_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* define if you have intxx_t data type */
+#undef HAVE_INTXX_T
+
+/* Define to 1 if the system has the type `in_addr_t'. */
+#undef HAVE_IN_ADDR_T
+
+/* Define to 1 if the system has the type `in_port_t'. */
+#undef HAVE_IN_PORT_T
+
+/* Define if you have isblank(3C). */
+#undef HAVE_ISBLANK
+
+/* Define to 1 if you have the <lastlog.h> header file. */
+#undef HAVE_LASTLOG_H
+
+/* Define to 1 if you have the <libaudit.h> header file. */
+#undef HAVE_LIBAUDIT_H
+
+/* Define to 1 if you have the `bsm' library (-lbsm). */
+#undef HAVE_LIBBSM
+
+/* Define to 1 if you have the `crypt' library (-lcrypt). */
+#undef HAVE_LIBCRYPT
+
+/* Define to 1 if you have the `dl' library (-ldl). */
+#undef HAVE_LIBDL
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define if system has libiaf that supports set_id */
+#undef HAVE_LIBIAF
+
+/* Define to 1 if you have the `network' library (-lnetwork). */
+#undef HAVE_LIBNETWORK
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `pam' library (-lpam). */
+#undef HAVE_LIBPAM
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the <libutil.h> header file. */
+#undef HAVE_LIBUTIL_H
+
+/* Define to 1 if you have the `xnet' library (-lxnet). */
+#undef HAVE_LIBXNET
+
+/* Define to 1 if you have the `z' library (-lz). */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <linux/if_tun.h> header file. */
+#undef HAVE_LINUX_IF_TUN_H
+
+/* Define if your libraries define login() */
+#undef HAVE_LOGIN
+
+/* Define to 1 if you have the <login_cap.h> header file. */
+#undef HAVE_LOGIN_CAP_H
+
+/* Define to 1 if you have the `login_getcapbool' function. */
+#undef HAVE_LOGIN_GETCAPBOOL
+
+/* Define to 1 if you have the <login.h> header file. */
+#undef HAVE_LOGIN_H
+
+/* Define to 1 if you have the `logout' function. */
+#undef HAVE_LOGOUT
+
+/* Define to 1 if you have the `logwtmp' function. */
+#undef HAVE_LOGWTMP
+
+/* Define to 1 if the system has the type `long double'. */
+#undef HAVE_LONG_DOUBLE
+
+/* Define to 1 if the system has the type `long long'. */
+#undef HAVE_LONG_LONG
+
+/* Define to 1 if you have the <maillock.h> header file. */
+#undef HAVE_MAILLOCK_H
+
+/* Define to 1 if you have the `md5_crypt' function. */
+#undef HAVE_MD5_CRYPT
+
+/* Define if you want to allow MD5 passwords */
+#undef HAVE_MD5_PASSWORDS
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mkdtemp' function. */
+#undef HAVE_MKDTEMP
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* define if you have mode_t data type */
+#undef HAVE_MODE_T
+
+/* Some systems put nanosleep outside of libc */
+#undef HAVE_NANOSLEEP
+
+/* Define to 1 if you have the <ndir.h> header file. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netgroup.h> header file. */
+#undef HAVE_NETGROUP_H
+
+/* Define to 1 if you have the <net/if_tun.h> header file. */
+#undef HAVE_NET_IF_TUN_H
+
+/* Define if you are on NeXT */
+#undef HAVE_NEXT
+
+/* Define to 1 if you have the `ngetaddrinfo' function. */
+#undef HAVE_NGETADDRINFO
+
+/* Define to 1 if you have the `nsleep' function. */
+#undef HAVE_NSLEEP
+
+/* Define to 1 if you have the `ogetaddrinfo' function. */
+#undef HAVE_OGETADDRINFO
+
+/* Define if you have an old version of PAM which takes only one argument to
+   pam_strerror */
+#undef HAVE_OLD_PAM
+
+/* Define to 1 if you have the `openlog_r' function. */
+#undef HAVE_OPENLOG_R
+
+/* Define to 1 if you have the `openpty' function. */
+#undef HAVE_OPENPTY
+
+/* Define if your ssl headers are included with #include <openssl/header.h> */
+#undef HAVE_OPENSSL
+
+/* Define if you have Digital Unix Security Integration Architecture */
+#undef HAVE_OSF_SIA
+
+/* Define to 1 if you have the `pam_getenvlist' function. */
+#undef HAVE_PAM_GETENVLIST
+
+/* Define to 1 if you have the <pam/pam_appl.h> header file. */
+#undef HAVE_PAM_PAM_APPL_H
+
+/* Define to 1 if you have the `pam_putenv' function. */
+#undef HAVE_PAM_PUTENV
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define if you have ut_pid in utmp.h */
+#undef HAVE_PID_IN_UTMP
+
+/* define if you have pid_t data type */
+#undef HAVE_PID_T
+
+/* Define to 1 if you have the `poll' function. */
+#undef HAVE_POLL
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define to 1 if you have the `prctl' function. */
+#undef HAVE_PRCTL
+
+/* Define if you have /proc/$pid/fd */
+#undef HAVE_PROC_PID
+
+/* Define to 1 if you have the `pstat' function. */
+#undef HAVE_PSTAT
+
+/* Define to 1 if you have the <pty.h> header file. */
+#undef HAVE_PTY_H
+
+/* Define to 1 if you have the `pututline' function. */
+#undef HAVE_PUTUTLINE
+
+/* Define to 1 if you have the `pututxline' function. */
+#undef HAVE_PUTUTXLINE
+
+/* Define if your password has a pw_change field */
+#undef HAVE_PW_CHANGE_IN_PASSWD
+
+/* Define if your password has a pw_class field */
+#undef HAVE_PW_CLASS_IN_PASSWD
+
+/* Define if your password has a pw_expire field */
+#undef HAVE_PW_EXPIRE_IN_PASSWD
+
+/* Define to 1 if you have the `readpassphrase' function. */
+#undef HAVE_READPASSPHRASE
+
+/* Define to 1 if you have the <readpassphrase.h> header file. */
+#undef HAVE_READPASSPHRASE_H
+
+/* Define to 1 if you have the `realpath' function. */
+#undef HAVE_REALPATH
+
+/* Define to 1 if you have the `recvmsg' function. */
+#undef HAVE_RECVMSG
+
+/* sys/resource.h has RLIMIT_NPROC */
+#undef HAVE_RLIMIT_NPROC
+
+/* Define to 1 if you have the <rpc/types.h> header file. */
+#undef HAVE_RPC_TYPES_H
+
+/* Define to 1 if you have the `rresvport_af' function. */
+#undef HAVE_RRESVPORT_AF
+
+/* Define to 1 if you have the `RSA_generate_key_ex' function. */
+#undef HAVE_RSA_GENERATE_KEY_EX
+
+/* Define to 1 if you have the `RSA_get_default_method' function. */
+#undef HAVE_RSA_GET_DEFAULT_METHOD
+
+/* Define to 1 if you have the <sandbox.h> header file. */
+#undef HAVE_SANDBOX_H
+
+/* Define to 1 if you have the `sandbox_init' function. */
+#undef HAVE_SANDBOX_INIT
+
+/* define if you have sa_family_t data type */
+#undef HAVE_SA_FAMILY_T
+
+/* Define if you have SecureWare-based protected password database */
+#undef HAVE_SECUREWARE
+
+/* Define to 1 if you have the <security/pam_appl.h> header file. */
+#undef HAVE_SECURITY_PAM_APPL_H
+
+/* Define to 1 if you have the `sendmsg' function. */
+#undef HAVE_SENDMSG
+
+/* Define to 1 if you have the `setauthdb' function. */
+#undef HAVE_SETAUTHDB
+
+/* Define to 1 if you have the `setdtablesize' function. */
+#undef HAVE_SETDTABLESIZE
+
+/* Define to 1 if you have the `setegid' function. */
+#undef HAVE_SETEGID
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `seteuid' function. */
+#undef HAVE_SETEUID
+
+/* Define to 1 if you have the `setgroupent' function. */
+#undef HAVE_SETGROUPENT
+
+/* Define to 1 if you have the `setgroups' function. */
+#undef HAVE_SETGROUPS
+
+/* Define to 1 if you have the `setlogin' function. */
+#undef HAVE_SETLOGIN
+
+/* Define to 1 if you have the `setluid' function. */
+#undef HAVE_SETLUID
+
+/* Define to 1 if you have the `setpassent' function. */
+#undef HAVE_SETPASSENT
+
+/* Define to 1 if you have the `setpcred' function. */
+#undef HAVE_SETPCRED
+
+/* Define to 1 if you have the `setproctitle' function. */
+#undef HAVE_SETPROCTITLE
+
+/* Define to 1 if you have the `setregid' function. */
+#undef HAVE_SETREGID
+
+/* Define to 1 if you have the `setresgid' function. */
+#undef HAVE_SETRESGID
+
+/* Define to 1 if you have the `setresuid' function. */
+#undef HAVE_SETRESUID
+
+/* Define to 1 if you have the `setreuid' function. */
+#undef HAVE_SETREUID
+
+/* Define to 1 if you have the `setrlimit' function. */
+#undef HAVE_SETRLIMIT
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `setutent' function. */
+#undef HAVE_SETUTENT
+
+/* Define to 1 if you have the `setutxdb' function. */
+#undef HAVE_SETUTXDB
+
+/* Define to 1 if you have the `setutxent' function. */
+#undef HAVE_SETUTXENT
+
+/* Define to 1 if you have the `setvbuf' function. */
+#undef HAVE_SETVBUF
+
+/* Define to 1 if you have the `set_id' function. */
+#undef HAVE_SET_ID
+
+/* Define to 1 if you have the `SHA256_Update' function. */
+#undef HAVE_SHA256_UPDATE
+
+/* Define to 1 if you have the <sha2.h> header file. */
+#undef HAVE_SHA2_H
+
+/* Define to 1 if you have the <shadow.h> header file. */
+#undef HAVE_SHADOW_H
+
+/* Define to 1 if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
+/* Define to 1 if you have the `sigvec' function. */
+#undef HAVE_SIGVEC
+
+/* Define to 1 if the system has the type `sig_atomic_t'. */
+#undef HAVE_SIG_ATOMIC_T
+
+/* define if you have size_t data type */
+#undef HAVE_SIZE_T
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the `socketpair' function. */
+#undef HAVE_SOCKETPAIR
+
+/* Have PEERCRED socket option */
+#undef HAVE_SO_PEERCRED
+
+/* define if you have ssize_t data type */
+#undef HAVE_SSIZE_T
+
+/* Fields in struct sockaddr_storage */
+#undef HAVE_SS_FAMILY_IN_SS
+
+/* Define to 1 if you have the `statfs' function. */
+#undef HAVE_STATFS
+
+/* Define to 1 if you have the `statvfs' function. */
+#undef HAVE_STATVFS
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Silly mkstemp() */
+#undef HAVE_STRICT_MKSTEMP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strmode' function. */
+#undef HAVE_STRMODE
+
+/* Define to 1 if you have the `strnvis' function. */
+#undef HAVE_STRNVIS
+
+/* Define to 1 if you have the `strptime' function. */
+#undef HAVE_STRPTIME
+
+/* Define to 1 if you have the `strsep' function. */
+#undef HAVE_STRSEP
+
+/* Define to 1 if you have the `strtoll' function. */
+#undef HAVE_STRTOLL
+
+/* Define to 1 if you have the `strtonum' function. */
+#undef HAVE_STRTONUM
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* define if you have struct addrinfo data type */
+#undef HAVE_STRUCT_ADDRINFO
+
+/* define if you have struct in6_addr data type */
+#undef HAVE_STRUCT_IN6_ADDR
+
+/* define if you have struct sockaddr_in6 data type */
+#undef HAVE_STRUCT_SOCKADDR_IN6
+
+/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */
+#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
+
+/* define if you have struct sockaddr_storage data type */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
+/* Define to 1 if the system has the type `struct timespec'. */
+#undef HAVE_STRUCT_TIMESPEC
+
+/* define if you have struct timeval */
+#undef HAVE_STRUCT_TIMEVAL
+
+/* Define to 1 if you have the `swap32' function. */
+#undef HAVE_SWAP32
+
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
+/* Define if you have syslen in utmpx.h */
+#undef HAVE_SYSLEN_IN_UTMPX
+
+/* Define to 1 if you have the <sys/audit.h> header file. */
+#undef HAVE_SYS_AUDIT_H
+
+/* Define to 1 if you have the <sys/bitypes.h> header file. */
+#undef HAVE_SYS_BITYPES_H
+
+/* Define to 1 if you have the <sys/bsdtty.h> header file. */
+#undef HAVE_SYS_BSDTTY_H
+
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#undef HAVE_SYS_CDEFS_H
+
+/* Define to 1 if you have the <sys/dir.h> header file. */
+#undef HAVE_SYS_DIR_H
+
+/* Define if your system defines sys_errlist[] */
+#undef HAVE_SYS_ERRLIST
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file. */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if your system defines sys_nerr */
+#undef HAVE_SYS_NERR
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#undef HAVE_SYS_POLL_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/pstat.h> header file. */
+#undef HAVE_SYS_PSTAT_H
+
+/* Define to 1 if you have the <sys/ptms.h> header file. */
+#undef HAVE_SYS_PTMS_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#undef HAVE_SYS_STATVFS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/stream.h> header file. */
+#undef HAVE_SYS_STREAM_H
+
+/* Define to 1 if you have the <sys/stropts.h> header file. */
+#undef HAVE_SYS_STROPTS_H
+
+/* Define to 1 if you have the <sys/strtio.h> header file. */
+#undef HAVE_SYS_STRTIO_H
+
+/* Force use of sys/syslog.h on Ultrix */
+#undef HAVE_SYS_SYSLOG_H
+
+/* Define to 1 if you have the <sys/sysmacros.h> header file. */
+#undef HAVE_SYS_SYSMACROS_H
+
+/* Define to 1 if you have the <sys/timers.h> header file. */
+#undef HAVE_SYS_TIMERS_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the `tcgetpgrp' function. */
+#undef HAVE_TCGETPGRP
+
+/* Define to 1 if you have the `tcsendbreak' function. */
+#undef HAVE_TCSENDBREAK
+
+/* Define to 1 if you have the `time' function. */
+#undef HAVE_TIME
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define if you have ut_time in utmp.h */
+#undef HAVE_TIME_IN_UTMP
+
+/* Define if you have ut_time in utmpx.h */
+#undef HAVE_TIME_IN_UTMPX
+
+/* Define to 1 if you have the `timingsafe_bcmp' function. */
+#undef HAVE_TIMINGSAFE_BCMP
+
+/* Define to 1 if you have the <tmpdir.h> header file. */
+#undef HAVE_TMPDIR_H
+
+/* Define to 1 if you have the `truncate' function. */
+#undef HAVE_TRUNCATE
+
+/* Define to 1 if you have the <ttyent.h> header file. */
+#undef HAVE_TTYENT_H
+
+/* Define if you have ut_tv in utmp.h */
+#undef HAVE_TV_IN_UTMP
+
+/* Define if you have ut_tv in utmpx.h */
+#undef HAVE_TV_IN_UTMPX
+
+/* Define if you have ut_type in utmp.h */
+#undef HAVE_TYPE_IN_UTMP
+
+/* Define if you have ut_type in utmpx.h */
+#undef HAVE_TYPE_IN_UTMPX
+
+/* Define to 1 if you have the <ucred.h> header file. */
+#undef HAVE_UCRED_H
+
+/* define if you have uintxx_t data type */
+#undef HAVE_UINTXX_T
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unsetenv' function. */
+#undef HAVE_UNSETENV
+
+/* Define to 1 if the system has the type `unsigned long long'. */
+#undef HAVE_UNSIGNED_LONG_LONG
+
+/* Define to 1 if you have the `updwtmp' function. */
+#undef HAVE_UPDWTMP
+
+/* Define to 1 if you have the `updwtmpx' function. */
+#undef HAVE_UPDWTMPX
+
+/* Define to 1 if you have the <usersec.h> header file. */
+#undef HAVE_USERSEC_H
+
+/* Define to 1 if you have the `user_from_uid' function. */
+#undef HAVE_USER_FROM_UID
+
+/* Define to 1 if you have the <util.h> header file. */
+#undef HAVE_UTIL_H
+
+/* Define to 1 if you have the `utimes' function. */
+#undef HAVE_UTIMES
+
+/* Define to 1 if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
+/* Define to 1 if you have the `utmpname' function. */
+#undef HAVE_UTMPNAME
+
+/* Define to 1 if you have the `utmpxname' function. */
+#undef HAVE_UTMPXNAME
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
+
+/* Define to 1 if you have the <utmp.h> header file. */
+#undef HAVE_UTMP_H
+
+/* define if you have u_char data type */
+#undef HAVE_U_CHAR
+
+/* define if you have u_int data type */
+#undef HAVE_U_INT
+
+/* define if you have u_int64_t data type */
+#undef HAVE_U_INT64_T
+
+/* define if you have u_intxx_t data type */
+#undef HAVE_U_INTXX_T
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define if va_copy exists */
+#undef HAVE_VA_COPY
+
+/* Define to 1 if you have the `vhangup' function. */
+#undef HAVE_VHANGUP
+
+/* Define to 1 if you have the <vis.h> header file. */
+#undef HAVE_VIS_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if you have the `waitpid' function. */
+#undef HAVE_WAITPID
+
+/* Define to 1 if you have the `_getlong' function. */
+#undef HAVE__GETLONG
+
+/* Define to 1 if you have the `_getpty' function. */
+#undef HAVE__GETPTY
+
+/* Define to 1 if you have the `_getshort' function. */
+#undef HAVE__GETSHORT
+
+/* Define if you have struct __res_state _res as an extern */
+#undef HAVE__RES_EXTERN
+
+/* Define to 1 if you have the `__b64_ntop' function. */
+#undef HAVE___B64_NTOP
+
+/* Define to 1 if you have the `__b64_pton' function. */
+#undef HAVE___B64_PTON
+
+/* Define if compiler implements __FUNCTION__ */
+#undef HAVE___FUNCTION__
+
+/* Define if libc defines __progname */
+#undef HAVE___PROGNAME
+
+/* Fields in struct sockaddr_storage */
+#undef HAVE___SS_FAMILY_IN_SS
+
+/* Define if __va_copy exists */
+#undef HAVE___VA_COPY
+
+/* Define if compiler implements __func__ */
+#undef HAVE___func__
+
+/* Define this if you are using the Heimdal version of Kerberos V5 */
+#undef HEIMDAL
+
+/* Define if you need to use IP address instead of hostname in $DISPLAY */
+#undef IPADDR_IN_DISPLAY
+
+/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
+#undef IPV4_IN_IPV6
+
+/* Define if your system choked on IP TOS setting */
+#undef IP_TOS_IS_BROKEN
+
+/* Define if you want Kerberos 5 support */
+#undef KRB5
+
+/* Define if pututxline updates lastlog too */
+#undef LASTLOG_WRITE_PUTUTXLINE
+
+/* Define if you want TCP Wrappers support */
+#undef LIBWRAP
+
+/* Define to whatever link() returns for "not supported" if it doesn't return
+   EOPNOTSUPP. */
+#undef LINK_OPNOTSUPP_ERRNO
+
+/* Adjust Linux out-of-memory killer */
+#undef LINUX_OOM_ADJUST
+
+/* max value of long long calculated by configure */
+#undef LLONG_MAX
+
+/* min value of long long calculated by configure */
+#undef LLONG_MIN
+
+/* Account locked with pw(1) */
+#undef LOCKED_PASSWD_PREFIX
+
+/* String used in /etc/passwd to denote locked account */
+#undef LOCKED_PASSWD_STRING
+
+/* String used in /etc/passwd to denote locked account */
+#undef LOCKED_PASSWD_SUBSTR
+
+/* Some versions of /bin/login need the TERM supplied on the commandline */
+#undef LOGIN_NEEDS_TERM
+
+/* Some systems need a utmpx entry for /bin/login to work */
+#undef LOGIN_NEEDS_UTMPX
+
+/* Define if your login program cannot handle end of options ("--") */
+#undef LOGIN_NO_ENDOPT
+
+/* If your header files don't define LOGIN_PROGRAM, then use this (detected)
+   from environment and PATH */
+#undef LOGIN_PROGRAM_FALLBACK
+
+/* Set this to your mail directory if you do not have _PATH_MAILDIR */
+#undef MAIL_DIRECTORY
+
+/* Define on *nto-qnx systems */
+#undef MISSING_FD_MASK
+
+/* Define on *nto-qnx systems */
+#undef MISSING_HOWMANY
+
+/* Define on *nto-qnx systems */
+#undef MISSING_NFDBITS
+
+/* Need setpgrp to acquire controlling tty */
+#undef NEED_SETPGRP
+
+/* Define if the concept of ports only accessible to superusers isn't known */
+#undef NO_IPPORT_RESERVED_CONCEPT
+
+/* Define if you don't want to use lastlog in session.c */
+#undef NO_SSH_LASTLOG
+
+/* Define if X11 doesn't support AF_UNIX sockets on that system */
+#undef NO_X11_UNIX_SOCKETS
+
+/* Define if EVP_DigestUpdate returns void */
+#undef OPENSSL_EVP_DIGESTUPDATE_VOID
+
+/* libcrypto includes complete ECC support */
+#undef OPENSSL_HAS_ECC
+
+/* libcrypto is missing AES 192 and 256 bit functions */
+#undef OPENSSL_LOBOTOMISED_AES
+
+/* Define if you want OpenSSL's internally seeded PRNG only */
+#undef OPENSSL_PRNG_ONLY
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define if you are using Solaris-derived PAM which passes pam_messages to
+   the conversation function with an extra level of indirection */
+#undef PAM_SUN_CODEBASE
+
+/* Work around problematic Linux PAM modules handling of PAM_TTY */
+#undef PAM_TTY_KLUDGE
+
+/* must supply username to passwd */
+#undef PASSWD_NEEDS_USERNAME
+
+/* Port number of PRNGD/EGD random number socket */
+#undef PRNGD_PORT
+
+/* Location of PRNGD/EGD random number socket */
+#undef PRNGD_SOCKET
+
+/* read(1) can return 0 for a non-closed fd */
+#undef PTY_ZEROREAD
+
+/* Sandbox using Darwin sandbox_init(3) */
+#undef SANDBOX_DARWIN
+
+/* no privsep sandboxing */
+#undef SANDBOX_NULL
+
+/* Sandbox using setrlimit(2) */
+#undef SANDBOX_RLIMIT
+
+/* Sandbox using systrace(4) */
+#undef SANDBOX_SYSTRACE
+
+/* Define if your platform breaks doing a seteuid before a setuid */
+#undef SETEUID_BREAKS_SETUID
+
+/* The size of `char', as computed by sizeof. */
+#undef SIZEOF_CHAR
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long int', as computed by sizeof. */
+#undef SIZEOF_LONG_INT
+
+/* The size of `long long int', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG_INT
+
+/* The size of `short int', as computed by sizeof. */
+#undef SIZEOF_SHORT_INT
+
+/* Define if you want S/Key support */
+#undef SKEY
+
+/* Define if your skeychallenge() function takes 4 arguments (NetBSD) */
+#undef SKEYCHALLENGE_4ARG
+
+/* Define as const if snprintf() can declare const char *fmt */
+#undef SNPRINTF_CONST
+
+/* Define to a Set Process Title type if your system is supported by
+   bsd-setproctitle.c */
+#undef SPT_TYPE
+
+/* Define if sshd somehow reacquires a controlling TTY after setsid() */
+#undef SSHD_ACQUIRES_CTTY
+
+/* Define if pam_chauthtok wants real uid set to the unpriv'ed user */
+#undef SSHPAM_CHAUTHTOK_NEEDS_RUID
+
+/* Use audit debugging module */
+#undef SSH_AUDIT_EVENTS
+
+/* Windows is sensitive to read buffer size */
+#undef SSH_IOBUFSZ
+
+/* non-privileged user for privilege separation */
+#undef SSH_PRIVSEP_USER
+
+/* Use tunnel device compatibility to OpenBSD */
+#undef SSH_TUN_COMPAT_AF
+
+/* Open tunnel devices the FreeBSD way */
+#undef SSH_TUN_FREEBSD
+
+/* Open tunnel devices the Linux tun/tap way */
+#undef SSH_TUN_LINUX
+
+/* No layer 2 tunnel support */
+#undef SSH_TUN_NO_L2
+
+/* Open tunnel devices the OpenBSD way */
+#undef SSH_TUN_OPENBSD
+
+/* Prepend the address family to IP tunnel traffic */
+#undef SSH_TUN_PREPEND_AF
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you want a different $PATH for the superuser */
+#undef SUPERUSER_PATH
+
+/* syslog_r function is safe to use in in a signal handler */
+#undef SYSLOG_R_SAFE_IN_SIGHAND
+
+/* Support passwords > 8 chars */
+#undef UNIXWARE_LONG_PASSWORDS
+
+/* Specify default $PATH */
+#undef USER_PATH
+
+/* Define this if you want to use libkafs' AFS support */
+#undef USE_AFS
+
+/* Use BSM audit module */
+#undef USE_BSM_AUDIT
+
+/* Use btmp to log bad logins */
+#undef USE_BTMP
+
+/* Use libedit for sftp */
+#undef USE_LIBEDIT
+
+/* Use Linux audit module */
+#undef USE_LINUX_AUDIT
+
+/* Enable OpenSSL engine support */
+#undef USE_OPENSSL_ENGINE
+
+/* Define if you want to enable PAM support */
+#undef USE_PAM
+
+/* Use PIPES instead of a socketpair() */
+#undef USE_PIPES
+
+/* Define if you have Solaris process contracts */
+#undef USE_SOLARIS_PROCESS_CONTRACTS
+
+/* Define if you have Solaris projects */
+#undef USE_SOLARIS_PROJECTS
+
+/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */
+#undef WITH_ABBREV_NO_TTY
+
+/* Define if you want to enable AIX4's authenticate function */
+#undef WITH_AIXAUTHENTICATE
+
+/* Define if you have/want arrays (cluster-wide session managment, not C
+   arrays) */
+#undef WITH_IRIX_ARRAY
+
+/* Define if you want IRIX audit trails */
+#undef WITH_IRIX_AUDIT
+
+/* Define if you want IRIX kernel jobs */
+#undef WITH_IRIX_JOBS
+
+/* Define if you want IRIX project management */
+#undef WITH_IRIX_PROJECT
+
+/* Define if you want SELinux support. */
+#undef WITH_SELINUX
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+#  undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Define if xauth is found in your path */
+#undef XAUTH_PATH
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* log for bad login attempts */
+#undef _PATH_BTMP
+
+/* Full path of your "passwd" program */
+#undef _PATH_PASSWD_PROG
+
+/* Specify location of ssh.pid */
+#undef _PATH_SSH_PIDDIR
+
+/* Define if we don't have struct __res_state in resolv.h */
+#undef __res_state
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* type to use in place of socklen_t if not defined */
+#undef socklen_t
diff --git a/.pc/gssapi.patch/configure b/.pc/gssapi.patch/configure
new file mode 100755 (executable)
index 0000000..43c4372
--- /dev/null
@@ -0,0 +1,17535 @@
+#! /bin/sh
+# From configure.ac Revision: 1.480 .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68 for OpenSSH Portable.
+#
+# Report bugs to <openssh-unix-dev@mindrot.org>.
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+        /*)
+          for as_base in sh bash ksh sh5; do
+            # Try only shells that exist, to save several forks.
+            as_shell=$as_dir/$as_base
+            if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+                   { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+                  if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+          done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+             { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  # We cannot yet assume a decent shell, so we have to provide a
+       # neutralization value for shells without unset; and this also
+       # works around shells that cannot unset nonexistent variables.
+       # Preserve -v and -x to the replacement shell.
+       BASH_ENV=/dev/null
+       ENV=/dev/null
+       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+       export CONFIG_SHELL
+       case $- in # ((((
+         *v*x* | *x*v* ) as_opts=-vx ;;
+         *v* ) as_opts=-v ;;
+         *x* ) as_opts=-x ;;
+         * ) as_opts= ;;
+       esac
+       exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: openssh-unix-dev@mindrot.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='OpenSSH'
+PACKAGE_TARNAME='openssh'
+PACKAGE_VERSION='Portable'
+PACKAGE_STRING='OpenSSH Portable'
+PACKAGE_BUGREPORT='openssh-unix-dev@mindrot.org'
+PACKAGE_URL=''
+
+ac_unique_file="ssh.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+TEST_SSH_IPV6
+piddir
+user_path
+mansubdir
+MANTYPE
+XAUTH_PATH
+STRIP_OPT
+xauth_path
+PRIVSEP_PATH
+KRB5CONF
+SSHDLIBS
+SSHLIBS
+SSH_PRIVSEP_USER
+COMMENT_OUT_ECC
+TEST_SSH_ECC
+TEST_SSH_SHA256
+LIBEDIT
+PKGCONFIG
+LD
+PATH_PASSWD_PROG
+LOGIN_PROGRAM_FALLBACK
+STARTUP_SCRIPT_SHELL
+MAKE_PACKAGE_SUPPORTED
+PATH_USERADD_PROG
+PATH_GROUPADD_PROG
+MANFMT
+TEST_SHELL
+MANDOC
+NROFF
+GROFF
+SH
+TEST_MINUS_S_SH
+ENT
+SED
+PERL
+KILL
+CAT
+AR
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+RANLIB
+AWK
+EGREP
+GREP
+CPP
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_largefile
+with_stackprotect
+with_rpath
+with_cflags
+with_cppflags
+with_ldflags
+with_libs
+with_Werror
+with_solaris_contracts
+with_solaris_projects
+with_osfsia
+with_zlib
+with_zlib_version_check
+with_skey
+with_tcp_wrappers
+with_libedit
+with_audit
+with_ssl_dir
+with_openssl_header_check
+with_ssl_engine
+with_prngd_port
+with_prngd_socket
+with_pam
+with_privsep_user
+with_sandbox
+with_selinux
+with_kerberos5
+with_privsep_path
+with_xauth
+enable_strip
+with_maildir
+with_mantype
+with_md5_passwords
+with_shadow
+with_ipaddr_display
+enable_etc_default_login
+with_default_path
+with_superuser_path
+with_4in6
+with_bsd_auth
+with_pid_dir
+enable_lastlog
+enable_utmp
+enable_utmpx
+enable_wtmp
+enable_wtmpx
+enable_libutil
+enable_pututline
+enable_pututxline
+with_lastlog
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used" >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_myself" : 'X\(//\)[^/]' \| \
+        X"$as_myself" : 'X\(//\)$' \| \
+        X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures OpenSSH Portable to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/openssh]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of OpenSSH Portable:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --disable-largefile     omit support for large files
+  --disable-strip         Disable calling strip(1) on install
+  --disable-etc-default-login Disable using PATH from /etc/default/login no
+  --disable-lastlog       disable use of lastlog even if detected no
+  --disable-utmp          disable use of utmp even if detected no
+  --disable-utmpx         disable use of utmpx even if detected no
+  --disable-wtmp          disable use of wtmp even if detected no
+  --disable-wtmpx         disable use of wtmpx even if detected no
+  --disable-libutil       disable use of libutil (login() etc.) no
+  --disable-pututline     disable use of pututline() etc. (uwtmp) no
+  --disable-pututxline    disable use of pututxline() etc. (uwtmpx) no
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --without-stackprotect  Don't use compiler's stack protection
+  --without-rpath         Disable auto-added -R linker paths
+  --with-cflags           Specify additional flags to pass to compiler
+  --with-cppflags         Specify additional flags to pass to preprocessor
+  --with-ldflags          Specify additional flags to pass to linker
+  --with-libs             Specify additional libraries to link with
+  --with-Werror           Build main code with -Werror
+  --with-solaris-contracts Enable Solaris process contracts (experimental)
+  --with-solaris-projects Enable Solaris projects (experimental)
+  --with-osfsia           Enable Digital Unix SIA
+  --with-zlib=PATH        Use zlib in PATH
+  --without-zlib-version-check Disable zlib version check
+  --with-skey[=PATH]      Enable S/Key support (optionally in PATH)
+  --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
+  --with-libedit[=PATH]   Enable libedit support for sftp
+  --with-audit=module     Enable audit support (modules=debug,bsm,linux)
+  --with-ssl-dir=PATH     Specify path to OpenSSL installation
+  --without-openssl-header-check Disable OpenSSL version consistency check
+  --with-ssl-engine       Enable OpenSSL (hardware) ENGINE support
+  --with-prngd-port=PORT  read entropy from PRNGD/EGD TCP localhost:PORT
+  --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)
+  --with-pam              Enable PAM support
+  --with-privsep-user=user Specify non-privileged user for privilege separation
+  --with-sandbox=style    Specify privilege separation sandbox (no, darwin, rlimit, systrace)
+  --with-selinux          Enable SELinux support
+  --with-kerberos5=PATH   Enable Kerberos 5 support
+  --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)
+  --with-xauth=PATH       Specify path to xauth program
+  --with-maildir=/path/to/mail    Specify your system mail directory
+  --with-mantype=man|cat|doc  Set man page type
+  --with-md5-passwords    Enable use of MD5 passwords
+  --without-shadow        Disable shadow password support
+  --with-ipaddr-display   Use ip address instead of hostname in \$DISPLAY
+  --with-default-path=    Specify default \$PATH environment for server
+  --with-superuser-path=  Specify different path for super-user
+  --with-4in6             Check for and convert IPv4 in IPv6 mapped addresses
+  --with-bsd-auth         Enable BSD auth support
+  --with-pid-dir=PATH     Specify location of ssh.pid file
+  --with-lastlog=FILE|DIR specify lastlog location common locations
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <openssh-unix-dev@mindrot.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+OpenSSH configure Portable
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ------------------------------------------- ##
+## Report this to openssh-unix-dev@mindrot.org ##
+## ------------------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+        return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+           return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if test "$cross_compiling" = yes; then
+    # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid; break
+else
+  as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+                       if test $ac_lo -le $ac_mid; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=$ac_mid; break
+else
+  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+                       if test $ac_mid -le $ac_hi; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid
+else
+  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (($2) < 0)
+    {
+      long int i = longval ();
+      if (i != ($2))
+       return 1;
+      fprintf (f, "%ld", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ($2))
+       return 1;
+      fprintf (f, "%lu", i);
+    }
+  /* Do not output a trailing newline, as this causes \r\n confusion
+     on some platforms.  */
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+  ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+  fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_compute_int
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by OpenSSH $as_me Portable, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       $as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       # differences in whitespace do not lead to failure.
+       ac_old_val_w=`echo x $ac_old_val`
+       ac_new_val_w=`echo x $ac_new_val`
+       if test "$ac_old_val_w" != "$ac_new_val_w"; then
+         { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+         ac_cache_corrupted=:
+       else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+         eval $ac_var=\$ac_old_val
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+              not a universal capable compiler
+            #endif
+            typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+       # Check for potential -arch flags.  It is not universal unless
+       # there are at least two -arch flags with different values.
+       ac_arch=
+       ac_prev=
+       for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+        if test -n "$ac_prev"; then
+          case $ac_word in
+            i?86 | x86_64 | ppc | ppc64)
+              if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+                ac_arch=$ac_word
+              else
+                ac_cv_c_bigendian=universal
+                break
+              fi
+              ;;
+          esac
+          ac_prev=
+        elif test "x$ac_word" = "x-arch"; then
+          ac_prev=arch
+        fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+            #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+                    && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+                    && LITTLE_ENDIAN)
+             bogus endian macros
+            #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+               #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+                not big endian
+               #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+             bogus endian macros
+            #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+                not big endian
+               #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+                 { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+               short int ascii_ii[] =
+                 { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+               int use_ascii (int i) {
+                 return ascii_mm[i] + ascii_ii[i];
+               }
+               short int ebcdic_ii[] =
+                 { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+               short int ebcdic_mm[] =
+                 { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+               int use_ebcdic (int i) {
+                 return ebcdic_mm[i] + ebcdic_ii[i];
+               }
+               extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+             ac_cv_c_bigendian=yes
+           fi
+           if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+             if test "$ac_cv_c_bigendian" = unknown; then
+               ac_cv_c_bigendian=no
+             else
+               # finding both strings is unlikely to happen, but who knows?
+               ac_cv_c_bigendian=unknown
+             fi
+           fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+            /* Are we little or big endian?  From Harbison&Steele.  */
+            union
+            {
+              long int l;
+              char c[sizeof (long int)];
+            } u;
+            u.l = 1;
+            return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+   no)
+      ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+# Checks for programs.
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           rm -rf conftest.one conftest.two conftest.dir
+           echo one > conftest.one
+           echo two > conftest.two
+           mkdir conftest.dir
+           if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+             test -s conftest.one && test -s conftest.two &&
+             test -s conftest.dir/conftest.one &&
+             test -s conftest.dir/conftest.two
+           then
+             ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+             break 3
+           fi
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+# Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $AR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_AR="$AR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+AR=$ac_cv_path_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "cat", so it can be a program name with args.
+set dummy cat; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_CAT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $CAT in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_CAT="$CAT" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_CAT="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+CAT=$ac_cv_path_CAT
+if test -n "$CAT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAT" >&5
+$as_echo "$CAT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "kill", so it can be a program name with args.
+set dummy kill; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_KILL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $KILL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_KILL="$KILL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_KILL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+KILL=$ac_cv_path_KILL
+if test -n "$KILL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KILL" >&5
+$as_echo "$KILL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+for ac_prog in perl5 perl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PERL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PERL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PERL=$ac_cv_path_PERL
+if test -n "$PERL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5
+$as_echo "$PERL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$PERL" && break
+done
+
+# Extract the first word of "sed", so it can be a program name with args.
+set dummy sed; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $SED in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SED="$SED" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+SED=$ac_cv_path_SED
+if test -n "$SED"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5
+$as_echo "$SED" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# Extract the first word of "ent", so it can be a program name with args.
+set dummy ent; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ENT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ENT in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ENT="$ENT" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ENT="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ENT=$ac_cv_path_ENT
+if test -n "$ENT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENT" >&5
+$as_echo "$ENT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# Extract the first word of "bash", so it can be a program name with args.
+set dummy bash; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_TEST_MINUS_S_SH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $TEST_MINUS_S_SH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
+if test -n "$TEST_MINUS_S_SH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5
+$as_echo "$TEST_MINUS_S_SH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "ksh", so it can be a program name with args.
+set dummy ksh; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_TEST_MINUS_S_SH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $TEST_MINUS_S_SH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
+if test -n "$TEST_MINUS_S_SH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5
+$as_echo "$TEST_MINUS_S_SH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "sh", so it can be a program name with args.
+set dummy sh; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_TEST_MINUS_S_SH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $TEST_MINUS_S_SH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
+if test -n "$TEST_MINUS_S_SH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5
+$as_echo "$TEST_MINUS_S_SH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "sh", so it can be a program name with args.
+set dummy sh; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $SH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SH="$SH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_SH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+SH=$ac_cv_path_SH
+if test -n "$SH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SH" >&5
+$as_echo "$SH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "groff", so it can be a program name with args.
+set dummy groff; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GROFF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GROFF in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+GROFF=$ac_cv_path_GROFF
+if test -n "$GROFF"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5
+$as_echo "$GROFF" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "nroff", so it can be a program name with args.
+set dummy nroff; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_NROFF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $NROFF in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+NROFF=$ac_cv_path_NROFF
+if test -n "$NROFF"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5
+$as_echo "$NROFF" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "mandoc", so it can be a program name with args.
+set dummy mandoc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MANDOC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MANDOC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_MANDOC="$MANDOC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_MANDOC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+MANDOC=$ac_cv_path_MANDOC
+if test -n "$MANDOC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANDOC" >&5
+$as_echo "$MANDOC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+TEST_SHELL=sh
+
+
+if test "x$MANDOC" != "x" ; then
+       MANFMT="$MANDOC"
+elif test "x$NROFF" != "x" ; then
+       MANFMT="$NROFF -mandoc"
+elif test "x$GROFF" != "x" ; then
+       MANFMT="$GROFF -mandoc -Tascii"
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no manpage formatted found" >&5
+$as_echo "$as_me: WARNING: no manpage formatted found" >&2;}
+       MANFMT="false"
+fi
+
+
+# Extract the first word of "groupadd", so it can be a program name with args.
+set dummy groupadd; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PATH_GROUPADD_PROG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PATH_GROUPADD_PROG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PATH_GROUPADD_PROG="$PATH_GROUPADD_PROG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /usr/sbin${PATH_SEPARATOR}/etc
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PATH_GROUPADD_PROG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_PATH_GROUPADD_PROG" && ac_cv_path_PATH_GROUPADD_PROG="groupadd"
+  ;;
+esac
+fi
+PATH_GROUPADD_PROG=$ac_cv_path_PATH_GROUPADD_PROG
+if test -n "$PATH_GROUPADD_PROG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_GROUPADD_PROG" >&5
+$as_echo "$PATH_GROUPADD_PROG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "useradd", so it can be a program name with args.
+set dummy useradd; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PATH_USERADD_PROG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PATH_USERADD_PROG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PATH_USERADD_PROG="$PATH_USERADD_PROG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /usr/sbin${PATH_SEPARATOR}/etc
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PATH_USERADD_PROG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_PATH_USERADD_PROG" && ac_cv_path_PATH_USERADD_PROG="useradd"
+  ;;
+esac
+fi
+PATH_USERADD_PROG=$ac_cv_path_PATH_USERADD_PROG
+if test -n "$PATH_USERADD_PROG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_USERADD_PROG" >&5
+$as_echo "$PATH_USERADD_PROG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "pkgmk", so it can be a program name with args.
+set dummy pkgmk; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MAKE_PACKAGE_SUPPORTED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$MAKE_PACKAGE_SUPPORTED"; then
+  ac_cv_prog_MAKE_PACKAGE_SUPPORTED="$MAKE_PACKAGE_SUPPORTED" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_MAKE_PACKAGE_SUPPORTED="yes"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_prog_MAKE_PACKAGE_SUPPORTED" && ac_cv_prog_MAKE_PACKAGE_SUPPORTED="no"
+fi
+fi
+MAKE_PACKAGE_SUPPORTED=$ac_cv_prog_MAKE_PACKAGE_SUPPORTED
+if test -n "$MAKE_PACKAGE_SUPPORTED"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE_PACKAGE_SUPPORTED" >&5
+$as_echo "$MAKE_PACKAGE_SUPPORTED" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test -x /sbin/sh; then
+       STARTUP_SCRIPT_SHELL=/sbin/sh
+
+else
+       STARTUP_SCRIPT_SHELL=/bin/sh
+
+fi
+
+# System features
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+        if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+fi
+
+
+if test -z "$AR" ; then
+       as_fn_error $? "*** 'ar' missing, please install or fix your \$PATH ***" "$LINENO" 5
+fi
+
+# Use LOGIN_PROGRAM from environment if possible
+if test ! -z "$LOGIN_PROGRAM" ; then
+
+cat >>confdefs.h <<_ACEOF
+#define LOGIN_PROGRAM_FALLBACK "$LOGIN_PROGRAM"
+_ACEOF
+
+else
+       # Search for login
+       # Extract the first word of "login", so it can be a program name with args.
+set dummy login; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LOGIN_PROGRAM_FALLBACK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LOGIN_PROGRAM_FALLBACK in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LOGIN_PROGRAM_FALLBACK="$LOGIN_PROGRAM_FALLBACK" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_LOGIN_PROGRAM_FALLBACK="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+LOGIN_PROGRAM_FALLBACK=$ac_cv_path_LOGIN_PROGRAM_FALLBACK
+if test -n "$LOGIN_PROGRAM_FALLBACK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LOGIN_PROGRAM_FALLBACK" >&5
+$as_echo "$LOGIN_PROGRAM_FALLBACK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+       if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then
+               cat >>confdefs.h <<_ACEOF
+#define LOGIN_PROGRAM_FALLBACK "$LOGIN_PROGRAM_FALLBACK"
+_ACEOF
+
+       fi
+fi
+
+# Extract the first word of "passwd", so it can be a program name with args.
+set dummy passwd; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PATH_PASSWD_PROG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PATH_PASSWD_PROG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PATH_PASSWD_PROG="$PATH_PASSWD_PROG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PATH_PASSWD_PROG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PATH_PASSWD_PROG=$ac_cv_path_PATH_PASSWD_PROG
+if test -n "$PATH_PASSWD_PROG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_PASSWD_PROG" >&5
+$as_echo "$PATH_PASSWD_PROG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test ! -z "$PATH_PASSWD_PROG" ; then
+
+cat >>confdefs.h <<_ACEOF
+#define _PATH_PASSWD_PROG "$PATH_PASSWD_PROG"
+_ACEOF
+
+fi
+
+if test -z "$LD" ; then
+       LD=$CC
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+
+ac_fn_c_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include <limits.h>
+"
+if test "x$ac_cv_have_decl_LLONG_MAX" = xyes; then :
+  have_llong_max=1
+fi
+
+ac_fn_c_check_decl "$LINENO" "SYSTR_POLICY_KILL" "ac_cv_have_decl_SYSTR_POLICY_KILL" "
+       #include <sys/types.h>
+       #include <sys/param.h>
+       #include <dev/systrace.h>
+
+"
+if test "x$ac_cv_have_decl_SYSTR_POLICY_KILL" = xyes; then :
+  have_systr_policy_kill=1
+fi
+
+ac_fn_c_check_decl "$LINENO" "RLIMIT_NPROC" "ac_cv_have_decl_RLIMIT_NPROC" "
+       #include <sys/types.h>
+       #include <sys/resource.h>
+
+"
+if test "x$ac_cv_have_decl_RLIMIT_NPROC" = xyes; then :
+
+$as_echo "#define HAVE_RLIMIT_NPROC /**/" >>confdefs.h
+
+fi
+
+
+use_stack_protector=1
+
+# Check whether --with-stackprotect was given.
+if test "${with_stackprotect+set}" = set; then :
+  withval=$with_stackprotect;
+    if test "x$withval" = "xno"; then
+       use_stack_protector=0
+    fi
+fi
+
+
+
+if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wall" >&5
+$as_echo_n "checking if $CC supports -Wall... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wall"
+       _define_flag=""
+       test "x$_define_flag" = "x" && _define_flag="-Wall"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wpointer-arith" >&5
+$as_echo_n "checking if $CC supports -Wpointer-arith... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wpointer-arith"
+       _define_flag=""
+       test "x$_define_flag" = "x" && _define_flag="-Wpointer-arith"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wuninitialized" >&5
+$as_echo_n "checking if $CC supports -Wuninitialized... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wuninitialized"
+       _define_flag=""
+       test "x$_define_flag" = "x" && _define_flag="-Wuninitialized"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wsign-compare" >&5
+$as_echo_n "checking if $CC supports -Wsign-compare... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wsign-compare"
+       _define_flag=""
+       test "x$_define_flag" = "x" && _define_flag="-Wsign-compare"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wformat-security" >&5
+$as_echo_n "checking if $CC supports -Wformat-security... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wformat-security"
+       _define_flag=""
+       test "x$_define_flag" = "x" && _define_flag="-Wformat-security"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wpointer-sign" >&5
+$as_echo_n "checking if $CC supports -Wpointer-sign... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wpointer-sign"
+       _define_flag="-Wno-pointer-sign"
+       test "x$_define_flag" = "x" && _define_flag="-Wpointer-sign"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wunused-result" >&5
+$as_echo_n "checking if $CC supports -Wunused-result... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wunused-result"
+       _define_flag="-Wno-unused-result"
+       test "x$_define_flag" = "x" && _define_flag="-Wunused-result"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       {
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -fno-strict-aliasing" >&5
+$as_echo_n "checking if $CC supports -fno-strict-aliasing... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -fno-strict-aliasing"
+       _define_flag=""
+       test "x$_define_flag" = "x" && _define_flag="-fno-strict-aliasing"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                 CFLAGS="$saved_CFLAGS $_define_flag"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+}
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5
+$as_echo_n "checking gcc version... " >&6; }
+       GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'`
+       case $GCC_VER in
+               1.*) no_attrib_nonnull=1 ;;
+               2.8* | 2.9*)
+                    no_attrib_nonnull=1
+                    ;;
+               2.*) no_attrib_nonnull=1 ;;
+               *) ;;
+       esac
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCC_VER" >&5
+$as_echo "$GCC_VER" >&6; }
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC accepts -fno-builtin-memset" >&5
+$as_echo_n "checking if $CC accepts -fno-builtin-memset... " >&6; }
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -fno-builtin-memset"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <string.h>
+int
+main ()
+{
+ char b[10]; memset(b, 0, sizeof(b));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                 CFLAGS="$saved_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+       # -fstack-protector-all doesn't always work for some GCC versions
+       # and/or platforms, so we test if we can.  If it's not supported
+       # on a given platform gcc will emit a warning so we use -Werror.
+       if test "x$use_stack_protector" = "x1"; then
+           for t in -fstack-protector-all -fstack-protector; do
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports $t" >&5
+$as_echo_n "checking if $CC supports $t... " >&6; }
+               saved_CFLAGS="$CFLAGS"
+               saved_LDFLAGS="$LDFLAGS"
+               CFLAGS="$CFLAGS $t -Werror"
+               LDFLAGS="$LDFLAGS $t -Werror"
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdio.h>
+int
+main ()
+{
+
+       char x[256];
+       snprintf(x, sizeof(x), "XXX");
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                     CFLAGS="$saved_CFLAGS $t"
+                     LDFLAGS="$saved_LDFLAGS $t"
+                     { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $t works" >&5
+$as_echo_n "checking if $t works... " >&6; }
+                     if test "$cross_compiling" = yes; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: cannot test" >&5
+$as_echo "$as_me: WARNING: cross compiling: cannot test" >&2;}
+                         break
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdio.h>
+int
+main ()
+{
+
+       char x[256];
+       snprintf(x, sizeof(x), "XXX");
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                         break
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+               CFLAGS="$saved_CFLAGS"
+               LDFLAGS="$saved_LDFLAGS"
+           done
+       fi
+
+       if test -z "$have_llong_max"; then
+               # retry LLONG_MAX with -std=gnu99, needed on some Linuxes
+               unset ac_cv_have_decl_LLONG_MAX
+               saved_CFLAGS="$CFLAGS"
+               CFLAGS="$CFLAGS -std=gnu99"
+               ac_fn_c_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include <limits.h>
+
+"
+if test "x$ac_cv_have_decl_LLONG_MAX" = xyes; then :
+  have_llong_max=1
+else
+  CFLAGS="$saved_CFLAGS"
+fi
+
+       fi
+fi
+
+if test "x$no_attrib_nonnull" != "x1" ; then
+
+$as_echo "#define HAVE_ATTRIBUTE__NONNULL__ 1" >>confdefs.h
+
+fi
+
+
+# Check whether --with-rpath was given.
+if test "${with_rpath+set}" = set; then :
+  withval=$with_rpath;
+               if test "x$withval" = "xno" ; then
+                       need_dash_r=""
+               fi
+               if test "x$withval" = "xyes" ; then
+                       need_dash_r=1
+               fi
+
+
+fi
+
+
+# Allow user to specify flags
+
+# Check whether --with-cflags was given.
+if test "${with_cflags+set}" = set; then :
+  withval=$with_cflags;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       CFLAGS="$CFLAGS $withval"
+               fi
+
+
+fi
+
+
+# Check whether --with-cppflags was given.
+if test "${with_cppflags+set}" = set; then :
+  withval=$with_cppflags;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       CPPFLAGS="$CPPFLAGS $withval"
+               fi
+
+
+fi
+
+
+# Check whether --with-ldflags was given.
+if test "${with_ldflags+set}" = set; then :
+  withval=$with_ldflags;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       LDFLAGS="$LDFLAGS $withval"
+               fi
+
+
+fi
+
+
+# Check whether --with-libs was given.
+if test "${with_libs+set}" = set; then :
+  withval=$with_libs;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       LIBS="$LIBS $withval"
+               fi
+
+
+fi
+
+
+# Check whether --with-Werror was given.
+if test "${with_Werror+set}" = set; then :
+  withval=$with_Werror;
+               if test -n "$withval"  &&  test "x$withval" != "xno"; then
+                       werror_flags="-Werror"
+                       if test "x${withval}" != "xyes"; then
+                               werror_flags="$withval"
+                       fi
+               fi
+
+
+fi
+
+
+for ac_header in  \
+       bstring.h \
+       crypt.h \
+       crypto/sha2.h \
+       dirent.h \
+       endian.h \
+       features.h \
+       fcntl.h \
+       floatingpoint.h \
+       getopt.h \
+       glob.h \
+       ia.h \
+       iaf.h \
+       limits.h \
+       login.h \
+       maillock.h \
+       ndir.h \
+       net/if_tun.h \
+       netdb.h \
+       netgroup.h \
+       pam/pam_appl.h \
+       paths.h \
+       poll.h \
+       pty.h \
+       readpassphrase.h \
+       rpc/types.h \
+       security/pam_appl.h \
+       sha2.h \
+       shadow.h \
+       stddef.h \
+       stdint.h \
+       string.h \
+       strings.h \
+       sys/audit.h \
+       sys/bitypes.h \
+       sys/bsdtty.h \
+       sys/cdefs.h \
+       sys/dir.h \
+       sys/mman.h \
+       sys/ndir.h \
+       sys/poll.h \
+       sys/prctl.h \
+       sys/pstat.h \
+       sys/select.h \
+       sys/stat.h \
+       sys/stream.h \
+       sys/stropts.h \
+       sys/strtio.h \
+       sys/statvfs.h \
+       sys/sysmacros.h \
+       sys/time.h \
+       sys/timers.h \
+       sys/un.h \
+       time.h \
+       tmpdir.h \
+       ttyent.h \
+       ucred.h \
+       unistd.h \
+       usersec.h \
+       util.h \
+       utime.h \
+       utmp.h \
+       utmpx.h \
+       vis.h \
+
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# lastlog.h requires sys/time.h to be included first on Solaris
+for ac_header in lastlog.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "lastlog.h" "ac_cv_header_lastlog_h" "
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+"
+if test "x$ac_cv_header_lastlog_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LASTLOG_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# sys/ptms.h requires sys/stream.h to be included first on Solaris
+for ac_header in sys/ptms.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "sys/ptms.h" "ac_cv_header_sys_ptms_h" "
+#ifdef HAVE_SYS_STREAM_H
+# include <sys/stream.h>
+#endif
+
+"
+if test "x$ac_cv_header_sys_ptms_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_PTMS_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# login_cap.h requires sys/types.h on NetBSD
+for ac_header in login_cap.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "login_cap.h" "ac_cv_header_login_cap_h" "
+#include <sys/types.h>
+
+"
+if test "x$ac_cv_header_login_cap_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LOGIN_CAP_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# older BSDs need sys/param.h before sys/mount.h
+for ac_header in sys/mount.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" "
+#include <sys/param.h>
+
+"
+if test "x$ac_cv_header_sys_mount_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MOUNT_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# Messages for features tested for in target-specific section
+SIA_MSG="no"
+SPC_MSG="no"
+SP_MSG="no"
+
+# Check for some target-specific stuff
+case "$host" in
+*-*-aix*)
+       # Some versions of VAC won't allow macro redefinitions at
+       # -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that
+       # particularly with older versions of vac or xlc.
+       # It also throws errors about null macro argments, but these are
+       # not fatal.
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows macro redefinitions" >&5
+$as_echo_n "checking if compiler allows macro redefinitions... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#define testmacro foo
+#define testmacro bar
+int
+main ()
+{
+ exit(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+             CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`"
+             LD="`echo $LD | sed 's/-qlanglvl\=ansi//g'`"
+             CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`"
+             CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`"
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to specify blibpath for linker ($LD)" >&5
+$as_echo_n "checking how to specify blibpath for linker ($LD)... " >&6; }
+       if (test -z "$blibpath"); then
+               blibpath="/usr/lib:/lib"
+       fi
+       saved_LDFLAGS="$LDFLAGS"
+       if test "$GCC" = "yes"; then
+               flags="-Wl,-blibpath: -Wl,-rpath, -blibpath:"
+       else
+               flags="-blibpath: -Wl,-blibpath: -Wl,-rpath,"
+       fi
+       for tryflags in $flags ;do
+               if (test -z "$blibflags"); then
+                       LDFLAGS="$saved_LDFLAGS $tryflags$blibpath"
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  blibflags=$tryflags
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+               fi
+       done
+       if (test -z "$blibflags"); then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+               as_fn_error $? "*** must be able to specify blibpath on AIX - check config.log" "$LINENO" 5
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $blibflags" >&5
+$as_echo "$blibflags" >&6; }
+       fi
+       LDFLAGS="$saved_LDFLAGS"
+               ac_fn_c_check_func "$LINENO" "authenticate" "ac_cv_func_authenticate"
+if test "x$ac_cv_func_authenticate" = xyes; then :
+
+$as_echo "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for authenticate in -ls" >&5
+$as_echo_n "checking for authenticate in -ls... " >&6; }
+if ${ac_cv_lib_s_authenticate+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ls  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char authenticate ();
+int
+main ()
+{
+return authenticate ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_s_authenticate=yes
+else
+  ac_cv_lib_s_authenticate=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_s_authenticate" >&5
+$as_echo "$ac_cv_lib_s_authenticate" >&6; }
+if test "x$ac_cv_lib_s_authenticate" = xyes; then :
+   $as_echo "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h
+
+                               LIBS="$LIBS -ls"
+
+fi
+
+
+fi
+
+               ac_fn_c_check_decl "$LINENO" "authenticate" "ac_cv_have_decl_authenticate" "#include <usersec.h>
+"
+if test "x$ac_cv_have_decl_authenticate" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_AUTHENTICATE $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "loginrestrictions" "ac_cv_have_decl_loginrestrictions" "#include <usersec.h>
+"
+if test "x$ac_cv_have_decl_loginrestrictions" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_LOGINRESTRICTIONS $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "loginsuccess" "ac_cv_have_decl_loginsuccess" "#include <usersec.h>
+"
+if test "x$ac_cv_have_decl_loginsuccess" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_LOGINSUCCESS $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "passwdexpired" "ac_cv_have_decl_passwdexpired" "#include <usersec.h>
+"
+if test "x$ac_cv_have_decl_passwdexpired" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_PASSWDEXPIRED $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "setauthdb" "ac_cv_have_decl_setauthdb" "#include <usersec.h>
+"
+if test "x$ac_cv_have_decl_setauthdb" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SETAUTHDB $ac_have_decl
+_ACEOF
+
+               ac_fn_c_check_decl "$LINENO" "loginfailed" "ac_cv_have_decl_loginfailed" "#include <usersec.h>
+
+"
+if test "x$ac_cv_have_decl_loginfailed" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_LOGINFAILED $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if loginfailed takes 4 arguments" >&5
+$as_echo_n "checking if loginfailed takes 4 arguments... " >&6; }
+           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <usersec.h>
+int
+main ()
+{
+ (void)loginfailed("user","host","tty",0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define AIX_LOGINFAILED_4ARG 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+       for ac_func in getgrset setauthdb
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+       ac_fn_c_check_decl "$LINENO" "F_CLOSEM" "ac_cv_have_decl_F_CLOSEM" " #include <limits.h>
+             #include <fcntl.h>
+
+"
+if test "x$ac_cv_have_decl_F_CLOSEM" = xyes; then :
+
+$as_echo "#define HAVE_FCNTL_CLOSEM 1" >>confdefs.h
+
+fi
+
+       check_for_aix_broken_getaddrinfo=1
+
+$as_echo "#define BROKEN_REALPATH 1" >>confdefs.h
+
+
+$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+
+$as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
+
+
+$as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h
+
+
+$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
+
+
+$as_echo "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h
+
+
+$as_echo "#define PTY_ZEROREAD 1" >>confdefs.h
+
+       ;;
+*-*-cygwin*)
+       check_for_libcrypt_later=1
+       LIBS="$LIBS /usr/lib/textreadmode.o"
+
+$as_echo "#define HAVE_CYGWIN 1" >>confdefs.h
+
+
+$as_echo "#define USE_PIPES 1" >>confdefs.h
+
+
+$as_echo "#define DISABLE_SHADOW 1" >>confdefs.h
+
+
+$as_echo "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h
+
+
+$as_echo "#define NO_IPPORT_RESERVED_CONCEPT 1" >>confdefs.h
+
+
+$as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
+
+
+$as_echo "#define SSH_IOBUFSZ 65535" >>confdefs.h
+
+
+$as_echo "#define FILESYSTEM_NO_BACKSLASH 1" >>confdefs.h
+
+       ;;
+*-*-dgux*)
+
+$as_echo "#define IP_TOS_IS_BROKEN 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       ;;
+*-*-darwin*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have working getaddrinfo" >&5
+$as_echo_n "checking if we have working getaddrinfo... " >&6; }
+       if test "$cross_compiling" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: assume it is working" >&5
+$as_echo "assume it is working" >&6; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <mach-o/dyld.h>
+main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
+               exit(0);
+       else
+               exit(1);
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: working" >&5
+$as_echo "working" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: buggy" >&5
+$as_echo "buggy" >&6; }
+
+$as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_GLOB 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define BIND_8_COMPAT 1
+_ACEOF
+
+
+$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h
+
+
+$as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h
+
+
+$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
+
+
+       ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default"
+if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then :
+
+else
+
+$as_echo "#define AU_IPv4 0" >>confdefs.h
+
+           #include <bsm/audit.h>
+
+$as_echo "#define LASTLOG_WRITE_PUTUTXLINE 1" >>confdefs.h
+
+
+fi
+
+
+$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
+
+       for ac_func in sandbox_init
+do :
+  ac_fn_c_check_func "$LINENO" "sandbox_init" "ac_cv_func_sandbox_init"
+if test "x$ac_cv_func_sandbox_init" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SANDBOX_INIT 1
+_ACEOF
+
+fi
+done
+
+       for ac_header in sandbox.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sandbox.h" "ac_cv_header_sandbox_h" "$ac_includes_default"
+if test "x$ac_cv_header_sandbox_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SANDBOX_H 1
+_ACEOF
+
+fi
+
+done
+
+       ;;
+*-*-dragonfly*)
+       SSHDLIBS="$SSHDLIBS -lcrypt"
+       ;;
+*-*-haiku*)
+    LIBS="$LIBS -lbsd "
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5
+$as_echo_n "checking for socket in -lnetwork... " >&6; }
+if ${ac_cv_lib_network_socket+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetwork  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_network_socket=yes
+else
+  ac_cv_lib_network_socket=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5
+$as_echo "$ac_cv_lib_network_socket" >&6; }
+if test "x$ac_cv_lib_network_socket" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNETWORK 1
+_ACEOF
+
+  LIBS="-lnetwork $LIBS"
+
+fi
+
+    $as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h
+
+    MANTYPE=man
+    ;;
+*-*-hpux*)
+       # first we define all of the options common to all HP-UX releases
+       CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
+       IPADDR_IN_DISPLAY=yes
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+
+$as_echo "#define LOGIN_NO_ENDOPT 1" >>confdefs.h
+
+       $as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h
+
+
+$as_echo "#define LOCKED_PASSWD_STRING \"*\"" >>confdefs.h
+
+       $as_echo "#define SPT_TYPE SPT_PSTAT" >>confdefs.h
+
+       maildir="/var/mail"
+       LIBS="$LIBS -lsec"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for t_error in -lxnet" >&5
+$as_echo_n "checking for t_error in -lxnet... " >&6; }
+if ${ac_cv_lib_xnet_t_error+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxnet  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char t_error ();
+int
+main ()
+{
+return t_error ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_xnet_t_error=yes
+else
+  ac_cv_lib_xnet_t_error=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_t_error" >&5
+$as_echo "$ac_cv_lib_xnet_t_error" >&6; }
+if test "x$ac_cv_lib_xnet_t_error" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXNET 1
+_ACEOF
+
+  LIBS="-lxnet $LIBS"
+
+else
+  as_fn_error $? "*** -lxnet needed on HP-UX - check config.log ***" "$LINENO" 5
+fi
+
+
+       # next, we define all of the options specific to major releases
+       case "$host" in
+       *-*-hpux10*)
+               if test -z "$GCC"; then
+                       CFLAGS="$CFLAGS -Ae"
+               fi
+               ;;
+       *-*-hpux11*)
+
+$as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+
+$as_echo "#define DISABLE_UTMP 1" >>confdefs.h
+
+
+$as_echo "#define USE_BTMP 1" >>confdefs.h
+
+               check_for_hpux_broken_getaddrinfo=1
+               check_for_conflicting_getspnam=1
+               ;;
+       esac
+
+       # lastly, we define options specific to minor releases
+       case "$host" in
+       *-*-hpux10.26)
+
+$as_echo "#define HAVE_SECUREWARE 1" >>confdefs.h
+
+               disable_ptmx_check=yes
+               LIBS="$LIBS -lsecpw"
+               ;;
+       esac
+       ;;
+*-*-irix5*)
+       PATH="$PATH:/usr/etc"
+
+$as_echo "#define BROKEN_INET_NTOA 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+
+$as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h
+
+       $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
+
+       ;;
+*-*-irix6*)
+       PATH="$PATH:/usr/etc"
+
+$as_echo "#define WITH_IRIX_ARRAY 1" >>confdefs.h
+
+
+$as_echo "#define WITH_IRIX_PROJECT 1" >>confdefs.h
+
+
+$as_echo "#define WITH_IRIX_AUDIT 1" >>confdefs.h
+
+       ac_fn_c_check_func "$LINENO" "jlimit_startjob" "ac_cv_func_jlimit_startjob"
+if test "x$ac_cv_func_jlimit_startjob" = xyes; then :
+
+$as_echo "#define WITH_IRIX_JOBS 1" >>confdefs.h
+
+fi
+
+       $as_echo "#define BROKEN_INET_NTOA 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h
+
+       $as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h
+
+       $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
+
+       ;;
+*-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
+       check_for_libcrypt_later=1
+       $as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h
+
+       $as_echo "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h
+
+       $as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
+
+
+$as_echo "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h
+
+
+$as_echo "#define USE_BTMP 1" >>confdefs.h
+
+       ;;
+*-*-linux*)
+       no_dev_ptmx=1
+       check_for_libcrypt_later=1
+       check_for_openpty_ctty_bug=1
+
+$as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h
+
+
+$as_echo "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h
+
+       $as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
+
+
+$as_echo "#define LINK_OPNOTSUPP_ERRNO EPERM" >>confdefs.h
+
+
+$as_echo "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h
+
+       $as_echo "#define USE_BTMP 1" >>confdefs.h
+
+
+$as_echo "#define LINUX_OOM_ADJUST 1" >>confdefs.h
+
+       inet6_default_4in6=yes
+       case `uname -r` in
+       1.*|2.0.*)
+
+$as_echo "#define BROKEN_CMSG_TYPE 1" >>confdefs.h
+
+               ;;
+       esac
+       # tun(4) forwarding compat code
+       for ac_header in linux/if_tun.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/if_tun.h" "ac_cv_header_linux_if_tun_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_if_tun_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_IF_TUN_H 1
+_ACEOF
+
+fi
+
+done
+
+       if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then
+
+$as_echo "#define SSH_TUN_LINUX 1" >>confdefs.h
+
+
+$as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h
+
+
+$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
+
+       fi
+       ;;
+mips-sony-bsd|mips-sony-newsos4)
+
+$as_echo "#define NEED_SETPGRP 1" >>confdefs.h
+
+       SONY=1
+       ;;
+*-*-netbsd*)
+       check_for_libcrypt_before=1
+       if test "x$withval" != "xno" ; then
+               need_dash_r=1
+       fi
+
+$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h
+
+       ac_fn_c_check_header_mongrel "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_if_tap_h" = xyes; then :
+
+else
+
+$as_echo "#define SSH_TUN_NO_L2 1" >>confdefs.h
+
+fi
+
+
+
+$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
+
+       ;;
+*-*-freebsd*)
+       check_for_libcrypt_later=1
+
+$as_echo "#define LOCKED_PASSWD_PREFIX \"*LOCKED*\"" >>confdefs.h
+
+
+$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h
+
+       ac_fn_c_check_header_mongrel "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_if_tap_h" = xyes; then :
+
+else
+
+$as_echo "#define SSH_TUN_NO_L2 1" >>confdefs.h
+
+fi
+
+
+
+$as_echo "#define BROKEN_GLOB 1" >>confdefs.h
+
+       ;;
+*-*-bsdi*)
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       ;;
+*-next-*)
+       conf_lastlog_location="/usr/adm/lastlog"
+       conf_utmp_location=/etc/utmp
+       conf_wtmp_location=/usr/adm/wtmp
+       maildir=/usr/spool/mail
+
+$as_echo "#define HAVE_NEXT 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_REALPATH 1" >>confdefs.h
+
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_SAVED_UIDS 1" >>confdefs.h
+
+       ;;
+*-*-openbsd*)
+
+$as_echo "#define HAVE_ATTRIBUTE__SENTINEL__ 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_ATTRIBUTE__BOUNDED__ 1" >>confdefs.h
+
+
+$as_echo "#define SSH_TUN_OPENBSD 1" >>confdefs.h
+
+
+$as_echo "#define SYSLOG_R_SAFE_IN_SIGHAND 1" >>confdefs.h
+
+       ;;
+*-*-solaris*)
+       if test "x$withval" != "xno" ; then
+               need_dash_r=1
+       fi
+       $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+       $as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h
+
+
+$as_echo "#define LOGIN_NEEDS_TERM 1" >>confdefs.h
+
+       $as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h
+
+
+$as_echo "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h
+
+       $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
+
+       # Pushing STREAMS modules will cause sshd to acquire a controlling tty.
+
+$as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
+
+
+$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h
+
+       external_path_file=/etc/default/login
+       # hardwire lastlog location (can't detect it on some versions)
+       conf_lastlog_location="/var/adm/lastlog"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for obsolete utmp and wtmp in solaris2.x" >&5
+$as_echo_n "checking for obsolete utmp and wtmp in solaris2.x... " >&6; }
+       sol2ver=`echo "$host"| sed -e 's/.*[0-9]\.//'`
+       if test "$sol2ver" -ge 8; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               $as_echo "#define DISABLE_UTMP 1" >>confdefs.h
+
+
+$as_echo "#define DISABLE_WTMP 1" >>confdefs.h
+
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+# Check whether --with-solaris-contracts was given.
+if test "${with_solaris_contracts+set}" = set; then :
+  withval=$with_solaris_contracts;
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ct_tmpl_activate in -lcontract" >&5
+$as_echo_n "checking for ct_tmpl_activate in -lcontract... " >&6; }
+if ${ac_cv_lib_contract_ct_tmpl_activate+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcontract  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ct_tmpl_activate ();
+int
+main ()
+{
+return ct_tmpl_activate ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_contract_ct_tmpl_activate=yes
+else
+  ac_cv_lib_contract_ct_tmpl_activate=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_contract_ct_tmpl_activate" >&5
+$as_echo "$ac_cv_lib_contract_ct_tmpl_activate" >&6; }
+if test "x$ac_cv_lib_contract_ct_tmpl_activate" = xyes; then :
+
+$as_echo "#define USE_SOLARIS_PROCESS_CONTRACTS 1" >>confdefs.h
+
+                         SSHDLIBS="$SSHDLIBS -lcontract"
+                         SPC_MSG="yes"
+fi
+
+
+fi
+
+
+# Check whether --with-solaris-projects was given.
+if test "${with_solaris_projects+set}" = set; then :
+  withval=$with_solaris_projects;
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setproject in -lproject" >&5
+$as_echo_n "checking for setproject in -lproject... " >&6; }
+if ${ac_cv_lib_project_setproject+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lproject  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setproject ();
+int
+main ()
+{
+return setproject ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_project_setproject=yes
+else
+  ac_cv_lib_project_setproject=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_project_setproject" >&5
+$as_echo "$ac_cv_lib_project_setproject" >&6; }
+if test "x$ac_cv_lib_project_setproject" = xyes; then :
+
+$as_echo "#define USE_SOLARIS_PROJECTS 1" >>confdefs.h
+
+                       SSHDLIBS="$SSHDLIBS -lproject"
+                       SP_MSG="yes"
+fi
+
+
+fi
+
+       ;;
+*-*-sunos4*)
+       CPPFLAGS="$CPPFLAGS -DSUNOS4"
+       for ac_func in getpwanam
+do :
+  ac_fn_c_check_func "$LINENO" "getpwanam" "ac_cv_func_getpwanam"
+if test "x$ac_cv_func_getpwanam" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETPWANAM 1
+_ACEOF
+
+fi
+done
+
+       $as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
+
+       conf_utmp_location=/etc/utmp
+       conf_wtmp_location=/var/adm/wtmp
+       conf_lastlog_location=/var/adm/lastlog
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       ;;
+*-ncr-sysv*)
+       LIBS="$LIBS -lc89"
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       ;;
+*-sni-sysv*)
+       # /usr/ucblib MUST NOT be searched on ReliantUNIX
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5
+$as_echo_n "checking for dlsym in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlsym+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlsym ();
+int
+main ()
+{
+return dlsym ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlsym=yes
+else
+  ac_cv_lib_dl_dlsym=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5
+$as_echo "$ac_cv_lib_dl_dlsym" >&6; }
+if test "x$ac_cv_lib_dl_dlsym" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+       # -lresolv needs to be at the end of LIBS or DNS lookups break
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5
+$as_echo_n "checking for res_query in -lresolv... " >&6; }
+if ${ac_cv_lib_resolv_res_query+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char res_query ();
+int
+main ()
+{
+return res_query ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_resolv_res_query=yes
+else
+  ac_cv_lib_resolv_res_query=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_query" >&5
+$as_echo "$ac_cv_lib_resolv_res_query" >&6; }
+if test "x$ac_cv_lib_resolv_res_query" = xyes; then :
+   LIBS="$LIBS -lresolv"
+fi
+
+       IPADDR_IN_DISPLAY=yes
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define IP_TOS_IS_BROKEN 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
+
+       external_path_file=/etc/default/login
+       # /usr/ucblib/libucb.a no longer needed on ReliantUNIX
+       # Attention: always take care to bind libsocket and libnsl before libc,
+       # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog
+       ;;
+# UnixWare 1.x, UnixWare 2.x, and others based on code from Univel.
+*-*-sysv4.2*)
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+
+$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
+
+       $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
+
+       ;;
+# UnixWare 7.x, OpenUNIX 8
+*-*-sysv5*)
+       CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf"
+
+$as_echo "#define UNIXWARE_LONG_PASSWORDS 1" >>confdefs.h
+
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       $as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
+
+       case "$host" in
+       *-*-sysv5SCO_SV*)       # SCO OpenServer 6.x
+               maildir=/var/spool/mail
+               TEST_SHELL=/u95/bin/sh
+
+$as_echo "#define BROKEN_LIBIAF 1" >>confdefs.h
+
+               $as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getluid in -lprot" >&5
+$as_echo_n "checking for getluid in -lprot... " >&6; }
+if ${ac_cv_lib_prot_getluid+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lprot  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getluid ();
+int
+main ()
+{
+return getluid ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_prot_getluid=yes
+else
+  ac_cv_lib_prot_getluid=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_prot_getluid" >&5
+$as_echo "$ac_cv_lib_prot_getluid" >&6; }
+if test "x$ac_cv_lib_prot_getluid" = xyes; then :
+   LIBS="$LIBS -lprot"
+                       for ac_func in getluid setluid
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+                       $as_echo "#define HAVE_SECUREWARE 1" >>confdefs.h
+
+                       $as_echo "#define DISABLE_SHADOW 1" >>confdefs.h
+
+
+fi
+
+               ;;
+       *)      $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
+
+               check_for_libcrypt_later=1
+               ;;
+       esac
+       ;;
+*-*-sysv*)
+       ;;
+# SCO UNIX and OEM versions of SCO UNIX
+*-*-sco3.2v4*)
+       as_fn_error $? "\"This Platform is no longer supported.\"" "$LINENO" 5
+       ;;
+# SCO OpenServer 5.x
+*-*-sco3.2v5*)
+       if test -z "$GCC"; then
+               CFLAGS="$CFLAGS -belf"
+       fi
+       LIBS="$LIBS -lprot -lx -ltinfo -lm"
+       no_dev_ptmx=1
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define HAVE_SECUREWARE 1" >>confdefs.h
+
+       $as_echo "#define DISABLE_SHADOW 1" >>confdefs.h
+
+       $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       $as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h
+
+       $as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
+
+       for ac_func in getluid setluid
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+       MANTYPE=man
+       TEST_SHELL=ksh
+       ;;
+*-*-unicosmk*)
+
+$as_echo "#define NO_SSH_LASTLOG 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
+
+       LDFLAGS="$LDFLAGS"
+       LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
+       MANTYPE=cat
+       ;;
+*-*-unicosmp*)
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       $as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h
+
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
+
+       LDFLAGS="$LDFLAGS"
+       LIBS="$LIBS -lgen -lacid -ldb"
+       MANTYPE=cat
+       ;;
+*-*-unicos*)
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
+
+       $as_echo "#define NO_SSH_LASTLOG 1" >>confdefs.h
+
+       LDFLAGS="$LDFLAGS -Wl,-Dmsglevel=334:fatal"
+       LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
+       MANTYPE=cat
+       ;;
+*-dec-osf*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Digital Unix SIA" >&5
+$as_echo_n "checking for Digital Unix SIA... " >&6; }
+       no_osfsia=""
+
+# Check whether --with-osfsia was given.
+if test "${with_osfsia+set}" = set; then :
+  withval=$with_osfsia;
+                       if test "x$withval" = "xno" ; then
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+                               no_osfsia=1
+                       fi
+
+fi
+
+       if test -z "$no_osfsia" ; then
+               if test -f /etc/sia/matrix.conf; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_OSF_SIA 1" >>confdefs.h
+
+
+$as_echo "#define DISABLE_LOGIN 1" >>confdefs.h
+
+                       $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
+
+                       LIBS="$LIBS -lsecurity -ldb -lm -laud"
+                       SIA_MSG="yes"
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define LOCKED_PASSWD_SUBSTR \"Nologin\"" >>confdefs.h
+
+               fi
+       fi
+       $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
+
+       $as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
+
+       $as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_READV_COMPARISON 1" >>confdefs.h
+
+       ;;
+
+*-*-nto-qnx*)
+       $as_echo "#define USE_PIPES 1" >>confdefs.h
+
+       $as_echo "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h
+
+
+$as_echo "#define MISSING_NFDBITS 1" >>confdefs.h
+
+
+$as_echo "#define MISSING_HOWMANY 1" >>confdefs.h
+
+
+$as_echo "#define MISSING_FD_MASK 1" >>confdefs.h
+
+       $as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
+
+       $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_SHADOW_EXPIRE 1" >>confdefs.h
+
+       enable_etc_default_login=no     # has incompatible /etc/default/login
+       case "$host" in
+       *-*-nto-qnx6*)
+               $as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
+
+               ;;
+       esac
+       ;;
+
+*-*-ultrix*)
+
+$as_echo "#define BROKEN_GETGROUPS 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_MMAP 1" >>confdefs.h
+
+       $as_echo "#define NEED_SETPGRP 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_SYS_SYSLOG_H 1" >>confdefs.h
+
+       ;;
+
+*-*-lynxos)
+        CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"
+       $as_echo "#define MISSING_HOWMANY 1" >>confdefs.h
+
+
+$as_echo "#define BROKEN_SETVBUF 1" >>confdefs.h
+
+        ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler and flags for sanity" >&5
+$as_echo_n "checking compiler and flags for sanity... " >&6; }
+if test "$cross_compiling" = yes; then :
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking compiler sanity" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking compiler sanity" >&2;}
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdio.h>
+int
+main ()
+{
+ exit(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               as_fn_error $? "*** compiler cannot create working executables, check config.log ***" "$LINENO" 5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+# Checks for libraries.
+ac_fn_c_check_func "$LINENO" "yp_match" "ac_cv_func_yp_match"
+if test "x$ac_cv_func_yp_match" = xyes; then :
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yp_match in -lnsl" >&5
+$as_echo_n "checking for yp_match in -lnsl... " >&6; }
+if ${ac_cv_lib_nsl_yp_match+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char yp_match ();
+int
+main ()
+{
+return yp_match ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nsl_yp_match=yes
+else
+  ac_cv_lib_nsl_yp_match=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_yp_match" >&5
+$as_echo "$ac_cv_lib_nsl_yp_match" >&6; }
+if test "x$ac_cv_lib_nsl_yp_match" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+  LIBS="-lnsl $LIBS"
+
+fi
+
+fi
+
+ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt"
+if test "x$ac_cv_func_setsockopt" = xyes; then :
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5
+$as_echo_n "checking for setsockopt in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_setsockopt+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setsockopt ();
+int
+main ()
+{
+return setsockopt ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_setsockopt=yes
+else
+  ac_cv_lib_socket_setsockopt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5
+$as_echo "$ac_cv_lib_socket_setsockopt" >&6; }
+if test "x$ac_cv_lib_socket_setsockopt" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+  LIBS="-lsocket $LIBS"
+
+fi
+
+fi
+
+
+for ac_func in dirname
+do :
+  ac_fn_c_check_func "$LINENO" "dirname" "ac_cv_func_dirname"
+if test "x$ac_cv_func_dirname" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DIRNAME 1
+_ACEOF
+ for ac_header in libgen.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default"
+if test "x$ac_cv_header_libgen_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBGEN_H 1
+_ACEOF
+
+fi
+
+done
+
+else
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dirname in -lgen" >&5
+$as_echo_n "checking for dirname in -lgen... " >&6; }
+if ${ac_cv_lib_gen_dirname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgen  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dirname ();
+int
+main ()
+{
+return dirname ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_gen_dirname=yes
+else
+  ac_cv_lib_gen_dirname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_dirname" >&5
+$as_echo "$ac_cv_lib_gen_dirname" >&6; }
+if test "x$ac_cv_lib_gen_dirname" = xyes; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken dirname" >&5
+$as_echo_n "checking for broken dirname... " >&6; }
+if ${ac_cv_have_broken_dirname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+                       save_LIBS="$LIBS"
+                       LIBS="$LIBS -lgen"
+                       if test "$cross_compiling" = yes; then :
+   ac_cv_have_broken_dirname="no"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <libgen.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+    char *s, buf[32];
+
+    strncpy(buf,"/etc", 32);
+    s = dirname(buf);
+    if (!s || strncmp(s, "/", 32) != 0) {
+       exit(1);
+    } else {
+       exit(0);
+    }
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+   ac_cv_have_broken_dirname="no"
+else
+   ac_cv_have_broken_dirname="yes"
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+                       LIBS="$save_LIBS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_broken_dirname" >&5
+$as_echo "$ac_cv_have_broken_dirname" >&6; }
+               if test "x$ac_cv_have_broken_dirname" = "xno" ; then
+                       LIBS="$LIBS -lgen"
+                       $as_echo "#define HAVE_DIRNAME 1" >>confdefs.h
+
+                       for ac_header in libgen.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default"
+if test "x$ac_cv_header_libgen_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBGEN_H 1
+_ACEOF
+
+fi
+
+done
+
+               fi
+
+fi
+
+
+fi
+done
+
+
+ac_fn_c_check_func "$LINENO" "getspnam" "ac_cv_func_getspnam"
+if test "x$ac_cv_func_getspnam" = xyes; then :
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getspnam in -lgen" >&5
+$as_echo_n "checking for getspnam in -lgen... " >&6; }
+if ${ac_cv_lib_gen_getspnam+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgen  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getspnam ();
+int
+main ()
+{
+return getspnam ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_gen_getspnam=yes
+else
+  ac_cv_lib_gen_getspnam=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_getspnam" >&5
+$as_echo "$ac_cv_lib_gen_getspnam" >&6; }
+if test "x$ac_cv_lib_gen_getspnam" = xyes; then :
+  LIBS="$LIBS -lgen"
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing basename" >&5
+$as_echo_n "checking for library containing basename... " >&6; }
+if ${ac_cv_search_basename+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char basename ();
+int
+main ()
+{
+return basename ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' gen; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_basename=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_basename+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_basename+:} false; then :
+
+else
+  ac_cv_search_basename=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_basename" >&5
+$as_echo "$ac_cv_search_basename" >&6; }
+ac_res=$ac_cv_search_basename
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_BASENAME 1" >>confdefs.h
+
+fi
+
+
+
+# Check whether --with-zlib was given.
+if test "${with_zlib+set}" = set; then :
+  withval=$with_zlib;  if test "x$withval" = "xno" ; then
+               as_fn_error $? "*** zlib is required ***" "$LINENO" 5
+         elif test "x$withval" != "xyes"; then
+               if test -d "$withval/lib"; then
+                       if test -n "${need_dash_r}"; then
+                               LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                       else
+                               LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                       fi
+               else
+                       if test -n "${need_dash_r}"; then
+                               LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+                       else
+                               LDFLAGS="-L${withval} ${LDFLAGS}"
+                       fi
+               fi
+               if test -d "$withval/include"; then
+                       CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+               else
+                       CPPFLAGS="-I${withval} ${CPPFLAGS}"
+               fi
+       fi
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_zlib_h" = xyes; then :
+
+else
+  as_fn_error $? "*** zlib.h missing - please install first or check config.log ***" "$LINENO" 5
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5
+$as_echo_n "checking for deflate in -lz... " >&6; }
+if ${ac_cv_lib_z_deflate+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char deflate ();
+int
+main ()
+{
+return deflate ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_z_deflate=yes
+else
+  ac_cv_lib_z_deflate=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5
+$as_echo "$ac_cv_lib_z_deflate" >&6; }
+if test "x$ac_cv_lib_z_deflate" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBZ 1
+_ACEOF
+
+  LIBS="-lz $LIBS"
+
+else
+
+               saved_CPPFLAGS="$CPPFLAGS"
+               saved_LDFLAGS="$LDFLAGS"
+               save_LIBS="$LIBS"
+                               if test -n "${need_dash_r}"; then
+                       LDFLAGS="-L/usr/local/lib -R/usr/local/lib ${saved_LDFLAGS}"
+               else
+                       LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}"
+               fi
+               CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}"
+               LIBS="$LIBS -lz"
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char deflate ();
+int
+main ()
+{
+return deflate ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  $as_echo "#define HAVE_LIBZ 1" >>confdefs.h
+
+else
+
+                               as_fn_error $? "*** zlib missing - please install first or check config.log ***" "$LINENO" 5
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+
+fi
+
+
+
+# Check whether --with-zlib-version-check was given.
+if test "${with_zlib_version_check+set}" = set; then :
+  withval=$with_zlib_version_check;   if test "x$withval" = "xno" ; then
+               zlib_check_nonfatal=1
+          fi
+
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for possibly buggy zlib" >&5
+$as_echo_n "checking for possibly buggy zlib... " >&6; }
+if test "$cross_compiling" = yes; then :
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking zlib version" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking zlib version" >&2;}
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <zlib.h>
+
+int
+main ()
+{
+
+       int a=0, b=0, c=0, d=0, n, v;
+       n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d);
+       if (n != 3 && n != 4)
+               exit(1);
+       v = a*1000000 + b*10000 + c*100 + d;
+       fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v);
+
+       /* 1.1.4 is OK */
+       if (a == 1 && b == 1 && c >= 4)
+               exit(0);
+
+       /* 1.2.3 and up are OK */
+       if (v >= 1020300)
+               exit(0);
+
+       exit(2);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+         if test -z "$zlib_check_nonfatal" ; then
+               as_fn_error $? "*** zlib too old - check config.log ***
+Your reported zlib version has known security problems.  It's possible your
+vendor has fixed these problems without changing the version number.  If you
+are sure this is the case, you can disable the check by running
+\"./configure --without-zlib-version-check\".
+If you are in doubt, upgrade zlib to version 1.2.3 or greater.
+See http://www.gzip.org/zlib/ for details." "$LINENO" 5
+         else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib version may have security problems" >&5
+$as_echo "$as_me: WARNING: zlib version may have security problems" >&2;}
+         fi
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp"
+if test "x$ac_cv_func_strcasecmp" = xyes; then :
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strcasecmp in -lresolv" >&5
+$as_echo_n "checking for strcasecmp in -lresolv... " >&6; }
+if ${ac_cv_lib_resolv_strcasecmp+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strcasecmp ();
+int
+main ()
+{
+return strcasecmp ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_resolv_strcasecmp=yes
+else
+  ac_cv_lib_resolv_strcasecmp=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_strcasecmp" >&5
+$as_echo "$ac_cv_lib_resolv_strcasecmp" >&6; }
+if test "x$ac_cv_lib_resolv_strcasecmp" = xyes; then :
+  LIBS="$LIBS -lresolv"
+fi
+
+
+fi
+
+for ac_func in utimes
+do :
+  ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes"
+if test "x$ac_cv_func_utimes" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_UTIMES 1
+_ACEOF
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utimes in -lc89" >&5
+$as_echo_n "checking for utimes in -lc89... " >&6; }
+if ${ac_cv_lib_c89_utimes+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc89  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char utimes ();
+int
+main ()
+{
+return utimes ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_c89_utimes=yes
+else
+  ac_cv_lib_c89_utimes=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c89_utimes" >&5
+$as_echo "$ac_cv_lib_c89_utimes" >&6; }
+if test "x$ac_cv_lib_c89_utimes" = xyes; then :
+  $as_echo "#define HAVE_UTIMES 1" >>confdefs.h
+
+                                       LIBS="$LIBS -lc89"
+fi
+
+
+fi
+done
+
+
+for ac_header in libutil.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libutil.h" "ac_cv_header_libutil_h" "$ac_includes_default"
+if test "x$ac_cv_header_libutil_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUTIL_H 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing login" >&5
+$as_echo_n "checking for library containing login... " >&6; }
+if ${ac_cv_search_login+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char login ();
+int
+main ()
+{
+return login ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' util bsd; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_login=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_login+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_login+:} false; then :
+
+else
+  ac_cv_search_login=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_login" >&5
+$as_echo "$ac_cv_search_login" >&6; }
+ac_res=$ac_cv_search_login
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_LOGIN 1" >>confdefs.h
+
+fi
+
+for ac_func in fmt_scaled logout updwtmp logwtmp
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+for ac_func in strftime
+do :
+  ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime"
+if test "x$ac_cv_func_strftime" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRFTIME 1
+_ACEOF
+
+else
+  # strftime is in -lintl on SCO UNIX.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5
+$as_echo_n "checking for strftime in -lintl... " >&6; }
+if ${ac_cv_lib_intl_strftime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lintl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strftime ();
+int
+main ()
+{
+return strftime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_intl_strftime=yes
+else
+  ac_cv_lib_intl_strftime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5
+$as_echo "$ac_cv_lib_intl_strftime" >&6; }
+if test "x$ac_cv_lib_intl_strftime" = xyes; then :
+  $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h
+
+LIBS="-lintl $LIBS"
+fi
+
+fi
+done
+
+
+# Check for ALTDIRFUNC glob() extension
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_ALTDIRFUNC support" >&5
+$as_echo_n "checking for GLOB_ALTDIRFUNC support... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+               #include <glob.h>
+               #ifdef GLOB_ALTDIRFUNC
+               FOUNDIT
+               #endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "FOUNDIT" >/dev/null 2>&1; then :
+
+
+$as_echo "#define GLOB_HAS_ALTDIRFUNC 1" >>confdefs.h
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+fi
+rm -f conftest*
+
+
+# Check for g.gl_matchc glob() extension
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gl_matchc field in glob_t" >&5
+$as_echo_n "checking for gl_matchc field in glob_t... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <glob.h>
+int
+main ()
+{
+ glob_t g; g.gl_matchc = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+
+$as_echo "#define GLOB_HAS_GL_MATCHC 1" >>confdefs.h
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Check for g.gl_statv glob() extension
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gl_statv and GLOB_KEEPSTAT extensions for glob" >&5
+$as_echo_n "checking for gl_statv and GLOB_KEEPSTAT extensions for glob... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <glob.h>
+int
+main ()
+{
+
+#ifndef GLOB_KEEPSTAT
+#error "glob does not support GLOB_KEEPSTAT extension"
+#endif
+glob_t g;
+g.gl_statv = NULL;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+
+$as_echo "#define GLOB_HAS_GL_STATV 1" >>confdefs.h
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ac_fn_c_check_decl "$LINENO" "GLOB_NOMATCH" "ac_cv_have_decl_GLOB_NOMATCH" "#include <glob.h>
+"
+if test "x$ac_cv_have_decl_GLOB_NOMATCH" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_GLOB_NOMATCH $ac_have_decl
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct dirent allocates space for d_name" >&5
+$as_echo_n "checking whether struct dirent allocates space for d_name... " >&6; }
+if test "$cross_compiling" = yes; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5
+$as_echo "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;}
+               $as_echo "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h
+
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <dirent.h>
+int
+main ()
+{
+
+       struct dirent d;
+       exit(sizeof(d.d_name)<=sizeof(char));
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for /proc/pid/fd directory" >&5
+$as_echo_n "checking for /proc/pid/fd directory... " >&6; }
+if test -d "/proc/$$/fd" ; then
+
+$as_echo "#define HAVE_PROC_PID 1" >>confdefs.h
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+# Check whether user wants S/Key support
+SKEY_MSG="no"
+
+# Check whether --with-skey was given.
+if test "${with_skey+set}" = set; then :
+  withval=$with_skey;
+               if test "x$withval" != "xno" ; then
+
+                       if test "x$withval" != "xyes" ; then
+                               CPPFLAGS="$CPPFLAGS -I${withval}/include"
+                               LDFLAGS="$LDFLAGS -L${withval}/lib"
+                       fi
+
+
+$as_echo "#define SKEY 1" >>confdefs.h
+
+                       LIBS="-lskey $LIBS"
+                       SKEY_MSG="yes"
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for s/key support" >&5
+$as_echo_n "checking for s/key support... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <skey.h>
+
+int
+main ()
+{
+
+       char *ff = skey_keyinfo(""); ff="";
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                                       as_fn_error $? "** Incomplete or missing s/key libraries." "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if skeychallenge takes 4 arguments" >&5
+$as_echo_n "checking if skeychallenge takes 4 arguments... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <skey.h>
+
+int
+main ()
+{
+
+       (void)skeychallenge(NULL,"name","",0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define SKEYCHALLENGE_4ARG 1" >>confdefs.h
+
+else
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               fi
+
+
+fi
+
+
+# Check whether user wants TCP wrappers support
+TCPW_MSG="no"
+
+# Check whether --with-tcp-wrappers was given.
+if test "${with_tcp_wrappers+set}" = set; then :
+  withval=$with_tcp_wrappers;
+               if test "x$withval" != "xno" ; then
+                       saved_LIBS="$LIBS"
+                       saved_LDFLAGS="$LDFLAGS"
+                       saved_CPPFLAGS="$CPPFLAGS"
+                       if test -n "${withval}" && \
+                           test "x${withval}" != "xyes"; then
+                               if test -d "${withval}/lib"; then
+                                       if test -n "${need_dash_r}"; then
+                                               LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                                       else
+                                               LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                                       fi
+                               else
+                                       if test -n "${need_dash_r}"; then
+                                               LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+                                       else
+                                               LDFLAGS="-L${withval} ${LDFLAGS}"
+                                       fi
+                               fi
+                               if test -d "${withval}/include"; then
+                                       CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+                               else
+                                       CPPFLAGS="-I${withval} ${CPPFLAGS}"
+                               fi
+                       fi
+                       LIBS="-lwrap $LIBS"
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libwrap" >&5
+$as_echo_n "checking for libwrap... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <tcpd.h>
+int deny_severity = 0, allow_severity = 0;
+
+int
+main ()
+{
+
+       hosts_access(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define LIBWRAP 1" >>confdefs.h
+
+                                       SSHDLIBS="$SSHDLIBS -lwrap"
+                                       TCPW_MSG="yes"
+
+else
+
+                                       as_fn_error $? "*** libwrap missing" "$LINENO" 5
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+                       LIBS="$saved_LIBS"
+               fi
+
+
+fi
+
+
+# Check whether user wants libedit support
+LIBEDIT_MSG="no"
+
+# Check whether --with-libedit was given.
+if test "${with_libedit+set}" = set; then :
+  withval=$with_libedit;  if test "x$withval" != "xno" ; then
+               if test "x$withval" = "xyes" ; then
+                       # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKGCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKGCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_PKGCONFIG" && ac_cv_path_PKGCONFIG="no"
+  ;;
+esac
+fi
+PKGCONFIG=$ac_cv_path_PKGCONFIG
+if test -n "$PKGCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
+$as_echo "$PKGCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+                       if test "x$PKGCONFIG" != "xno"; then
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about libedit" >&5
+$as_echo_n "checking if $PKGCONFIG knows about libedit... " >&6; }
+                               if "$PKGCONFIG" libedit; then
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                                       use_pkgconfig_for_libedit=yes
+                               else
+                                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                               fi
+                       fi
+               else
+                       CPPFLAGS="$CPPFLAGS -I${withval}/include"
+                       if test -n "${need_dash_r}"; then
+                               LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                       else
+                               LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                       fi
+               fi
+               if test "x$use_pkgconfig_for_libedit" = "xyes"; then
+                       LIBEDIT=`$PKGCONFIG --libs-only-l libedit`
+                       CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`"
+               else
+                       LIBEDIT="-ledit -lcurses"
+               fi
+               OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'`
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for el_init in -ledit" >&5
+$as_echo_n "checking for el_init in -ledit... " >&6; }
+if ${ac_cv_lib_edit_el_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ledit  $OTHERLIBS
+                $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char el_init ();
+int
+main ()
+{
+return el_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_edit_el_init=yes
+else
+  ac_cv_lib_edit_el_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_el_init" >&5
+$as_echo "$ac_cv_lib_edit_el_init" >&6; }
+if test "x$ac_cv_lib_edit_el_init" = xyes; then :
+
+$as_echo "#define USE_LIBEDIT 1" >>confdefs.h
+
+                         LIBEDIT_MSG="yes"
+
+
+else
+   as_fn_error $? "libedit not found" "$LINENO" 5
+fi
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libedit version is compatible" >&5
+$as_echo_n "checking if libedit version is compatible... " >&6; }
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <histedit.h>
+int
+main ()
+{
+
+       int i = H_SETSIZE;
+       el_init("", NULL, NULL, NULL);
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                     as_fn_error $? "libedit version is not compatible" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       fi
+
+fi
+
+
+AUDIT_MODULE=none
+
+# Check whether --with-audit was given.
+if test "${with_audit+set}" = set; then :
+  withval=$with_audit;
+         { $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported audit module" >&5
+$as_echo_n "checking for supported audit module... " >&6; }
+         case "$withval" in
+         bsm)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: bsm" >&5
+$as_echo "bsm" >&6; }
+               AUDIT_MODULE=bsm
+                               for ac_header in bsm/audit.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "bsm/audit.h" "ac_cv_header_bsm_audit_h" "
+#ifdef HAVE_TIME_H
+# include <time.h>
+#endif
+
+
+"
+if test "x$ac_cv_header_bsm_audit_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_BSM_AUDIT_H 1
+_ACEOF
+
+else
+  as_fn_error $? "BSM enabled and bsm/audit.h not found" "$LINENO" 5
+fi
+
+done
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaudit in -lbsm" >&5
+$as_echo_n "checking for getaudit in -lbsm... " >&6; }
+if ${ac_cv_lib_bsm_getaudit+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getaudit ();
+int
+main ()
+{
+return getaudit ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_bsm_getaudit=yes
+else
+  ac_cv_lib_bsm_getaudit=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsm_getaudit" >&5
+$as_echo "$ac_cv_lib_bsm_getaudit" >&6; }
+if test "x$ac_cv_lib_bsm_getaudit" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBBSM 1
+_ACEOF
+
+  LIBS="-lbsm $LIBS"
+
+else
+  as_fn_error $? "BSM enabled and required library not found" "$LINENO" 5
+fi
+
+               for ac_func in getaudit
+do :
+  ac_fn_c_check_func "$LINENO" "getaudit" "ac_cv_func_getaudit"
+if test "x$ac_cv_func_getaudit" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETAUDIT 1
+_ACEOF
+
+else
+  as_fn_error $? "BSM enabled and required function not found" "$LINENO" 5
+fi
+done
+
+               # These are optional
+               for ac_func in getaudit_addr aug_get_machine
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+$as_echo "#define USE_BSM_AUDIT 1" >>confdefs.h
+
+               ;;
+         linux)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: linux" >&5
+$as_echo "linux" >&6; }
+               AUDIT_MODULE=linux
+                               for ac_header in libaudit.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libaudit.h" "ac_cv_header_libaudit_h" "$ac_includes_default"
+if test "x$ac_cv_header_libaudit_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBAUDIT_H 1
+_ACEOF
+
+fi
+
+done
+
+               SSHDLIBS="$SSHDLIBS -laudit"
+
+$as_echo "#define USE_LINUX_AUDIT 1" >>confdefs.h
+
+               ;;
+         debug)
+               AUDIT_MODULE=debug
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
+$as_echo "debug" >&6; }
+
+$as_echo "#define SSH_AUDIT_EVENTS 1" >>confdefs.h
+
+               ;;
+         no)
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               ;;
+         *)
+               as_fn_error $? "Unknown audit module $withval" "$LINENO" 5
+               ;;
+       esac
+
+fi
+
+
+for ac_func in  \
+       arc4random \
+       arc4random_buf \
+       arc4random_uniform \
+       asprintf \
+       b64_ntop \
+       __b64_ntop \
+       b64_pton \
+       __b64_pton \
+       bcopy \
+       bindresvport_sa \
+       clock \
+       closefrom \
+       dirfd \
+       fchmod \
+       fchown \
+       freeaddrinfo \
+       fstatvfs \
+       futimes \
+       getaddrinfo \
+       getcwd \
+       getgrouplist \
+       getnameinfo \
+       getopt \
+       getpeereid \
+       getpeerucred \
+       _getpty \
+       getrlimit \
+       getttyent \
+       glob \
+       group_from_gid \
+       inet_aton \
+       inet_ntoa \
+       inet_ntop \
+       innetgr \
+       login_getcapbool \
+       md5_crypt \
+       memmove \
+       mkdtemp \
+       mmap \
+       ngetaddrinfo \
+       nsleep \
+       ogetaddrinfo \
+       openlog_r \
+       openpty \
+       poll \
+       prctl \
+       pstat \
+       readpassphrase \
+       realpath \
+       recvmsg \
+       rresvport_af \
+       sendmsg \
+       setdtablesize \
+       setegid \
+       setenv \
+       seteuid \
+       setgroupent \
+       setgroups \
+       setlogin \
+       setpassent\
+       setpcred \
+       setproctitle \
+       setregid \
+       setreuid \
+       setrlimit \
+       setsid \
+       setvbuf \
+       sigaction \
+       sigvec \
+       snprintf \
+       socketpair \
+       statfs \
+       statvfs \
+       strdup \
+       strerror \
+       strlcat \
+       strlcpy \
+       strmode \
+       strnvis \
+       strptime \
+       strtonum \
+       strtoll \
+       strtoul \
+       swap32 \
+       sysconf \
+       tcgetpgrp \
+       timingsafe_bcmp \
+       truncate \
+       unsetenv \
+       updwtmpx \
+       user_from_uid \
+       vasprintf \
+       vhangup \
+       vsnprintf \
+       waitpid \
+
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <ctype.h>
+int
+main ()
+{
+ return (isblank('a'));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_ISBLANK 1" >>confdefs.h
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+# PKCS#11 support requires dlopen() and co
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dlopen+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define ENABLE_PKCS11 /**/" >>confdefs.h
+
+
+fi
+
+
+# IRIX has a const char return value for gai_strerror()
+for ac_func in gai_strerror
+do :
+  ac_fn_c_check_func "$LINENO" "gai_strerror" "ac_cv_func_gai_strerror"
+if test "x$ac_cv_func_gai_strerror" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GAI_STRERROR 1
+_ACEOF
+
+       $as_echo "#define HAVE_GAI_STRERROR 1" >>confdefs.h
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+const char *gai_strerror(int);
+
+int
+main ()
+{
+
+       char *str;
+       str = gai_strerror(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+
+$as_echo "#define HAVE_CONST_GAI_STRERROR_PROTO 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep" >&5
+$as_echo_n "checking for library containing nanosleep... " >&6; }
+if ${ac_cv_search_nanosleep+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nanosleep ();
+int
+main ()
+{
+return nanosleep ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' rt posix4; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_nanosleep=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_nanosleep+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_nanosleep+:} false; then :
+
+else
+  ac_cv_search_nanosleep=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep" >&5
+$as_echo "$ac_cv_search_nanosleep" >&6; }
+ac_res=$ac_cv_search_nanosleep
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_NANOSLEEP 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_decl "$LINENO" "getrusage" "ac_cv_have_decl_getrusage" "$ac_includes_default"
+if test "x$ac_cv_have_decl_getrusage" = xyes; then :
+  for ac_func in getrusage
+do :
+  ac_fn_c_check_func "$LINENO" "getrusage" "ac_cv_func_getrusage"
+if test "x$ac_cv_func_getrusage" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETRUSAGE 1
+_ACEOF
+
+fi
+done
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "strsep" "ac_cv_have_decl_strsep" "
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl_strsep" = xyes; then :
+  for ac_func in strsep
+do :
+  ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep"
+if test "x$ac_cv_func_strsep" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRSEP 1
+_ACEOF
+
+fi
+done
+
+fi
+
+
+ac_fn_c_check_decl "$LINENO" "tcsendbreak" "ac_cv_have_decl_tcsendbreak" "#include <termios.h>
+
+"
+if test "x$ac_cv_have_decl_tcsendbreak" = xyes; then :
+  $as_echo "#define HAVE_TCSENDBREAK 1" >>confdefs.h
+
+else
+  for ac_func in tcsendbreak
+do :
+  ac_fn_c_check_func "$LINENO" "tcsendbreak" "ac_cv_func_tcsendbreak"
+if test "x$ac_cv_func_tcsendbreak" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_TCSENDBREAK 1
+_ACEOF
+
+fi
+done
+
+fi
+
+
+ac_fn_c_check_decl "$LINENO" "h_errno" "ac_cv_have_decl_h_errno" "#include <netdb.h>
+"
+if test "x$ac_cv_have_decl_h_errno" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_H_ERRNO $ac_have_decl
+_ACEOF
+
+
+ac_fn_c_check_decl "$LINENO" "SHUT_RD" "ac_cv_have_decl_SHUT_RD" "
+#include <sys/types.h>
+#include <sys/socket.h>
+
+"
+if test "x$ac_cv_have_decl_SHUT_RD" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SHUT_RD $ac_have_decl
+_ACEOF
+
+
+ac_fn_c_check_decl "$LINENO" "O_NONBLOCK" "ac_cv_have_decl_O_NONBLOCK" "
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl_O_NONBLOCK" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_O_NONBLOCK $ac_have_decl
+_ACEOF
+
+
+ac_fn_c_check_decl "$LINENO" "writev" "ac_cv_have_decl_writev" "
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+"
+if test "x$ac_cv_have_decl_writev" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_WRITEV $ac_have_decl
+_ACEOF
+
+
+ac_fn_c_check_decl "$LINENO" "MAXSYMLINKS" "ac_cv_have_decl_MAXSYMLINKS" "
+#include <sys/param.h>
+
+"
+if test "x$ac_cv_have_decl_MAXSYMLINKS" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_MAXSYMLINKS $ac_have_decl
+_ACEOF
+
+
+ac_fn_c_check_decl "$LINENO" "offsetof" "ac_cv_have_decl_offsetof" "
+#include <stddef.h>
+
+"
+if test "x$ac_cv_have_decl_offsetof" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_OFFSETOF $ac_have_decl
+_ACEOF
+
+
+for ac_func in setresuid
+do :
+  ac_fn_c_check_func "$LINENO" "setresuid" "ac_cv_func_setresuid"
+if test "x$ac_cv_func_setresuid" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SETRESUID 1
+_ACEOF
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if setresuid seems to work" >&5
+$as_echo_n "checking if setresuid seems to work... " >&6; }
+       if test "$cross_compiling" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking setresuid" >&2;}
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <errno.h>
+
+int
+main ()
+{
+
+       errno=0;
+       setresuid(0,0,0);
+       if (errno==ENOSYS)
+               exit(1);
+       else
+               exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+$as_echo "#define BROKEN_SETRESUID 1" >>confdefs.h
+
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5
+$as_echo "not implemented" >&6; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+done
+
+
+for ac_func in setresgid
+do :
+  ac_fn_c_check_func "$LINENO" "setresgid" "ac_cv_func_setresgid"
+if test "x$ac_cv_func_setresgid" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SETRESGID 1
+_ACEOF
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if setresgid seems to work" >&5
+$as_echo_n "checking if setresgid seems to work... " >&6; }
+       if test "$cross_compiling" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking setresuid" >&2;}
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <errno.h>
+
+int
+main ()
+{
+
+       errno=0;
+       setresgid(0,0,0);
+       if (errno==ENOSYS)
+               exit(1);
+       else
+               exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+$as_echo "#define BROKEN_SETRESGID 1" >>confdefs.h
+
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5
+$as_echo "not implemented" >&6; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+done
+
+
+for ac_func in gettimeofday time
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in endutent getutent getutid getutline pututline setutent
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in utmpname
+do :
+  ac_fn_c_check_func "$LINENO" "utmpname" "ac_cv_func_utmpname"
+if test "x$ac_cv_func_utmpname" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_UTMPNAME 1
+_ACEOF
+
+fi
+done
+
+for ac_func in endutxent getutxent getutxid getutxline getutxuser pututxline
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in setutxdb setutxent utmpxname
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in getlastlogxbyname
+do :
+  ac_fn_c_check_func "$LINENO" "getlastlogxbyname" "ac_cv_func_getlastlogxbyname"
+if test "x$ac_cv_func_getlastlogxbyname" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETLASTLOGXBYNAME 1
+_ACEOF
+
+fi
+done
+
+
+ac_fn_c_check_func "$LINENO" "daemon" "ac_cv_func_daemon"
+if test "x$ac_cv_func_daemon" = xyes; then :
+
+$as_echo "#define HAVE_DAEMON 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for daemon in -lbsd" >&5
+$as_echo_n "checking for daemon in -lbsd... " >&6; }
+if ${ac_cv_lib_bsd_daemon+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsd  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char daemon ();
+int
+main ()
+{
+return daemon ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_bsd_daemon=yes
+else
+  ac_cv_lib_bsd_daemon=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_daemon" >&5
+$as_echo "$ac_cv_lib_bsd_daemon" >&6; }
+if test "x$ac_cv_lib_bsd_daemon" = xyes; then :
+  LIBS="$LIBS -lbsd"; $as_echo "#define HAVE_DAEMON 1" >>confdefs.h
+
+fi
+
+
+fi
+
+
+ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize"
+if test "x$ac_cv_func_getpagesize" = xyes; then :
+
+$as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpagesize in -lucb" >&5
+$as_echo_n "checking for getpagesize in -lucb... " >&6; }
+if ${ac_cv_lib_ucb_getpagesize+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lucb  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getpagesize ();
+int
+main ()
+{
+return getpagesize ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ucb_getpagesize=yes
+else
+  ac_cv_lib_ucb_getpagesize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ucb_getpagesize" >&5
+$as_echo "$ac_cv_lib_ucb_getpagesize" >&6; }
+if test "x$ac_cv_lib_ucb_getpagesize" = xyes; then :
+  LIBS="$LIBS -lucb"; $as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h
+
+fi
+
+
+fi
+
+
+# Check for broken snprintf
+if test "x$ac_cv_func_snprintf" = "xyes" ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf correctly terminates long strings" >&5
+$as_echo_n "checking whether snprintf correctly terminates long strings... " >&6; }
+       if test "$cross_compiling" = yes; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5
+$as_echo "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;}
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdio.h>
+int
+main ()
+{
+
+       char b[5];
+       snprintf(b,5,"123456789");
+       exit(b[4]!='\0');
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&5
+$as_echo "$as_me: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&2;}
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+# If we don't have a working asprintf, then we strongly depend on vsnprintf
+# returning the right thing on overflow: the number of characters it tried to
+# create (as per SUSv3)
+if test "x$ac_cv_func_asprintf" != "xyes" && \
+   test "x$ac_cv_func_vsnprintf" = "xyes" ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5
+$as_echo_n "checking whether vsnprintf returns correct values on overflow... " >&6; }
+       if test "$cross_compiling" = yes; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working vsnprintf()" >&5
+$as_echo "$as_me: WARNING: cross compiling: Assuming working vsnprintf()" >&2;}
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+int x_snprintf(char *str,size_t count,const char *fmt,...)
+{
+       size_t ret; va_list ap;
+       va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap);
+       return ret;
+}
+
+int
+main ()
+{
+
+       char x[1];
+       exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&5
+$as_echo "$as_me: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&2;}
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+# On systems where [v]snprintf is broken, but is declared in stdio,
+# check that the fmt argument is const char * or just char *.
+# This is only useful for when BROKEN_SNPRINTF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf can declare const char *fmt" >&5
+$as_echo_n "checking whether snprintf can declare const char *fmt... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+int snprintf(char *a, size_t b, const char *c, ...) { return 0; }
+
+int
+main ()
+{
+
+       snprintf(0, 0, 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define SNPRINTF_CONST const" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    $as_echo "#define SNPRINTF_CONST /* not const */" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# Check for missing getpeereid (or equiv) support
+NO_PEERCHECK=""
+if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether system supports SO_PEERCRED getsockopt" >&5
+$as_echo_n "checking whether system supports SO_PEERCRED getsockopt... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+int
+main ()
+{
+int i = SO_PEERCRED;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SO_PEERCRED 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               NO_PEERCHECK=1
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "x$ac_cv_func_mkdtemp" = "xyes" ; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for (overly) strict mkstemp" >&5
+$as_echo_n "checking for (overly) strict mkstemp... " >&6; }
+if test "$cross_compiling" = yes; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+               $as_echo "#define HAVE_STRICT_MKSTEMP 1" >>confdefs.h
+
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+
+int
+main ()
+{
+
+       char template[]="conftest.mkstemp-test";
+       if (mkstemp(template) == -1)
+               exit(1);
+       unlink(template);
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_STRICT_MKSTEMP 1" >>confdefs.h
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+if test ! -z "$check_for_openpty_ctty_bug"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if openpty correctly handles controlling tty" >&5
+$as_echo_n "checking if openpty correctly handles controlling tty... " >&6; }
+       if test "$cross_compiling" = yes; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5
+$as_echo "cross-compiling, assuming yes" >&6; }
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int
+main ()
+{
+
+       pid_t pid;
+       int fd, ptyfd, ttyfd, status;
+
+       pid = fork();
+       if (pid < 0) {          /* failed */
+               exit(1);
+       } else if (pid > 0) {   /* parent */
+               waitpid(pid, &status, 0);
+               if (WIFEXITED(status))
+                       exit(WEXITSTATUS(status));
+               else
+                       exit(2);
+       } else {                /* child */
+               close(0); close(1); close(2);
+               setsid();
+               openpty(&ptyfd, &ttyfd, NULL, NULL, NULL);
+               fd = open("/dev/tty", O_RDWR | O_NOCTTY);
+               if (fd >= 0)
+                       exit(3);        /* Acquired ctty: broken */
+               else
+                       exit(0);        /* Did not acquire ctty: OK */
+       }
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                       $as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
+    test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5
+$as_echo_n "checking if getaddrinfo seems to work... " >&6; }
+       if test "$cross_compiling" = yes; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5
+$as_echo "cross-compiling, assuming yes" >&6; }
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#define TEST_PORT "2222"
+
+int
+main ()
+{
+
+       int err, sock;
+       struct addrinfo *gai_ai, *ai, hints;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = AI_PASSIVE;
+
+       err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
+       if (err != 0) {
+               fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
+               exit(1);
+       }
+
+       for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET6)
+                       continue;
+
+               err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
+                   sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV);
+
+               if (err != 0) {
+                       if (err == EAI_SYSTEM)
+                               perror("getnameinfo EAI_SYSTEM");
+                       else
+                               fprintf(stderr, "getnameinfo failed: %s\n",
+                                   gai_strerror(err));
+                       exit(2);
+               }
+
+               sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+               if (sock < 0)
+                       perror("socket");
+               if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       if (errno == EBADF)
+                               exit(3);
+               }
+       }
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                       $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
+    test "x$check_for_aix_broken_getaddrinfo" = "x1"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5
+$as_echo_n "checking if getaddrinfo seems to work... " >&6; }
+       if test "$cross_compiling" = yes; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming no" >&5
+$as_echo "cross-compiling, assuming no" >&6; }
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#define TEST_PORT "2222"
+
+int
+main ()
+{
+
+       int err, sock;
+       struct addrinfo *gai_ai, *ai, hints;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = AI_PASSIVE;
+
+       err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
+       if (err != 0) {
+               fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
+               exit(1);
+       }
+
+       for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                       continue;
+
+               err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
+                   sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV);
+
+               if (ai->ai_family == AF_INET && err != 0) {
+                       perror("getnameinfo");
+                       exit(2);
+               }
+       }
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define AIX_GETNAMEINFO_HACK 1" >>confdefs.h
+
+
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                       $as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+if test "x$check_for_conflicting_getspnam" = "x1"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for conflicting getspnam in shadow.h" >&5
+$as_echo_n "checking for conflicting getspnam in shadow.h... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <shadow.h>
+int
+main ()
+{
+ exit(0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define GETSPNAM_CONFLICTING_DEFS 1" >>confdefs.h
+
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getpgrp requires zero arguments" >&5
+$as_echo_n "checking whether getpgrp requires zero arguments... " >&6; }
+if ${ac_cv_func_getpgrp_void+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # Use it with a single arg.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+getpgrp (0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_func_getpgrp_void=no
+else
+  ac_cv_func_getpgrp_void=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getpgrp_void" >&5
+$as_echo "$ac_cv_func_getpgrp_void" >&6; }
+if test $ac_cv_func_getpgrp_void = yes; then
+
+$as_echo "#define GETPGRP_VOID 1" >>confdefs.h
+
+fi
+
+
+# Search for OpenSSL
+saved_CPPFLAGS="$CPPFLAGS"
+saved_LDFLAGS="$LDFLAGS"
+
+# Check whether --with-ssl-dir was given.
+if test "${with_ssl_dir+set}" = set; then :
+  withval=$with_ssl_dir;
+               if test "x$withval" != "xno" ; then
+                       case "$withval" in
+                               # Relative paths
+                               ./*|../*)       withval="`pwd`/$withval"
+                       esac
+                       if test -d "$withval/lib"; then
+                               if test -n "${need_dash_r}"; then
+                                       LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                               else
+                                       LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                               fi
+                       elif test -d "$withval/lib64"; then
+                               if test -n "${need_dash_r}"; then
+                                       LDFLAGS="-L${withval}/lib64 -R${withval}/lib64 ${LDFLAGS}"
+                               else
+                                       LDFLAGS="-L${withval}/lib64 ${LDFLAGS}"
+                               fi
+                       else
+                               if test -n "${need_dash_r}"; then
+                                       LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+                               else
+                                       LDFLAGS="-L${withval} ${LDFLAGS}"
+                               fi
+                       fi
+                       if test -d "$withval/include"; then
+                               CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+                       else
+                               CPPFLAGS="-I${withval} ${CPPFLAGS}"
+                       fi
+               fi
+
+
+fi
+
+LIBS="-lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char RAND_add ();
+int
+main ()
+{
+return RAND_add ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
+
+else
+
+                               if test -n "${need_dash_r}"; then
+                       LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}"
+               else
+                       LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}"
+               fi
+               CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}"
+               ac_fn_c_check_header_mongrel "$LINENO" "openssl/opensslv.h" "ac_cv_header_openssl_opensslv_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_opensslv_h" = xyes; then :
+
+else
+  as_fn_error $? "*** OpenSSL headers missing - please install first or check config.log ***" "$LINENO" 5
+fi
+
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char RAND_add ();
+int
+main ()
+{
+return RAND_add ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  $as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
+
+else
+
+                               as_fn_error $? "*** Can't find recent OpenSSL libcrypto (see config.log for details) ***" "$LINENO" 5
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+# Determine OpenSSL header version
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL header version" >&5
+$as_echo_n "checking OpenSSL header version... " >&6; }
+if test "$cross_compiling" = yes; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/opensslv.h>
+#define DATA "conftest.sslincver"
+
+int
+main ()
+{
+
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+       if ((rc = fprintf(fd ,"%x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0)
+               exit(1);
+
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+               ssl_header_ver=`cat conftest.sslincver`
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_header_ver" >&5
+$as_echo "$ssl_header_ver" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+               as_fn_error $? "OpenSSL version header not found." "$LINENO" 5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+# Determine OpenSSL library version
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL library version" >&5
+$as_echo_n "checking OpenSSL library version... " >&6; }
+if test "$cross_compiling" = yes; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
+#define DATA "conftest.ssllibver"
+
+int
+main ()
+{
+
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+       if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0)
+               exit(1);
+
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+               ssl_library_ver=`cat conftest.ssllibver`
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5
+$as_echo "$ssl_library_ver" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+               as_fn_error $? "OpenSSL library not found." "$LINENO" 5
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+
+# Check whether --with-openssl-header-check was given.
+if test "${with_openssl_header_check+set}" = set; then :
+  withval=$with_openssl_header_check;   if test "x$withval" = "xno" ; then
+               openssl_check_nonfatal=1
+          fi
+
+
+fi
+
+
+# Sanity check OpenSSL headers
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's headers match the library" >&5
+$as_echo_n "checking whether OpenSSL's headers match the library... " >&6; }
+if test "$cross_compiling" = yes; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <string.h>
+#include <openssl/opensslv.h>
+
+int
+main ()
+{
+
+       exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               if test "x$openssl_check_nonfatal" = "x"; then
+                       as_fn_error $? "Your OpenSSL headers do not match your
+library. Check config.log for details.
+If you are sure your installation is consistent, you can disable the check
+by running \"./configure --without-openssl-header-check\".
+Also see contrib/findssl.sh for help identifying header/library mismatches.
+" "$LINENO" 5
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Your OpenSSL headers do not match your
+library. Check config.log for details.
+Also see contrib/findssl.sh for help identifying header/library mismatches." >&5
+$as_echo "$as_me: WARNING: Your OpenSSL headers do not match your
+library. Check config.log for details.
+Also see contrib/findssl.sh for help identifying header/library mismatches." >&2;}
+               fi
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL functions will link" >&5
+$as_echo_n "checking if programs using OpenSSL functions will link... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <openssl/evp.h>
+int
+main ()
+{
+ SSLeay_add_all_algorithms();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               saved_LIBS="$LIBS"
+               LIBS="$LIBS -ldl"
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL need -ldl" >&5
+$as_echo_n "checking if programs using OpenSSL need -ldl... " >&6; }
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <openssl/evp.h>
+int
+main ()
+{
+ SSLeay_add_all_algorithms();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                               LIBS="$saved_LIBS"
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+for ac_func in RSA_generate_key_ex DSA_generate_parameters_ex BN_is_prime_ex RSA_get_default_method
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+# Check whether --with-ssl-engine was given.
+if test "${with_ssl_engine+set}" = set; then :
+  withval=$with_ssl_engine;  if test "x$withval" != "xno" ; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL ENGINE support" >&5
+$as_echo_n "checking for OpenSSL ENGINE support... " >&6; }
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <openssl/engine.h>
+
+int
+main ()
+{
+
+       ENGINE_load_builtin_engines();
+       ENGINE_register_all_complete();
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define USE_OPENSSL_ENGINE 1" >>confdefs.h
+
+
+else
+   as_fn_error $? "OpenSSL ENGINE support not found" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+         fi
+
+fi
+
+
+# Check for OpenSSL without EVP_aes_{192,256}_cbc
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has crippled AES support" >&5
+$as_echo_n "checking whether OpenSSL has crippled AES support... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <string.h>
+#include <openssl/evp.h>
+
+int
+main ()
+{
+
+       exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define OPENSSL_LOBOTOMISED_AES 1" >>confdefs.h
+
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if EVP_DigestUpdate returns an int" >&5
+$as_echo_n "checking if EVP_DigestUpdate returns an int... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <string.h>
+#include <openssl/evp.h>
+
+int
+main ()
+{
+
+       if(EVP_DigestUpdate(NULL, NULL,0))
+               exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define OPENSSL_EVP_DIGESTUPDATE_VOID 1" >>confdefs.h
+
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+# Some systems want crypt() from libcrypt, *not* the version in OpenSSL,
+# because the system crypt() is more featureful.
+if test "x$check_for_libcrypt_before" = "x1"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
+$as_echo_n "checking for crypt in -lcrypt... " >&6; }
+if ${ac_cv_lib_crypt_crypt+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char crypt ();
+int
+main ()
+{
+return crypt ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypt_crypt=yes
+else
+  ac_cv_lib_crypt_crypt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5
+$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
+if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPT 1
+_ACEOF
+
+  LIBS="-lcrypt $LIBS"
+
+fi
+
+fi
+
+# Some Linux systems (Slackware) need crypt() from libcrypt, *not* the
+# version in OpenSSL.
+if test "x$check_for_libcrypt_later" = "x1"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
+$as_echo_n "checking for crypt in -lcrypt... " >&6; }
+if ${ac_cv_lib_crypt_crypt+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char crypt ();
+int
+main ()
+{
+return crypt ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypt_crypt=yes
+else
+  ac_cv_lib_crypt_crypt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5
+$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
+if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
+  LIBS="$LIBS -lcrypt"
+fi
+
+fi
+
+# Search for SHA256 support in libc and/or OpenSSL
+for ac_func in SHA256_Update EVP_sha256
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ TEST_SSH_SHA256=yes
+else
+  TEST_SSH_SHA256=no
+fi
+done
+
+
+
+# Check complete ECC support in OpenSSL
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has complete ECC support" >&5
+$as_echo_n "checking whether OpenSSL has complete ECC support... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
+# error "OpenSSL < 0.9.8g has unreliable ECC code"
+#endif
+
+int
+main ()
+{
+
+       EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
+       const EVP_MD *m = EVP_sha512(); /* We need this too */
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define OPENSSL_HAS_ECC 1" >>confdefs.h
+
+               TEST_SSH_ECC=yes
+               COMMENT_OUT_ECC=""
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               TEST_SSH_ECC=no
+               COMMENT_OUT_ECC="#no ecc#"
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+
+
+saved_LIBS="$LIBS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5
+$as_echo_n "checking for ia_openinfo in -liaf... " >&6; }
+if ${ac_cv_lib_iaf_ia_openinfo+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-liaf  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ia_openinfo ();
+int
+main ()
+{
+return ia_openinfo ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_iaf_ia_openinfo=yes
+else
+  ac_cv_lib_iaf_ia_openinfo=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iaf_ia_openinfo" >&5
+$as_echo "$ac_cv_lib_iaf_ia_openinfo" >&6; }
+if test "x$ac_cv_lib_iaf_ia_openinfo" = xyes; then :
+
+       LIBS="$LIBS -liaf"
+       for ac_func in set_id
+do :
+  ac_fn_c_check_func "$LINENO" "set_id" "ac_cv_func_set_id"
+if test "x$ac_cv_func_set_id" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SET_ID 1
+_ACEOF
+ SSHDLIBS="$SSHDLIBS -liaf"
+
+$as_echo "#define HAVE_LIBIAF 1" >>confdefs.h
+
+
+fi
+done
+
+
+fi
+
+LIBS="$saved_LIBS"
+
+### Configure cryptographic random number support
+
+# Check wheter OpenSSL seeds itself
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's PRNG is internally seeded" >&5
+$as_echo_n "checking whether OpenSSL's PRNG is internally seeded... " >&6; }
+if test "$cross_compiling" = yes; then :
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
+$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
+               # This is safe, since we will fatal() at runtime if
+               # OpenSSL is not seeded correctly.
+               OPENSSL_SEEDS_ITSELF=yes
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <string.h>
+#include <openssl/rand.h>
+
+int
+main ()
+{
+
+       exit(RAND_status() == 1 ? 0 : 1);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+               OPENSSL_SEEDS_ITSELF=yes
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+# PRNGD TCP socket
+
+# Check whether --with-prngd-port was given.
+if test "${with_prngd_port+set}" = set; then :
+  withval=$with_prngd_port;
+               case "$withval" in
+               no)
+                       withval=""
+                       ;;
+               [0-9]*)
+                       ;;
+               *)
+                       as_fn_error $? "You must specify a numeric port number for --with-prngd-port" "$LINENO" 5
+                       ;;
+               esac
+               if test ! -z "$withval" ; then
+                       PRNGD_PORT="$withval"
+
+cat >>confdefs.h <<_ACEOF
+#define PRNGD_PORT $PRNGD_PORT
+_ACEOF
+
+               fi
+
+
+fi
+
+
+# PRNGD Unix domain socket
+
+# Check whether --with-prngd-socket was given.
+if test "${with_prngd_socket+set}" = set; then :
+  withval=$with_prngd_socket;
+               case "$withval" in
+               yes)
+                       withval="/var/run/egd-pool"
+                       ;;
+               no)
+                       withval=""
+                       ;;
+               /*)
+                       ;;
+               *)
+                       as_fn_error $? "You must specify an absolute path to the entropy socket" "$LINENO" 5
+                       ;;
+               esac
+
+               if test ! -z "$withval" ; then
+                       if test ! -z "$PRNGD_PORT" ; then
+                               as_fn_error $? "You may not specify both a PRNGD/EGD port and socket" "$LINENO" 5
+                       fi
+                       if test ! -r "$withval" ; then
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Entropy socket is not readable" >&5
+$as_echo "$as_me: WARNING: Entropy socket is not readable" >&2;}
+                       fi
+                       PRNGD_SOCKET="$withval"
+
+cat >>confdefs.h <<_ACEOF
+#define PRNGD_SOCKET "$PRNGD_SOCKET"
+_ACEOF
+
+               fi
+
+else
+
+               # Check for existing socket only if we don't have a random device already
+               if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PRNGD/EGD socket" >&5
+$as_echo_n "checking for PRNGD/EGD socket... " >&6; }
+                       # Insert other locations here
+                       for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do
+                               if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then
+                                       PRNGD_SOCKET="$sock"
+                                       cat >>confdefs.h <<_ACEOF
+#define PRNGD_SOCKET "$PRNGD_SOCKET"
+_ACEOF
+
+                                       break;
+                               fi
+                       done
+                       if test ! -z "$PRNGD_SOCKET" ; then
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PRNGD_SOCKET" >&5
+$as_echo "$PRNGD_SOCKET" >&6; }
+                       else
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+                       fi
+               fi
+
+
+fi
+
+
+# Which randomness source do we use?
+if test ! -z "$PRNGD_PORT" ; then
+       RAND_MSG="PRNGd port $PRNGD_PORT"
+elif test ! -z "$PRNGD_SOCKET" ; then
+       RAND_MSG="PRNGd socket $PRNGD_SOCKET"
+elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then
+
+$as_echo "#define OPENSSL_PRNG_ONLY 1" >>confdefs.h
+
+       RAND_MSG="OpenSSL internal ONLY"
+else
+       as_fn_error $? "OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options" "$LINENO" 5
+fi
+
+# Check for PAM libs
+PAM_MSG="no"
+
+# Check whether --with-pam was given.
+if test "${with_pam+set}" = set; then :
+  withval=$with_pam;
+               if test "x$withval" != "xno" ; then
+                       if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \
+                          test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then
+                               as_fn_error $? "PAM headers not found" "$LINENO" 5
+                       fi
+
+                       saved_LIBS="$LIBS"
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_set_item in -lpam" >&5
+$as_echo_n "checking for pam_set_item in -lpam... " >&6; }
+if ${ac_cv_lib_pam_pam_set_item+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpam  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pam_set_item ();
+int
+main ()
+{
+return pam_set_item ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pam_pam_set_item=yes
+else
+  ac_cv_lib_pam_pam_set_item=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_set_item" >&5
+$as_echo "$ac_cv_lib_pam_pam_set_item" >&6; }
+if test "x$ac_cv_lib_pam_pam_set_item" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPAM 1
+_ACEOF
+
+  LIBS="-lpam $LIBS"
+
+else
+  as_fn_error $? "*** libpam missing" "$LINENO" 5
+fi
+
+                       for ac_func in pam_getenvlist
+do :
+  ac_fn_c_check_func "$LINENO" "pam_getenvlist" "ac_cv_func_pam_getenvlist"
+if test "x$ac_cv_func_pam_getenvlist" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PAM_GETENVLIST 1
+_ACEOF
+
+fi
+done
+
+                       for ac_func in pam_putenv
+do :
+  ac_fn_c_check_func "$LINENO" "pam_putenv" "ac_cv_func_pam_putenv"
+if test "x$ac_cv_func_pam_putenv" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PAM_PUTENV 1
+_ACEOF
+
+fi
+done
+
+                       LIBS="$saved_LIBS"
+
+                       PAM_MSG="yes"
+
+                       SSHDLIBS="$SSHDLIBS -lpam"
+
+$as_echo "#define USE_PAM 1" >>confdefs.h
+
+
+                       if test $ac_cv_lib_dl_dlopen = yes; then
+                               case "$LIBS" in
+                               *-ldl*)
+                                       # libdl already in LIBS
+                                       ;;
+                               *)
+                                       SSHDLIBS="$SSHDLIBS -ldl"
+                                       ;;
+                               esac
+                       fi
+               fi
+
+
+fi
+
+
+# Check for older PAM
+if test "x$PAM_MSG" = "xyes" ; then
+       # Check PAM strerror arguments (old PAM)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pam_strerror takes only one argument" >&5
+$as_echo_n "checking whether pam_strerror takes only one argument... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#if defined(HAVE_SECURITY_PAM_APPL_H)
+#include <security/pam_appl.h>
+#elif defined (HAVE_PAM_PAM_APPL_H)
+#include <pam/pam_appl.h>
+#endif
+
+int
+main ()
+{
+
+(void)pam_strerror((pam_handle_t *)NULL, -1);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+else
+
+
+$as_echo "#define HAVE_OLD_PAM 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                       PAM_MSG="yes (old library)"
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+SSH_PRIVSEP_USER=sshd
+
+# Check whether --with-privsep-user was given.
+if test "${with_privsep_user+set}" = set; then :
+  withval=$with_privsep_user;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       SSH_PRIVSEP_USER=$withval
+               fi
+
+
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER"
+_ACEOF
+
+
+
+# Decide which sandbox style to use
+sandbox_arg=""
+
+# Check whether --with-sandbox was given.
+if test "${with_sandbox+set}" = set; then :
+  withval=$with_sandbox;
+               if test "x$withval" = "xyes" ; then
+                       sandbox_arg=""
+               else
+                       sandbox_arg="$withval"
+               fi
+
+
+fi
+
+if test "x$sandbox_arg" = "xsystrace" || \
+   ( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then
+       test "x$have_systr_policy_kill" != "x1" && \
+               as_fn_error $? "systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support" "$LINENO" 5
+       SANDBOX_STYLE="systrace"
+
+$as_echo "#define SANDBOX_SYSTRACE 1" >>confdefs.h
+
+elif test "x$sandbox_arg" = "xdarwin" || \
+     ( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \
+       test "x$ac_cv_header_sandbox_h" = "xyes") ; then
+       test "x$ac_cv_func_sandbox_init" != "xyes" -o \
+            "x$ac_cv_header_sandbox_h" != "xyes" && \
+               as_fn_error $? "Darwin seatbelt sandbox requires sandbox.h and sandbox_init function" "$LINENO" 5
+       SANDBOX_STYLE="darwin"
+
+$as_echo "#define SANDBOX_DARWIN 1" >>confdefs.h
+
+elif test "x$sandbox_arg" = "xrlimit" || \
+     ( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" ) ; then
+       test "x$ac_cv_func_setrlimit" != "xyes" && \
+               as_fn_error $? "rlimit sandbox requires setrlimit function" "$LINENO" 5
+       SANDBOX_STYLE="rlimit"
+
+$as_echo "#define SANDBOX_RLIMIT 1" >>confdefs.h
+
+elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
+     test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
+       SANDBOX_STYLE="none"
+
+$as_echo "#define SANDBOX_NULL 1" >>confdefs.h
+
+else
+       as_fn_error $? "unsupported --with-sandbox" "$LINENO" 5
+fi
+
+# Cheap hack to ensure NEWS-OS libraries are arranged right.
+if test ! -z "$SONY" ; then
+  LIBS="$LIBS -liberty";
+fi
+
+# Check for  long long datatypes
+ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default"
+if test "x$ac_cv_type_long_long" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LONG_LONG 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default"
+if test "x$ac_cv_type_unsigned_long_long" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UNSIGNED_LONG_LONG 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "long double" "ac_cv_type_long_double" "$ac_includes_default"
+if test "x$ac_cv_type_long_double" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LONG_DOUBLE 1
+_ACEOF
+
+
+fi
+
+
+# Check datatype sizes
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5
+$as_echo_n "checking size of char... " >&6; }
+if ${ac_cv_sizeof_char+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_char" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (char)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_char=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5
+$as_echo "$ac_cv_sizeof_char" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_CHAR $ac_cv_sizeof_char
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short int" >&5
+$as_echo_n "checking size of short int... " >&6; }
+if ${ac_cv_sizeof_short_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short int))" "ac_cv_sizeof_short_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_short_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (short int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_short_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short_int" >&5
+$as_echo "$ac_cv_sizeof_short_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT_INT $ac_cv_sizeof_short_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+$as_echo_n "checking size of int... " >&6; }
+if ${ac_cv_sizeof_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+$as_echo "$ac_cv_sizeof_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long int" >&5
+$as_echo_n "checking size of long int... " >&6; }
+if ${ac_cv_sizeof_long_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long int))" "ac_cv_sizeof_long_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_int" >&5
+$as_echo "$ac_cv_sizeof_long_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long int" >&5
+$as_echo_n "checking size of long long int... " >&6; }
+if ${ac_cv_sizeof_long_long_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long int))" "ac_cv_sizeof_long_long_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_long_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long_long_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long_int" >&5
+$as_echo "$ac_cv_sizeof_long_long_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int
+_ACEOF
+
+
+
+# Sanity check long long for some platforms (AIX)
+if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
+       ac_cv_sizeof_long_long_int=0
+fi
+
+# compute LLONG_MIN and LLONG_MAX if we don't know them.
+if test -z "$have_llong_max"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for max value of long long" >&5
+$as_echo_n "checking for max value of long long... " >&6; }
+       if test "$cross_compiling" = yes; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+/* Why is this so damn hard? */
+#ifdef __GNUC__
+# undef __GNUC__
+#endif
+#define __USE_ISOC99
+#include <limits.h>
+#define DATA "conftest.llminmax"
+#define my_abs(a) ((a) < 0 ? ((a) * -1) : (a))
+
+/*
+ * printf in libc on some platforms (eg old Tru64) does not understand %lld so
+ * we do this the hard way.
+ */
+static int
+fprint_ll(FILE *f, long long n)
+{
+       unsigned int i;
+       int l[sizeof(long long) * 8];
+
+       if (n < 0)
+               if (fprintf(f, "-") < 0)
+                       return -1;
+       for (i = 0; n != 0; i++) {
+               l[i] = my_abs(n % 10);
+               n /= 10;
+       }
+       do {
+               if (fprintf(f, "%d", l[--i]) < 0)
+                       return -1;
+       } while (i != 0);
+       if (fprintf(f, " ") < 0)
+               return -1;
+       return 0;
+}
+
+int
+main ()
+{
+
+       FILE *f;
+       long long i, llmin, llmax = 0;
+
+       if((f = fopen(DATA,"w")) == NULL)
+               exit(1);
+
+#if defined(LLONG_MIN) && defined(LLONG_MAX)
+       fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n");
+       llmin = LLONG_MIN;
+       llmax = LLONG_MAX;
+#else
+       fprintf(stderr, "Calculating  LLONG_MIN and LLONG_MAX\n");
+       /* This will work on one's complement and two's complement */
+       for (i = 1; i > llmax; i <<= 1, i++)
+               llmax = i;
+       llmin = llmax + 1LL;    /* wrap */
+#endif
+
+       /* Sanity check */
+       if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax
+           || llmax - 1 > llmax || llmin == llmax || llmin == 0
+           || llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) {
+               fprintf(f, "unknown unknown\n");
+               exit(2);
+       }
+
+       if (fprint_ll(f, llmin) < 0)
+               exit(3);
+       if (fprint_ll(f, llmax) < 0)
+               exit(4);
+       if (fclose(f) < 0)
+               exit(5);
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+                       llong_min=`$AWK '{print $1}' conftest.llminmax`
+                       llong_max=`$AWK '{print $2}' conftest.llminmax`
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $llong_max" >&5
+$as_echo "$llong_max" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define LLONG_MAX ${llong_max}LL
+_ACEOF
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for min value of long long" >&5
+$as_echo_n "checking for min value of long long... " >&6; }
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $llong_min" >&5
+$as_echo "$llong_min" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define LLONG_MIN ${llong_min}LL
+_ACEOF
+
+
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+
+# More checks for data types
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int type" >&5
+$as_echo_n "checking for u_int type... " >&6; }
+if ${ac_cv_have_u_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ u_int a; a = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_u_int="yes"
+else
+   ac_cv_have_u_int="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int" >&5
+$as_echo "$ac_cv_have_u_int" >&6; }
+if test "x$ac_cv_have_u_int" = "xyes" ; then
+
+$as_echo "#define HAVE_U_INT 1" >>confdefs.h
+
+       have_u_int=1
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t types" >&5
+$as_echo_n "checking for intXX_t types... " >&6; }
+if ${ac_cv_have_intxx_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ int8_t a; int16_t b; int32_t c; a = b = c = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_intxx_t="yes"
+else
+   ac_cv_have_intxx_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_intxx_t" >&5
+$as_echo "$ac_cv_have_intxx_t" >&6; }
+if test "x$ac_cv_have_intxx_t" = "xyes" ; then
+
+$as_echo "#define HAVE_INTXX_T 1" >>confdefs.h
+
+       have_intxx_t=1
+fi
+
+if (test -z "$have_intxx_t" && \
+          test "x$ac_cv_header_stdint_h" = "xyes")
+then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t types in stdint.h" >&5
+$as_echo_n "checking for intXX_t types in stdint.h... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdint.h>
+int
+main ()
+{
+ int8_t a; int16_t b; int32_t c; a = b = c = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       $as_echo "#define HAVE_INTXX_T 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for int64_t type" >&5
+$as_echo_n "checking for int64_t type... " >&6; }
+if ${ac_cv_have_int64_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <sys/socket.h>
+#ifdef HAVE_SYS_BITYPES_H
+# include <sys/bitypes.h>
+#endif
+
+int
+main ()
+{
+
+int64_t a; a = 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_int64_t="yes"
+else
+   ac_cv_have_int64_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_int64_t" >&5
+$as_echo "$ac_cv_have_int64_t" >&6; }
+if test "x$ac_cv_have_int64_t" = "xyes" ; then
+
+$as_echo "#define HAVE_INT64_T 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types" >&5
+$as_echo_n "checking for u_intXX_t types... " >&6; }
+if ${ac_cv_have_u_intxx_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_u_intxx_t="yes"
+else
+   ac_cv_have_u_intxx_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_intxx_t" >&5
+$as_echo "$ac_cv_have_u_intxx_t" >&6; }
+if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then
+
+$as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h
+
+       have_u_intxx_t=1
+fi
+
+if test -z "$have_u_intxx_t" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types in sys/socket.h" >&5
+$as_echo_n "checking for u_intXX_t types in sys/socket.h... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/socket.h>
+int
+main ()
+{
+ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       $as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int64_t types" >&5
+$as_echo_n "checking for u_int64_t types... " >&6; }
+if ${ac_cv_have_u_int64_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ u_int64_t a; a = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_u_int64_t="yes"
+else
+   ac_cv_have_u_int64_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int64_t" >&5
+$as_echo "$ac_cv_have_u_int64_t" >&6; }
+if test "x$ac_cv_have_u_int64_t" = "xyes" ; then
+
+$as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h
+
+       have_u_int64_t=1
+fi
+
+if test -z "$have_u_int64_t" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int64_t type in sys/bitypes.h" >&5
+$as_echo_n "checking for u_int64_t type in sys/bitypes.h... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/bitypes.h>
+int
+main ()
+{
+ u_int64_t a; a = 1
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       $as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test -z "$have_u_intxx_t" ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types" >&5
+$as_echo_n "checking for uintXX_t types... " >&6; }
+if ${ac_cv_have_uintxx_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+
+int
+main ()
+{
+
+       uint8_t a;
+       uint16_t b;
+       uint32_t c;
+       a = b = c = 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_uintxx_t="yes"
+else
+   ac_cv_have_uintxx_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_uintxx_t" >&5
+$as_echo "$ac_cv_have_uintxx_t" >&6; }
+       if test "x$ac_cv_have_uintxx_t" = "xyes" ; then
+
+$as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h
+
+       fi
+fi
+
+if test -z "$have_uintxx_t" ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in stdint.h" >&5
+$as_echo_n "checking for uintXX_t types in stdint.h... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdint.h>
+int
+main ()
+{
+ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       $as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \
+          test "x$ac_cv_header_sys_bitypes_h" = "xyes")
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5
+$as_echo_n "checking for intXX_t and u_intXX_t types in sys/bitypes.h... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/bitypes.h>
+
+int
+main ()
+{
+
+                       int8_t a; int16_t b; int32_t c;
+                       u_int8_t e; u_int16_t f; u_int32_t g;
+                       a = b = c = e = f = g = 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                       $as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h
+
+                       $as_echo "#define HAVE_INTXX_T 1" >>confdefs.h
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_char" >&5
+$as_echo_n "checking for u_char... " >&6; }
+if ${ac_cv_have_u_char+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ u_char foo; foo = 125;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_u_char="yes"
+else
+   ac_cv_have_u_char="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_char" >&5
+$as_echo "$ac_cv_have_u_char" >&6; }
+if test "x$ac_cv_have_u_char" = "xyes" ; then
+
+$as_echo "#define HAVE_U_CHAR 1" >>confdefs.h
+
+fi
+
+
+   ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include <sys/types.h>
+#include <sys/socket.h>
+"
+if test "x$ac_cv_type_socklen_t" = xyes; then :
+
+else
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5
+$as_echo_n "checking for socklen_t equivalent... " >&6; }
+      if ${curl_cv_socklen_t_equiv+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+        # Systems have either "struct sockaddr *" or
+        # "void *" as the second argument to getpeername
+        curl_cv_socklen_t_equiv=
+        for arg2 in "struct sockaddr" void; do
+           for t in int size_t unsigned long "unsigned long"; do
+              cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+                 #include <sys/types.h>
+                 #include <sys/socket.h>
+
+                 int getpeername (int, $arg2 *, $t *);
+
+int
+main ()
+{
+
+                 $t len;
+                 getpeername(0,0,&len);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                 curl_cv_socklen_t_equiv="$t"
+                 break
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+           done
+        done
+
+        if test "x$curl_cv_socklen_t_equiv" = x; then
+           as_fn_error $? "Cannot find a type to use in place of socklen_t" "$LINENO" 5
+        fi
+
+fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $curl_cv_socklen_t_equiv" >&5
+$as_echo "$curl_cv_socklen_t_equiv" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define socklen_t $curl_cv_socklen_t_equiv
+_ACEOF
+
+fi
+
+
+
+ac_fn_c_check_type "$LINENO" "sig_atomic_t" "ac_cv_type_sig_atomic_t" "#include <signal.h>
+"
+if test "x$ac_cv_type_sig_atomic_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SIG_ATOMIC_T 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_type "$LINENO" "fsblkcnt_t" "ac_cv_type_fsblkcnt_t" "
+#include <sys/types.h>
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+"
+if test "x$ac_cv_type_fsblkcnt_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FSBLKCNT_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "fsfilcnt_t" "ac_cv_type_fsfilcnt_t" "
+#include <sys/types.h>
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+"
+if test "x$ac_cv_type_fsfilcnt_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_FSFILCNT_T 1
+_ACEOF
+
+
+fi
+
+
+ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" "#include <sys/types.h>
+#include <netinet/in.h>
+"
+if test "x$ac_cv_type_in_addr_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_IN_ADDR_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" "#include <sys/types.h>
+#include <netinet/in.h>
+"
+if test "x$ac_cv_type_in_port_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_IN_PORT_T 1
+_ACEOF
+
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for size_t" >&5
+$as_echo_n "checking for size_t... " >&6; }
+if ${ac_cv_have_size_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ size_t foo; foo = 1235;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_size_t="yes"
+else
+   ac_cv_have_size_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_size_t" >&5
+$as_echo "$ac_cv_have_size_t" >&6; }
+if test "x$ac_cv_have_size_t" = "xyes" ; then
+
+$as_echo "#define HAVE_SIZE_T 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ssize_t" >&5
+$as_echo_n "checking for ssize_t... " >&6; }
+if ${ac_cv_have_ssize_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ ssize_t foo; foo = 1235;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_ssize_t="yes"
+else
+   ac_cv_have_ssize_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ssize_t" >&5
+$as_echo "$ac_cv_have_ssize_t" >&6; }
+if test "x$ac_cv_have_ssize_t" = "xyes" ; then
+
+$as_echo "#define HAVE_SSIZE_T 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_t" >&5
+$as_echo_n "checking for clock_t... " >&6; }
+if ${ac_cv_have_clock_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <time.h>
+int
+main ()
+{
+ clock_t foo; foo = 1235;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_clock_t="yes"
+else
+   ac_cv_have_clock_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_clock_t" >&5
+$as_echo "$ac_cv_have_clock_t" >&6; }
+if test "x$ac_cv_have_clock_t" = "xyes" ; then
+
+$as_echo "#define HAVE_CLOCK_T 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sa_family_t" >&5
+$as_echo_n "checking for sa_family_t... " >&6; }
+if ${ac_cv_have_sa_family_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int
+main ()
+{
+ sa_family_t foo; foo = 1235;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_sa_family_t="yes"
+else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+int
+main ()
+{
+ sa_family_t foo; foo = 1235;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_sa_family_t="yes"
+else
+   ac_cv_have_sa_family_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_sa_family_t" >&5
+$as_echo "$ac_cv_have_sa_family_t" >&6; }
+if test "x$ac_cv_have_sa_family_t" = "xyes" ; then
+
+$as_echo "#define HAVE_SA_FAMILY_T 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pid_t" >&5
+$as_echo_n "checking for pid_t... " >&6; }
+if ${ac_cv_have_pid_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ pid_t foo; foo = 1235;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_pid_t="yes"
+else
+   ac_cv_have_pid_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pid_t" >&5
+$as_echo "$ac_cv_have_pid_t" >&6; }
+if test "x$ac_cv_have_pid_t" = "xyes" ; then
+
+$as_echo "#define HAVE_PID_T 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mode_t" >&5
+$as_echo_n "checking for mode_t... " >&6; }
+if ${ac_cv_have_mode_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/types.h>
+int
+main ()
+{
+ mode_t foo; foo = 1235;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_mode_t="yes"
+else
+   ac_cv_have_mode_t="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_mode_t" >&5
+$as_echo "$ac_cv_have_mode_t" >&6; }
+if test "x$ac_cv_have_mode_t" = "xyes" ; then
+
+$as_echo "#define HAVE_MODE_T 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_storage" >&5
+$as_echo_n "checking for struct sockaddr_storage... " >&6; }
+if ${ac_cv_have_struct_sockaddr_storage+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int
+main ()
+{
+ struct sockaddr_storage s;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_struct_sockaddr_storage="yes"
+else
+   ac_cv_have_struct_sockaddr_storage="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_storage" >&5
+$as_echo "$ac_cv_have_struct_sockaddr_storage" >&6; }
+if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_in6" >&5
+$as_echo_n "checking for struct sockaddr_in6... " >&6; }
+if ${ac_cv_have_struct_sockaddr_in6+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+int
+main ()
+{
+ struct sockaddr_in6 s; s.sin6_family = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_struct_sockaddr_in6="yes"
+else
+   ac_cv_have_struct_sockaddr_in6="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_in6" >&5
+$as_echo "$ac_cv_have_struct_sockaddr_in6" >&6; }
+if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_SOCKADDR_IN6 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct in6_addr" >&5
+$as_echo_n "checking for struct in6_addr... " >&6; }
+if ${ac_cv_have_struct_in6_addr+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+int
+main ()
+{
+ struct in6_addr s; s.s6_addr[0] = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_struct_in6_addr="yes"
+else
+   ac_cv_have_struct_in6_addr="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_in6_addr" >&5
+$as_echo "$ac_cv_have_struct_in6_addr" >&6; }
+if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h
+
+
+       ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_scope_id" "ac_cv_member_struct_sockaddr_in6_sin6_scope_id" "
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <netinet/in.h>
+
+"
+if test "x$ac_cv_member_struct_sockaddr_in6_sin6_scope_id" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
+_ACEOF
+
+
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct addrinfo" >&5
+$as_echo_n "checking for struct addrinfo... " >&6; }
+if ${ac_cv_have_struct_addrinfo+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+int
+main ()
+{
+ struct addrinfo s; s.ai_flags = AI_PASSIVE;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_struct_addrinfo="yes"
+else
+   ac_cv_have_struct_addrinfo="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_addrinfo" >&5
+$as_echo "$ac_cv_have_struct_addrinfo" >&6; }
+if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_ADDRINFO 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct timeval" >&5
+$as_echo_n "checking for struct timeval... " >&6; }
+if ${ac_cv_have_struct_timeval+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <sys/time.h>
+int
+main ()
+{
+ struct timeval tv; tv.tv_sec = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_struct_timeval="yes"
+else
+   ac_cv_have_struct_timeval="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_timeval" >&5
+$as_echo "$ac_cv_have_struct_timeval" >&6; }
+if test "x$ac_cv_have_struct_timeval" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_TIMEVAL 1" >>confdefs.h
+
+       have_struct_timeval=1
+fi
+
+ac_fn_c_check_type "$LINENO" "struct timespec" "ac_cv_type_struct_timespec" "$ac_includes_default"
+if test "x$ac_cv_type_struct_timespec" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TIMESPEC 1
+_ACEOF
+
+
+fi
+
+
+# We need int64_t or else certian parts of the compile will fail.
+if test "x$ac_cv_have_int64_t" = "xno" && \
+       test "x$ac_cv_sizeof_long_int" != "x8" && \
+       test "x$ac_cv_sizeof_long_long_int" = "x0" ; then
+       echo "OpenSSH requires int64_t support.  Contact your vendor or install"
+       echo "an alternative compiler (I.E., GCC) before continuing."
+       echo ""
+       exit 1;
+else
+       if test "$cross_compiling" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5
+$as_echo "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;}
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_SNPRINTF
+main()
+{
+       char buf[50];
+       char expected_out[50];
+       int mazsize = 50 ;
+#if (SIZEOF_LONG_INT == 8)
+       long int num = 0x7fffffffffffffff;
+#else
+       long long num = 0x7fffffffffffffffll;
+#endif
+       strcpy(expected_out, "9223372036854775807");
+       snprintf(buf, mazsize, "%lld", num);
+       if(strcmp(buf, expected_out) != 0)
+               exit(1);
+       exit(0);
+}
+#else
+main() { exit(0); }
+#endif
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+   true
+else
+   $as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+
+# look for field 'ut_host' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmp.h" >&5
+$as_echo_n "checking for ut_host field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_host" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_HOST_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_host' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmpx.h" >&5
+$as_echo_n "checking for ut_host field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_host" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_HOST_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'syslen' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"syslen
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for syslen field in utmpx.h" >&5
+$as_echo_n "checking for syslen field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "syslen" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_SYSLEN_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_pid' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_pid
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_pid field in utmp.h" >&5
+$as_echo_n "checking for ut_pid field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_pid" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_PID_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_type' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmp.h" >&5
+$as_echo_n "checking for ut_type field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_type" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_TYPE_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_type' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmpx.h" >&5
+$as_echo_n "checking for ut_type field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_type" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_TYPE_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_tv' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmp.h" >&5
+$as_echo_n "checking for ut_tv field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_tv" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_TV_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_id' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmp.h" >&5
+$as_echo_n "checking for ut_id field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_id" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_ID_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_id' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmpx.h" >&5
+$as_echo_n "checking for ut_id field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_id" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_ID_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_addr' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmp.h" >&5
+$as_echo_n "checking for ut_addr field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_addr" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_ADDR_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_addr' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmpx.h" >&5
+$as_echo_n "checking for ut_addr field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_addr" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_ADDR_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_addr_v6' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmp.h" >&5
+$as_echo_n "checking for ut_addr_v6 field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_addr_v6" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_ADDR_V6_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_addr_v6' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmpx.h" >&5
+$as_echo_n "checking for ut_addr_v6 field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_addr_v6" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_ADDR_V6_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_exit' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_exit
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_exit field in utmp.h" >&5
+$as_echo_n "checking for ut_exit field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_exit" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_EXIT_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_time' in header 'utmp.h'
+               ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmp.h" >&5
+$as_echo_n "checking for ut_time field in utmp.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmp.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_time" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_TIME_IN_UTMP 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_time' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmpx.h" >&5
+$as_echo_n "checking for ut_time field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_time" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_TIME_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+# look for field 'ut_tv' in header 'utmpx.h'
+               ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
+               ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmpx.h" >&5
+$as_echo_n "checking for ut_tv field in utmpx.h... " >&6; }
+       if eval \${$ossh_varname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <utmpx.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ut_tv" >/dev/null 2>&1; then :
+                       eval "$ossh_varname=yes"
+else
+                       eval "$ossh_varname=no"
+fi
+rm -f conftest*
+
+fi
+
+       ossh_result=`eval 'echo $'"$ossh_varname"`
+       if test -n "`echo $ossh_varname`"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
+$as_echo "$ossh_result" >&6; }
+               if test "x$ossh_result" = "xyes"; then
+
+$as_echo "#define HAVE_TV_IN_UTMPX 1" >>confdefs.h
+
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct __res_state" "retrans" "ac_cv_member_struct___res_state_retrans" "
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+"
+if test "x$ac_cv_member_struct___res_state_retrans" = xyes; then :
+
+else
+
+$as_echo "#define __res_state state" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ss_family field in struct sockaddr_storage" >&5
+$as_echo_n "checking for ss_family field in struct sockaddr_storage... " >&6; }
+if ${ac_cv_have_ss_family_in_struct_ss+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int
+main ()
+{
+ struct sockaddr_storage s; s.ss_family = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_ss_family_in_struct_ss="yes"
+else
+   ac_cv_have_ss_family_in_struct_ss="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ss_family_in_struct_ss" >&5
+$as_echo "$ac_cv_have_ss_family_in_struct_ss" >&6; }
+if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then
+
+$as_echo "#define HAVE_SS_FAMILY_IN_SS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __ss_family field in struct sockaddr_storage" >&5
+$as_echo_n "checking for __ss_family field in struct sockaddr_storage... " >&6; }
+if ${ac_cv_have___ss_family_in_struct_ss+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int
+main ()
+{
+ struct sockaddr_storage s; s.__ss_family = 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have___ss_family_in_struct_ss="yes"
+else
+   ac_cv_have___ss_family_in_struct_ss="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___ss_family_in_struct_ss" >&5
+$as_echo "$ac_cv_have___ss_family_in_struct_ss" >&6; }
+if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
+
+$as_echo "#define HAVE___SS_FAMILY_IN_SS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pw_class field in struct passwd" >&5
+$as_echo_n "checking for pw_class field in struct passwd... " >&6; }
+if ${ac_cv_have_pw_class_in_struct_passwd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <pwd.h>
+int
+main ()
+{
+ struct passwd p; p.pw_class = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_pw_class_in_struct_passwd="yes"
+else
+   ac_cv_have_pw_class_in_struct_passwd="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pw_class_in_struct_passwd" >&5
+$as_echo "$ac_cv_have_pw_class_in_struct_passwd" >&6; }
+if test "x$ac_cv_have_pw_class_in_struct_passwd" = "xyes" ; then
+
+$as_echo "#define HAVE_PW_CLASS_IN_PASSWD 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pw_expire field in struct passwd" >&5
+$as_echo_n "checking for pw_expire field in struct passwd... " >&6; }
+if ${ac_cv_have_pw_expire_in_struct_passwd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <pwd.h>
+int
+main ()
+{
+ struct passwd p; p.pw_expire = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_pw_expire_in_struct_passwd="yes"
+else
+   ac_cv_have_pw_expire_in_struct_passwd="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pw_expire_in_struct_passwd" >&5
+$as_echo "$ac_cv_have_pw_expire_in_struct_passwd" >&6; }
+if test "x$ac_cv_have_pw_expire_in_struct_passwd" = "xyes" ; then
+
+$as_echo "#define HAVE_PW_EXPIRE_IN_PASSWD 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pw_change field in struct passwd" >&5
+$as_echo_n "checking for pw_change field in struct passwd... " >&6; }
+if ${ac_cv_have_pw_change_in_struct_passwd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <pwd.h>
+int
+main ()
+{
+ struct passwd p; p.pw_change = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_pw_change_in_struct_passwd="yes"
+else
+   ac_cv_have_pw_change_in_struct_passwd="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pw_change_in_struct_passwd" >&5
+$as_echo "$ac_cv_have_pw_change_in_struct_passwd" >&6; }
+if test "x$ac_cv_have_pw_change_in_struct_passwd" = "xyes" ; then
+
+$as_echo "#define HAVE_PW_CHANGE_IN_PASSWD 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for msg_accrights field in struct msghdr" >&5
+$as_echo_n "checking for msg_accrights field in struct msghdr... " >&6; }
+if ${ac_cv_have_accrights_in_msghdr+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+int
+main ()
+{
+
+#ifdef msg_accrights
+#error "msg_accrights is a macro"
+exit(1);
+#endif
+struct msghdr m;
+m.msg_accrights = 0;
+exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_accrights_in_msghdr="yes"
+else
+   ac_cv_have_accrights_in_msghdr="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_accrights_in_msghdr" >&5
+$as_echo "$ac_cv_have_accrights_in_msghdr" >&6; }
+if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then
+
+$as_echo "#define HAVE_ACCRIGHTS_IN_MSGHDR 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct statvfs.f_fsid is integral type" >&5
+$as_echo_n "checking if struct statvfs.f_fsid is integral type... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+int
+main ()
+{
+ struct statvfs s; s.f_fsid = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if fsid_t has member val" >&5
+$as_echo_n "checking if fsid_t has member val... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/statvfs.h>
+
+int
+main ()
+{
+ fsid_t t; t.val[0] = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define FSID_HAS_VAL 1" >>confdefs.h
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if f_fsid has member __val" >&5
+$as_echo_n "checking if f_fsid has member __val... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/statvfs.h>
+
+int
+main ()
+{
+ fsid_t t; t.__val[0] = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define FSID_HAS___VAL 1" >>confdefs.h
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for msg_control field in struct msghdr" >&5
+$as_echo_n "checking for msg_control field in struct msghdr... " >&6; }
+if ${ac_cv_have_control_in_msghdr+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+int
+main ()
+{
+
+#ifdef msg_control
+#error "msg_control is a macro"
+exit(1);
+#endif
+struct msghdr m;
+m.msg_control = 0;
+exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_have_control_in_msghdr="yes"
+else
+   ac_cv_have_control_in_msghdr="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_control_in_msghdr" >&5
+$as_echo "$ac_cv_have_control_in_msghdr" >&6; }
+if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then
+
+$as_echo "#define HAVE_CONTROL_IN_MSGHDR 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines __progname" >&5
+$as_echo_n "checking if libc defines __progname... " >&6; }
+if ${ac_cv_libc_defines___progname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+ extern char *__progname; printf("%s", __progname);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_libc_defines___progname="yes"
+else
+   ac_cv_libc_defines___progname="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines___progname" >&5
+$as_echo "$ac_cv_libc_defines___progname" >&6; }
+if test "x$ac_cv_libc_defines___progname" = "xyes" ; then
+
+$as_echo "#define HAVE___PROGNAME 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __FUNCTION__" >&5
+$as_echo_n "checking whether $CC implements __FUNCTION__... " >&6; }
+if ${ac_cv_cc_implements___FUNCTION__+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdio.h>
+int
+main ()
+{
+ printf("%s", __FUNCTION__);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_cc_implements___FUNCTION__="yes"
+else
+   ac_cv_cc_implements___FUNCTION__="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___FUNCTION__" >&5
+$as_echo "$ac_cv_cc_implements___FUNCTION__" >&6; }
+if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then
+
+$as_echo "#define HAVE___FUNCTION__ 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __func__" >&5
+$as_echo_n "checking whether $CC implements __func__... " >&6; }
+if ${ac_cv_cc_implements___func__+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <stdio.h>
+int
+main ()
+{
+ printf("%s", __func__);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_cc_implements___func__="yes"
+else
+   ac_cv_cc_implements___func__="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___func__" >&5
+$as_echo "$ac_cv_cc_implements___func__" >&6; }
+if test "x$ac_cv_cc_implements___func__" = "xyes" ; then
+
+$as_echo "#define HAVE___func__ 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether va_copy exists" >&5
+$as_echo_n "checking whether va_copy exists... " >&6; }
+if ${ac_cv_have_va_copy+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdarg.h>
+va_list x,y;
+
+int
+main ()
+{
+ va_copy(x,y);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_have_va_copy="yes"
+else
+   ac_cv_have_va_copy="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_va_copy" >&5
+$as_echo "$ac_cv_have_va_copy" >&6; }
+if test "x$ac_cv_have_va_copy" = "xyes" ; then
+
+$as_echo "#define HAVE_VA_COPY 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __va_copy exists" >&5
+$as_echo_n "checking whether __va_copy exists... " >&6; }
+if ${ac_cv_have___va_copy+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdarg.h>
+va_list x,y;
+
+int
+main ()
+{
+ __va_copy(x,y);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_have___va_copy="yes"
+else
+   ac_cv_have___va_copy="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___va_copy" >&5
+$as_echo "$ac_cv_have___va_copy" >&6; }
+if test "x$ac_cv_have___va_copy" = "xyes" ; then
+
+$as_echo "#define HAVE___VA_COPY 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getopt has optreset support" >&5
+$as_echo_n "checking whether getopt has optreset support... " >&6; }
+if ${ac_cv_have_getopt_optreset+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <getopt.h>
+int
+main ()
+{
+ extern int optreset; optreset = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_have_getopt_optreset="yes"
+else
+   ac_cv_have_getopt_optreset="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_getopt_optreset" >&5
+$as_echo "$ac_cv_have_getopt_optreset" >&6; }
+if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then
+
+$as_echo "#define HAVE_GETOPT_OPTRESET 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_errlist" >&5
+$as_echo_n "checking if libc defines sys_errlist... " >&6; }
+if ${ac_cv_libc_defines_sys_errlist+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_libc_defines_sys_errlist="yes"
+else
+   ac_cv_libc_defines_sys_errlist="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_errlist" >&5
+$as_echo "$ac_cv_libc_defines_sys_errlist" >&6; }
+if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then
+
+$as_echo "#define HAVE_SYS_ERRLIST 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_nerr" >&5
+$as_echo_n "checking if libc defines sys_nerr... " >&6; }
+if ${ac_cv_libc_defines_sys_nerr+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+ extern int sys_nerr; printf("%i", sys_nerr);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_libc_defines_sys_nerr="yes"
+else
+   ac_cv_libc_defines_sys_nerr="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_nerr" >&5
+$as_echo "$ac_cv_libc_defines_sys_nerr" >&6; }
+if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
+
+$as_echo "#define HAVE_SYS_NERR 1" >>confdefs.h
+
+fi
+
+# Check libraries needed by DNS fingerprint support
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getrrsetbyname" >&5
+$as_echo_n "checking for library containing getrrsetbyname... " >&6; }
+if ${ac_cv_search_getrrsetbyname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getrrsetbyname ();
+int
+main ()
+{
+return getrrsetbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' resolv; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_getrrsetbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_getrrsetbyname+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_getrrsetbyname+:} false; then :
+
+else
+  ac_cv_search_getrrsetbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getrrsetbyname" >&5
+$as_echo "$ac_cv_search_getrrsetbyname" >&6; }
+ac_res=$ac_cv_search_getrrsetbyname
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_GETRRSETBYNAME 1" >>confdefs.h
+
+else
+
+               # Needed by our getrrsetbyname()
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing res_query" >&5
+$as_echo_n "checking for library containing res_query... " >&6; }
+if ${ac_cv_search_res_query+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char res_query ();
+int
+main ()
+{
+return res_query ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' resolv; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_res_query=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_res_query+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_res_query+:} false; then :
+
+else
+  ac_cv_search_res_query=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_res_query" >&5
+$as_echo "$ac_cv_search_res_query" >&6; }
+ac_res=$ac_cv_search_res_query
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5
+$as_echo_n "checking for library containing dn_expand... " >&6; }
+if ${ac_cv_search_dn_expand+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dn_expand ();
+int
+main ()
+{
+return dn_expand ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' resolv; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dn_expand=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dn_expand+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dn_expand+:} false; then :
+
+else
+  ac_cv_search_dn_expand=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5
+$as_echo "$ac_cv_search_dn_expand" >&6; }
+ac_res=$ac_cv_search_dn_expand
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if res_query will link" >&5
+$as_echo_n "checking if res_query will link... " >&6; }
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+
+int
+main ()
+{
+
+       res_query (0, 0, 0, 0, 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                   saved_LIBS="$LIBS"
+                   LIBS="$LIBS -lresolv"
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5
+$as_echo_n "checking for res_query in -lresolv... " >&6; }
+                   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+
+int
+main ()
+{
+
+       res_query (0, 0, 0, 0, 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  LIBS="$saved_LIBS"
+                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+               for ac_func in _getshort _getlong
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+               ac_fn_c_check_decl "$LINENO" "_getshort" "ac_cv_have_decl__getshort" "#include <sys/types.h>
+                   #include <arpa/nameser.h>
+"
+if test "x$ac_cv_have_decl__getshort" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__GETSHORT $ac_have_decl
+_ACEOF
+ac_fn_c_check_decl "$LINENO" "_getlong" "ac_cv_have_decl__getlong" "#include <sys/types.h>
+                   #include <arpa/nameser.h>
+"
+if test "x$ac_cv_have_decl__getlong" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL__GETLONG $ac_have_decl
+_ACEOF
+
+               ac_fn_c_check_member "$LINENO" "HEADER" "ad" "ac_cv_member_HEADER_ad" "#include <arpa/nameser.h>
+"
+if test "x$ac_cv_member_HEADER_ad" = xyes; then :
+
+$as_echo "#define HAVE_HEADER_AD 1" >>confdefs.h
+
+fi
+
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct __res_state _res is an extern" >&5
+$as_echo_n "checking if struct __res_state _res is an extern... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+extern struct __res_state _res;
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE__RES_EXTERN 1" >>confdefs.h
+
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+# Check whether user wants SELinux support
+SELINUX_MSG="no"
+LIBSELINUX=""
+
+# Check whether --with-selinux was given.
+if test "${with_selinux+set}" = set; then :
+  withval=$with_selinux;  if test "x$withval" != "xno" ; then
+               save_LIBS="$LIBS"
+
+$as_echo "#define WITH_SELINUX 1" >>confdefs.h
+
+               SELINUX_MSG="yes"
+               ac_fn_c_check_header_mongrel "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default"
+if test "x$ac_cv_header_selinux_selinux_h" = xyes; then :
+
+else
+  as_fn_error $? "SELinux support requires selinux.h header" "$LINENO" 5
+fi
+
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setexeccon in -lselinux" >&5
+$as_echo_n "checking for setexeccon in -lselinux... " >&6; }
+if ${ac_cv_lib_selinux_setexeccon+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lselinux  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setexeccon ();
+int
+main ()
+{
+return setexeccon ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_selinux_setexeccon=yes
+else
+  ac_cv_lib_selinux_setexeccon=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_setexeccon" >&5
+$as_echo "$ac_cv_lib_selinux_setexeccon" >&6; }
+if test "x$ac_cv_lib_selinux_setexeccon" = xyes; then :
+   LIBSELINUX="-lselinux"
+                         LIBS="$LIBS -lselinux"
+
+else
+  as_fn_error $? "SELinux support requires libselinux library" "$LINENO" 5
+fi
+
+               SSHLIBS="$SSHLIBS $LIBSELINUX"
+               SSHDLIBS="$SSHDLIBS $LIBSELINUX"
+               for ac_func in getseuserbyname get_default_context_with_level
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+               LIBS="$save_LIBS"
+       fi
+
+fi
+
+
+
+
+# Check whether user wants Kerberos 5 support
+KRB5_MSG="no"
+
+# Check whether --with-kerberos5 was given.
+if test "${with_kerberos5+set}" = set; then :
+  withval=$with_kerberos5;  if test "x$withval" != "xno" ; then
+               if test "x$withval" = "xyes" ; then
+                       KRB5ROOT="/usr/local"
+               else
+                       KRB5ROOT=${withval}
+               fi
+
+
+$as_echo "#define KRB5 1" >>confdefs.h
+
+               KRB5_MSG="yes"
+
+               # Extract the first word of "krb5-config", so it can be a program name with args.
+set dummy krb5-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_KRB5CONF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $KRB5CONF in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_KRB5CONF="$KRB5CONF" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="$KRB5ROOT/bin:$PATH"
+for as_dir in $as_dummy
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_KRB5CONF="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_KRB5CONF" && ac_cv_path_KRB5CONF="$KRB5ROOT/bin/krb5-config"
+  ;;
+esac
+fi
+KRB5CONF=$ac_cv_path_KRB5CONF
+if test -n "$KRB5CONF"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KRB5CONF" >&5
+$as_echo "$KRB5CONF" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+               if test -x $KRB5CONF ; then
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5
+$as_echo_n "checking for gssapi support... " >&6; }
+                       if $KRB5CONF | grep gssapi >/dev/null ; then
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define GSSAPI 1" >>confdefs.h
+
+                               k5confopts=gssapi
+                       else
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                               k5confopts=""
+                       fi
+                       K5CFLAGS="`$KRB5CONF --cflags $k5confopts`"
+                       K5LIBS="`$KRB5CONF --libs $k5confopts`"
+                       CPPFLAGS="$CPPFLAGS $K5CFLAGS"
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5
+$as_echo_n "checking whether we are using Heimdal... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <krb5.h>
+
+int
+main ()
+{
+ char *tmp = heimdal_version;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HEIMDAL 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+               else
+                       CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include"
+                       LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib"
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5
+$as_echo_n "checking whether we are using Heimdal... " >&6; }
+                       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+ #include <krb5.h>
+
+int
+main ()
+{
+ char *tmp = heimdal_version;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                                        $as_echo "#define HEIMDAL 1" >>confdefs.h
+
+                                        K5LIBS="-lkrb5"
+                                        K5LIBS="$K5LIBS -lcom_err -lasn1"
+                                        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for net_write in -lroken" >&5
+$as_echo_n "checking for net_write in -lroken... " >&6; }
+if ${ac_cv_lib_roken_net_write+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lroken  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char net_write ();
+int
+main ()
+{
+return net_write ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_roken_net_write=yes
+else
+  ac_cv_lib_roken_net_write=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_roken_net_write" >&5
+$as_echo "$ac_cv_lib_roken_net_write" >&6; }
+if test "x$ac_cv_lib_roken_net_write" = xyes; then :
+  K5LIBS="$K5LIBS -lroken"
+fi
+
+                                        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for des_cbc_encrypt in -ldes" >&5
+$as_echo_n "checking for des_cbc_encrypt in -ldes... " >&6; }
+if ${ac_cv_lib_des_des_cbc_encrypt+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldes  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char des_cbc_encrypt ();
+int
+main ()
+{
+return des_cbc_encrypt ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_des_des_cbc_encrypt=yes
+else
+  ac_cv_lib_des_des_cbc_encrypt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_des_des_cbc_encrypt" >&5
+$as_echo "$ac_cv_lib_des_des_cbc_encrypt" >&6; }
+if test "x$ac_cv_lib_des_des_cbc_encrypt" = xyes; then :
+  K5LIBS="$K5LIBS -ldes"
+fi
+
+
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                                        K5LIBS="-lkrb5 -lk5crypto -lcom_err"
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5
+$as_echo_n "checking for library containing dn_expand... " >&6; }
+if ${ac_cv_search_dn_expand+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dn_expand ();
+int
+main ()
+{
+return dn_expand ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' resolv; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dn_expand=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dn_expand+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dn_expand+:} false; then :
+
+else
+  ac_cv_search_dn_expand=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5
+$as_echo "$ac_cv_search_dn_expand" >&6; }
+ac_res=$ac_cv_search_dn_expand
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi_krb5" >&5
+$as_echo_n "checking for gss_init_sec_context in -lgssapi_krb5... " >&6; }
+if ${ac_cv_lib_gssapi_krb5_gss_init_sec_context+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgssapi_krb5 $K5LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gss_init_sec_context ();
+int
+main ()
+{
+return gss_init_sec_context ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_gssapi_krb5_gss_init_sec_context=yes
+else
+  ac_cv_lib_gssapi_krb5_gss_init_sec_context=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&5
+$as_echo "$ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&6; }
+if test "x$ac_cv_lib_gssapi_krb5_gss_init_sec_context" = xyes; then :
+   $as_echo "#define GSSAPI 1" >>confdefs.h
+
+                                 K5LIBS="-lgssapi_krb5 $K5LIBS"
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi" >&5
+$as_echo_n "checking for gss_init_sec_context in -lgssapi... " >&6; }
+if ${ac_cv_lib_gssapi_gss_init_sec_context+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgssapi $K5LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gss_init_sec_context ();
+int
+main ()
+{
+return gss_init_sec_context ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_gssapi_gss_init_sec_context=yes
+else
+  ac_cv_lib_gssapi_gss_init_sec_context=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5
+$as_echo "$ac_cv_lib_gssapi_gss_init_sec_context" >&6; }
+if test "x$ac_cv_lib_gssapi_gss_init_sec_context" = xyes; then :
+   $as_echo "#define GSSAPI 1" >>confdefs.h
+
+                                         K5LIBS="-lgssapi $K5LIBS"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api library - build may fail" >&5
+$as_echo "$as_me: WARNING: Cannot find any suitable gss-api library - build may fail" >&2;}
+fi
+
+
+fi
+
+
+                       ac_fn_c_check_header_mongrel "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_gssapi_h" = xyes; then :
+
+else
+   unset ac_cv_header_gssapi_h
+                                 CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+                                 for ac_header in gssapi.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_gssapi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GSSAPI_H 1
+_ACEOF
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api header - build may fail" >&5
+$as_echo "$as_me: WARNING: Cannot find any suitable gss-api header - build may fail" >&2;}
+
+fi
+
+done
+
+
+
+fi
+
+
+
+                       oldCPP="$CPPFLAGS"
+                       CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+                       ac_fn_c_check_header_mongrel "$LINENO" "gssapi_krb5.h" "ac_cv_header_gssapi_krb5_h" "$ac_includes_default"
+if test "x$ac_cv_header_gssapi_krb5_h" = xyes; then :
+
+else
+   CPPFLAGS="$oldCPP"
+fi
+
+
+
+               fi
+               if test ! -z "$need_dash_r" ; then
+                       LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
+               fi
+               if test ! -z "$blibpath" ; then
+                       blibpath="$blibpath:${KRB5ROOT}/lib"
+               fi
+
+               for ac_header in gssapi.h gssapi/gssapi.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+               for ac_header in gssapi_krb5.h gssapi/gssapi_krb5.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+               for ac_header in gssapi_generic.h gssapi/gssapi_generic.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+               LIBS="$LIBS $K5LIBS"
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing k_hasafs" >&5
+$as_echo_n "checking for library containing k_hasafs... " >&6; }
+if ${ac_cv_search_k_hasafs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char k_hasafs ();
+int
+main ()
+{
+return k_hasafs ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' kafs; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_k_hasafs=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_k_hasafs+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_k_hasafs+:} false; then :
+
+else
+  ac_cv_search_k_hasafs=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_k_hasafs" >&5
+$as_echo "$ac_cv_search_k_hasafs" >&6; }
+ac_res=$ac_cv_search_k_hasafs
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define USE_AFS 1" >>confdefs.h
+
+fi
+
+       fi
+
+
+fi
+
+
+# Looking for programs, paths and files
+
+PRIVSEP_PATH=/var/empty
+
+# Check whether --with-privsep-path was given.
+if test "${with_privsep_path+set}" = set; then :
+  withval=$with_privsep_path;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       PRIVSEP_PATH=$withval
+               fi
+
+
+fi
+
+
+
+
+# Check whether --with-xauth was given.
+if test "${with_xauth+set}" = set; then :
+  withval=$with_xauth;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       xauth_path=$withval
+               fi
+
+else
+
+               TestPath="$PATH"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/bin/X11"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/X11R6/bin"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin"
+               # Extract the first word of "xauth", so it can be a program name with args.
+set dummy xauth; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_xauth_path+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $xauth_path in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_xauth_path="$xauth_path" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $TestPath
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_xauth_path="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+xauth_path=$ac_cv_path_xauth_path
+if test -n "$xauth_path"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xauth_path" >&5
+$as_echo "$xauth_path" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+               if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then
+                       xauth_path="/usr/openwin/bin/xauth"
+               fi
+
+
+fi
+
+
+STRIP_OPT=-s
+# Check whether --enable-strip was given.
+if test "${enable_strip+set}" = set; then :
+  enableval=$enable_strip;
+               if test "x$enableval" = "xno" ; then
+                       STRIP_OPT=
+               fi
+
+
+fi
+
+
+
+if test -z "$xauth_path" ; then
+       XAUTH_PATH="undefined"
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define XAUTH_PATH "$xauth_path"
+_ACEOF
+
+       XAUTH_PATH=$xauth_path
+
+fi
+
+# Check for mail directory
+
+# Check whether --with-maildir was given.
+if test "${with_maildir+set}" = set; then :
+  withval=$with_maildir;
+       if test "X$withval" != X  &&  test "x$withval" != xno  &&  \
+           test "x${withval}" != xyes; then
+
+cat >>confdefs.h <<_ACEOF
+#define MAIL_DIRECTORY "$withval"
+_ACEOF
+
+           fi
+
+else
+
+       if test "X$maildir" != "X"; then
+           cat >>confdefs.h <<_ACEOF
+#define MAIL_DIRECTORY "$maildir"
+_ACEOF
+
+       else
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking Discovering system mail directory" >&5
+$as_echo_n "checking Discovering system mail directory... " >&6; }
+           if test "$cross_compiling" = yes; then :
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&5
+$as_echo "$as_me: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&2;}
+
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_MAILLOCK_H
+#include <maillock.h>
+#endif
+#define DATA "conftest.maildir"
+
+int
+main ()
+{
+
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+#if defined (_PATH_MAILDIR)
+       if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0)
+               exit(1);
+#elif defined (MAILDIR)
+       if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0)
+               exit(1);
+#elif defined (_PATH_MAIL)
+       if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0)
+               exit(1);
+#else
+       exit (2);
+#endif
+
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+                   maildir_what=`awk -F: '{print $1}' conftest.maildir`
+                   maildir=`awk -F: '{print $2}' conftest.maildir \
+                       | sed 's|/$||'`
+                   { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using: $maildir from $maildir_what" >&5
+$as_echo "Using: $maildir from $maildir_what" >&6; }
+                   if test "x$maildir_what" != "x_PATH_MAILDIR"; then
+                       cat >>confdefs.h <<_ACEOF
+#define MAIL_DIRECTORY "$maildir"
+_ACEOF
+
+                   fi
+
+else
+
+                   if test "X$ac_status" = "X2";then
+# our test program didn't find it. Default to /var/spool/mail
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using: default value of /var/spool/mail" >&5
+$as_echo "Using: default value of /var/spool/mail" >&6; }
+                       cat >>confdefs.h <<_ACEOF
+#define MAIL_DIRECTORY "/var/spool/mail"
+_ACEOF
+
+                    else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: *** not found ***" >&5
+$as_echo "*** not found ***" >&6; }
+                    fi
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+       fi
+
+
+fi
+ # maildir
+
+if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptmx test" >&5
+$as_echo "$as_me: WARNING: cross compiling: Disabling /dev/ptmx test" >&2;}
+       disable_ptmx_check=yes
+fi
+if test -z "$no_dev_ptmx" ; then
+       if test "x$disable_ptmx_check" != "xyes" ; then
+               as_ac_File=`$as_echo "ac_cv_file_"/dev/ptmx"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptmx\"" >&5
+$as_echo_n "checking for \"/dev/ptmx\"... " >&6; }
+if eval \${$as_ac_File+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  test "$cross_compiling" = yes &&
+  as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
+if test -r ""/dev/ptmx""; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+eval ac_res=\$$as_ac_File
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DEV_PTMX 1
+_ACEOF
+
+                               have_dev_ptmx=1
+
+
+fi
+
+       fi
+fi
+
+if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then
+       as_ac_File=`$as_echo "ac_cv_file_"/dev/ptc"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptc\"" >&5
+$as_echo_n "checking for \"/dev/ptc\"... " >&6; }
+if eval \${$as_ac_File+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  test "$cross_compiling" = yes &&
+  as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
+if test -r ""/dev/ptc""; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+eval ac_res=\$$as_ac_File
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DEV_PTS_AND_PTC 1
+_ACEOF
+
+                       have_dev_ptc=1
+
+
+fi
+
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptc test" >&5
+$as_echo "$as_me: WARNING: cross compiling: Disabling /dev/ptc test" >&2;}
+fi
+
+# Options from here on. Some of these are preset by platform above
+
+# Check whether --with-mantype was given.
+if test "${with_mantype+set}" = set; then :
+  withval=$with_mantype;
+               case "$withval" in
+               man|cat|doc)
+                       MANTYPE=$withval
+                       ;;
+               *)
+                       as_fn_error $? "invalid man type: $withval" "$LINENO" 5
+                       ;;
+               esac
+
+
+fi
+
+if test -z "$MANTYPE"; then
+       TestPath="/usr/bin${PATH_SEPARATOR}/usr/ucb"
+       for ac_prog in nroff awf
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_NROFF+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $NROFF in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $TestPath
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+NROFF=$ac_cv_path_NROFF
+if test -n "$NROFF"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5
+$as_echo "$NROFF" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$NROFF" && break
+done
+test -n "$NROFF" || NROFF="/bin/false"
+
+       if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then
+               MANTYPE=doc
+       elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then
+               MANTYPE=man
+       else
+               MANTYPE=cat
+       fi
+fi
+
+if test "$MANTYPE" = "doc"; then
+       mansubdir=man;
+else
+       mansubdir=$MANTYPE;
+fi
+
+
+# Check whether to enable MD5 passwords
+MD5_MSG="no"
+
+# Check whether --with-md5-passwords was given.
+if test "${with_md5_passwords+set}" = set; then :
+  withval=$with_md5_passwords;
+               if test "x$withval" != "xno" ; then
+
+$as_echo "#define HAVE_MD5_PASSWORDS 1" >>confdefs.h
+
+                       MD5_MSG="yes"
+               fi
+
+
+fi
+
+
+# Whether to disable shadow password support
+
+# Check whether --with-shadow was given.
+if test "${with_shadow+set}" = set; then :
+  withval=$with_shadow;
+               if test "x$withval" = "xno" ; then
+                       $as_echo "#define DISABLE_SHADOW 1" >>confdefs.h
+
+                       disable_shadow=yes
+               fi
+
+
+fi
+
+
+if test -z "$disable_shadow" ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the systems has expire shadow information" >&5
+$as_echo_n "checking if the systems has expire shadow information... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <shadow.h>
+struct spwd sp;
+
+int
+main ()
+{
+ sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   sp_expire_available=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+       if test "x$sp_expire_available" = "xyes" ; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAS_SHADOW_EXPIRE 1" >>confdefs.h
+
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+fi
+
+# Use ip address instead of hostname in $DISPLAY
+if test ! -z "$IPADDR_IN_DISPLAY" ; then
+       DISPLAY_HACK_MSG="yes"
+
+$as_echo "#define IPADDR_IN_DISPLAY 1" >>confdefs.h
+
+else
+       DISPLAY_HACK_MSG="no"
+
+# Check whether --with-ipaddr-display was given.
+if test "${with_ipaddr_display+set}" = set; then :
+  withval=$with_ipaddr_display;
+                       if test "x$withval" != "xno" ; then
+                               $as_echo "#define IPADDR_IN_DISPLAY 1" >>confdefs.h
+
+                               DISPLAY_HACK_MSG="yes"
+                       fi
+
+
+fi
+
+fi
+
+# check for /etc/default/login and use it if present.
+# Check whether --enable-etc-default-login was given.
+if test "${enable_etc_default_login+set}" = set; then :
+  enableval=$enable_etc_default_login;  if test "x$enableval" = "xno"; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: /etc/default/login handling disabled" >&5
+$as_echo "$as_me: /etc/default/login handling disabled" >&6;}
+               etc_default_login=no
+         else
+               etc_default_login=yes
+         fi
+else
+   if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes";
+         then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking /etc/default/login" >&5
+$as_echo "$as_me: WARNING: cross compiling: not checking /etc/default/login" >&2;}
+               etc_default_login=no
+         else
+               etc_default_login=yes
+         fi
+
+fi
+
+
+if test "x$etc_default_login" != "xno"; then
+       as_ac_File=`$as_echo "ac_cv_file_"/etc/default/login"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/etc/default/login\"" >&5
+$as_echo_n "checking for \"/etc/default/login\"... " >&6; }
+if eval \${$as_ac_File+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  test "$cross_compiling" = yes &&
+  as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
+if test -r ""/etc/default/login""; then
+  eval "$as_ac_File=yes"
+else
+  eval "$as_ac_File=no"
+fi
+fi
+eval ac_res=\$$as_ac_File
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
+   external_path_file=/etc/default/login
+fi
+
+       if test "x$external_path_file" = "x/etc/default/login"; then
+
+$as_echo "#define HAVE_ETC_DEFAULT_LOGIN 1" >>confdefs.h
+
+       fi
+fi
+
+if test $ac_cv_func_login_getcapbool = "yes" && \
+       test $ac_cv_header_login_cap_h = "yes" ; then
+       external_path_file=/etc/login.conf
+fi
+
+# Whether to mess with the default path
+SERVER_PATH_MSG="(default)"
+
+# Check whether --with-default-path was given.
+if test "${with_default_path+set}" = set; then :
+  withval=$with_default_path;
+               if test "x$external_path_file" = "x/etc/login.conf" ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+--with-default-path=PATH has no effect on this system.
+Edit /etc/login.conf instead." >&5
+$as_echo "$as_me: WARNING:
+--with-default-path=PATH has no effect on this system.
+Edit /etc/login.conf instead." >&2;}
+               elif test "x$withval" != "xno" ; then
+                       if test ! -z "$external_path_file" ; then
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+--with-default-path=PATH will only be used if PATH is not defined in
+$external_path_file ." >&5
+$as_echo "$as_me: WARNING:
+--with-default-path=PATH will only be used if PATH is not defined in
+$external_path_file ." >&2;}
+                       fi
+                       user_path="$withval"
+                       SERVER_PATH_MSG="$withval"
+               fi
+
+else
+   if test "x$external_path_file" = "x/etc/login.conf" ; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Make sure the path to scp is in /etc/login.conf" >&5
+$as_echo "$as_me: WARNING: Make sure the path to scp is in /etc/login.conf" >&2;}
+       else
+               if test ! -z "$external_path_file" ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+If PATH is defined in $external_path_file, ensure the path to scp is included,
+otherwise scp will not work." >&5
+$as_echo "$as_me: WARNING:
+If PATH is defined in $external_path_file, ensure the path to scp is included,
+otherwise scp will not work." >&2;}
+               fi
+               if test "$cross_compiling" = yes; then :
+   user_path="/usr/bin:/bin:/usr/sbin:/sbin"
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* find out what STDPATH is */
+#include <stdio.h>
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+#ifndef _PATH_STDPATH
+# ifdef _PATH_USERPATH /* Irix */
+#  define _PATH_STDPATH _PATH_USERPATH
+# else
+#  define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
+# endif
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#define DATA "conftest.stdpath"
+
+int
+main ()
+{
+
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+       if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0)
+               exit(1);
+
+       exit(0);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+   user_path=`cat conftest.stdpath`
+else
+   user_path="/usr/bin:/bin:/usr/sbin:/sbin"
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+# make sure $bindir is in USER_PATH so scp will work
+               t_bindir=`eval echo ${bindir}`
+               case $t_bindir in
+                       NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;;
+               esac
+               case $t_bindir in
+                       NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;;
+               esac
+               echo $user_path | grep ":$t_bindir"  > /dev/null 2>&1
+               if test $? -ne 0  ; then
+                       echo $user_path | grep "^$t_bindir"  > /dev/null 2>&1
+                       if test $? -ne 0  ; then
+                               user_path=$user_path:$t_bindir
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: Adding $t_bindir to USER_PATH so scp will work" >&5
+$as_echo "Adding $t_bindir to USER_PATH so scp will work" >&6; }
+                       fi
+               fi
+       fi
+
+fi
+
+if test "x$external_path_file" != "x/etc/login.conf" ; then
+
+cat >>confdefs.h <<_ACEOF
+#define USER_PATH "$user_path"
+_ACEOF
+
+
+fi
+
+# Set superuser path separately to user path
+
+# Check whether --with-superuser-path was given.
+if test "${with_superuser_path+set}" = set; then :
+  withval=$with_superuser_path;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+
+cat >>confdefs.h <<_ACEOF
+#define SUPERUSER_PATH "$withval"
+_ACEOF
+
+                       superuser_path=$withval
+               fi
+
+
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we need to convert IPv4 in IPv6-mapped addresses" >&5
+$as_echo_n "checking if we need to convert IPv4 in IPv6-mapped addresses... " >&6; }
+IPV4_IN6_HACK_MSG="no"
+
+# Check whether --with-4in6 was given.
+if test "${with_4in6+set}" = set; then :
+  withval=$with_4in6;
+               if test "x$withval" != "xno" ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define IPV4_IN_IPV6 1" >>confdefs.h
+
+                       IPV4_IN6_HACK_MSG="yes"
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               fi
+
+else
+
+               if test "x$inet6_default_4in6" = "xyes"; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5
+$as_echo "yes (default)" >&6; }
+                       $as_echo "#define IPV4_IN_IPV6 1" >>confdefs.h
+
+                       IPV4_IN6_HACK_MSG="yes"
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (default)" >&5
+$as_echo "no (default)" >&6; }
+               fi
+
+
+fi
+
+
+# Whether to enable BSD auth support
+BSD_AUTH_MSG=no
+
+# Check whether --with-bsd-auth was given.
+if test "${with_bsd_auth+set}" = set; then :
+  withval=$with_bsd_auth;
+               if test "x$withval" != "xno" ; then
+
+$as_echo "#define BSD_AUTH 1" >>confdefs.h
+
+                       BSD_AUTH_MSG=yes
+               fi
+
+
+fi
+
+
+# Where to place sshd.pid
+piddir=/var/run
+# make sure the directory exists
+if test ! -d $piddir ; then
+       piddir=`eval echo ${sysconfdir}`
+       case $piddir in
+               NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;;
+       esac
+fi
+
+
+# Check whether --with-pid-dir was given.
+if test "${with_pid_dir+set}" = set; then :
+  withval=$with_pid_dir;
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       piddir=$withval
+                       if test ! -d $piddir ; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** no $piddir directory on this system **" >&5
+$as_echo "$as_me: WARNING: ** no $piddir directory on this system **" >&2;}
+                       fi
+               fi
+
+
+fi
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define _PATH_SSH_PIDDIR "$piddir"
+_ACEOF
+
+
+
+# Check whether --enable-lastlog was given.
+if test "${enable_lastlog+set}" = set; then :
+  enableval=$enable_lastlog;
+               if test "x$enableval" = "xno" ; then
+                       $as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+# Check whether --enable-utmp was given.
+if test "${enable_utmp+set}" = set; then :
+  enableval=$enable_utmp;
+               if test "x$enableval" = "xno" ; then
+                       $as_echo "#define DISABLE_UTMP 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+# Check whether --enable-utmpx was given.
+if test "${enable_utmpx+set}" = set; then :
+  enableval=$enable_utmpx;
+               if test "x$enableval" = "xno" ; then
+
+$as_echo "#define DISABLE_UTMPX 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+# Check whether --enable-wtmp was given.
+if test "${enable_wtmp+set}" = set; then :
+  enableval=$enable_wtmp;
+               if test "x$enableval" = "xno" ; then
+                       $as_echo "#define DISABLE_WTMP 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+# Check whether --enable-wtmpx was given.
+if test "${enable_wtmpx+set}" = set; then :
+  enableval=$enable_wtmpx;
+               if test "x$enableval" = "xno" ; then
+
+$as_echo "#define DISABLE_WTMPX 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+# Check whether --enable-libutil was given.
+if test "${enable_libutil+set}" = set; then :
+  enableval=$enable_libutil;
+               if test "x$enableval" = "xno" ; then
+                       $as_echo "#define DISABLE_LOGIN 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+# Check whether --enable-pututline was given.
+if test "${enable_pututline+set}" = set; then :
+  enableval=$enable_pututline;
+               if test "x$enableval" = "xno" ; then
+
+$as_echo "#define DISABLE_PUTUTLINE 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+# Check whether --enable-pututxline was given.
+if test "${enable_pututxline+set}" = set; then :
+  enableval=$enable_pututxline;
+               if test "x$enableval" = "xno" ; then
+
+$as_echo "#define DISABLE_PUTUTXLINE 1" >>confdefs.h
+
+               fi
+
+
+fi
+
+
+# Check whether --with-lastlog was given.
+if test "${with_lastlog+set}" = set; then :
+  withval=$with_lastlog;
+               if test "x$withval" = "xno" ; then
+                       $as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
+
+               elif test -n "$withval"  &&  test "x${withval}" != "xyes"; then
+                       conf_lastlog_location=$withval
+               fi
+
+
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines LASTLOG_FILE" >&5
+$as_echo_n "checking if your system defines LASTLOG_FILE... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_LASTLOG_H
+#  include <lastlog.h>
+#endif
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+#ifdef HAVE_LOGIN_H
+# include <login.h>
+#endif
+
+int
+main ()
+{
+ char *lastlog = LASTLOG_FILE;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines _PATH_LASTLOG" >&5
+$as_echo_n "checking if your system defines _PATH_LASTLOG... " >&6; }
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_LASTLOG_H
+#  include <lastlog.h>
+#endif
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+
+int
+main ()
+{
+ char *lastlog = _PATH_LASTLOG;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                       system_lastlog_path=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test -z "$conf_lastlog_location"; then
+       if test x"$system_lastlog_path" = x"no" ; then
+               for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do
+                               if (test -d "$f" || test -f "$f") ; then
+                                       conf_lastlog_location=$f
+                               fi
+               done
+               if test -z "$conf_lastlog_location"; then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** Cannot find lastlog **" >&5
+$as_echo "$as_me: WARNING: ** Cannot find lastlog **" >&2;}
+                                       fi
+       fi
+fi
+
+if test -n "$conf_lastlog_location"; then
+
+cat >>confdefs.h <<_ACEOF
+#define CONF_LASTLOG_FILE "$conf_lastlog_location"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines UTMP_FILE" >&5
+$as_echo_n "checking if your system defines UTMP_FILE... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+
+int
+main ()
+{
+ char *utmp = UTMP_FILE;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+         system_utmp_path=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test -z "$conf_utmp_location"; then
+       if test x"$system_utmp_path" = x"no" ; then
+               for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do
+                       if test -f $f ; then
+                               conf_utmp_location=$f
+                       fi
+               done
+               if test -z "$conf_utmp_location"; then
+                       $as_echo "#define DISABLE_UTMP 1" >>confdefs.h
+
+               fi
+       fi
+fi
+if test -n "$conf_utmp_location"; then
+
+cat >>confdefs.h <<_ACEOF
+#define CONF_UTMP_FILE "$conf_utmp_location"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMP_FILE" >&5
+$as_echo_n "checking if your system defines WTMP_FILE... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+
+int
+main ()
+{
+ char *wtmp = WTMP_FILE;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+         system_wtmp_path=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test -z "$conf_wtmp_location"; then
+       if test x"$system_wtmp_path" = x"no" ; then
+               for f in /usr/adm/wtmp /var/log/wtmp; do
+                       if test -f $f ; then
+                               conf_wtmp_location=$f
+                       fi
+               done
+               if test -z "$conf_wtmp_location"; then
+                       $as_echo "#define DISABLE_WTMP 1" >>confdefs.h
+
+               fi
+       fi
+fi
+if test -n "$conf_wtmp_location"; then
+
+cat >>confdefs.h <<_ACEOF
+#define CONF_WTMP_FILE "$conf_wtmp_location"
+_ACEOF
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMPX_FILE" >&5
+$as_echo_n "checking if your system defines WTMPX_FILE... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+
+int
+main ()
+{
+ char *wtmpx = WTMPX_FILE;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+         system_wtmpx_path=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test -z "$conf_wtmpx_location"; then
+       if test x"$system_wtmpx_path" = x"no" ; then
+               $as_echo "#define DISABLE_WTMPX 1" >>confdefs.h
+
+       fi
+else
+
+cat >>confdefs.h <<_ACEOF
+#define CONF_WTMPX_FILE "$conf_wtmpx_location"
+_ACEOF
+
+fi
+
+
+if test ! -z "$blibpath" ; then
+       LDFLAGS="$LDFLAGS $blibflags$blibpath"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&5
+$as_echo "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;}
+fi
+
+CFLAGS="$CFLAGS $werror_flags"
+
+if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
+       TEST_SSH_IPV6=no
+else
+       TEST_SSH_IPV6=yes
+fi
+ac_fn_c_check_decl "$LINENO" "BROKEN_GETADDRINFO" "ac_cv_have_decl_BROKEN_GETADDRINFO" "$ac_includes_default"
+if test "x$ac_cv_have_decl_BROKEN_GETADDRINFO" = xyes; then :
+  TEST_SSH_IPV6=no
+fi
+
+TEST_SSH_IPV6=$TEST_SSH_IPV6
+
+
+
+ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile survey.sh"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+       cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+         mv -f confcache "$cache_file"$$ &&
+         mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+         mv -f confcache "$cache_file" ;;
+       esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in #(
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by OpenSSH $as_me Portable, which was
+generated by GNU Autoconf 2.68.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <openssh-unix-dev@mindrot.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+OpenSSH config.status Portable
+configured by $0, generated by GNU Autoconf 2.68,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "buildpkg.sh") CONFIG_FILES="$CONFIG_FILES buildpkg.sh" ;;
+    "opensshd.init") CONFIG_FILES="$CONFIG_FILES opensshd.init" ;;
+    "openssh.xml") CONFIG_FILES="$CONFIG_FILES openssh.xml" ;;
+    "openbsd-compat/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/Makefile" ;;
+    "openbsd-compat/regress/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/regress/Makefile" ;;
+    "survey.sh") CONFIG_FILES="$CONFIG_FILES survey.sh" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = "\a"
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=[    ]*/{
+h
+s///
+s/^/:/
+s/[     ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[  ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[    ]*#[    ]*define[       ][      ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+         $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+       `' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+# Print summary of options
+
+# Someone please show me a better way :)
+A=`eval echo ${prefix}` ; A=`eval echo ${A}`
+B=`eval echo ${bindir}` ; B=`eval echo ${B}`
+C=`eval echo ${sbindir}` ; C=`eval echo ${C}`
+D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}`
+E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}`
+F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}`
+G=`eval echo ${piddir}` ; G=`eval echo ${G}`
+H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}`
+I=`eval echo ${user_path}` ; I=`eval echo ${I}`
+J=`eval echo ${superuser_path}` ; J=`eval echo ${J}`
+
+echo ""
+echo "OpenSSH has been configured with the following options:"
+echo "                     User binaries: $B"
+echo "                   System binaries: $C"
+echo "               Configuration files: $D"
+echo "                   Askpass program: $E"
+echo "                      Manual pages: $F"
+echo "                          PID file: $G"
+echo "  Privilege separation chroot path: $H"
+if test "x$external_path_file" = "x/etc/login.conf" ; then
+echo "   At runtime, sshd will use the path defined in $external_path_file"
+echo "   Make sure the path to scp is present, otherwise scp will not work"
+else
+echo "            sshd default user PATH: $I"
+       if test ! -z "$external_path_file"; then
+echo "   (If PATH is set in $external_path_file it will be used instead. If"
+echo "   used, ensure the path to scp is present, otherwise scp will not work.)"
+       fi
+fi
+if test ! -z "$superuser_path" ; then
+echo "          sshd superuser user PATH: $J"
+fi
+echo "                    Manpage format: $MANTYPE"
+echo "                       PAM support: $PAM_MSG"
+echo "                   OSF SIA support: $SIA_MSG"
+echo "                 KerberosV support: $KRB5_MSG"
+echo "                   SELinux support: $SELINUX_MSG"
+echo "                 Smartcard support: $SCARD_MSG"
+echo "                     S/KEY support: $SKEY_MSG"
+echo "              TCP Wrappers support: $TCPW_MSG"
+echo "              MD5 password support: $MD5_MSG"
+echo "                   libedit support: $LIBEDIT_MSG"
+echo "  Solaris process contract support: $SPC_MSG"
+echo "           Solaris project support: $SP_MSG"
+echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
+echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
+echo "                  BSD Auth support: $BSD_AUTH_MSG"
+echo "              Random number source: $RAND_MSG"
+echo "             Privsep sandbox style: $SANDBOX_STYLE"
+
+echo ""
+
+echo "              Host: ${host}"
+echo "          Compiler: ${CC}"
+echo "    Compiler flags: ${CFLAGS}"
+echo "Preprocessor flags: ${CPPFLAGS}"
+echo "      Linker flags: ${LDFLAGS}"
+echo "         Libraries: ${LIBS}"
+if test ! -z "${SSHDLIBS}"; then
+echo "         +for sshd: ${SSHDLIBS}"
+fi
+if test ! -z "${SSHLIBS}"; then
+echo "          +for ssh: ${SSHLIBS}"
+fi
+
+echo ""
+
+if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then
+       echo "SVR4 style packages are supported with \"make package\""
+       echo ""
+fi
+
+if test "x$PAM_MSG" = "xyes" ; then
+       echo "PAM is enabled. You may need to install a PAM control file "
+       echo "for sshd, otherwise password authentication may fail. "
+       echo "Example PAM control files can be found in the contrib/ "
+       echo "subdirectory"
+       echo ""
+fi
+
+if test ! -z "$NO_PEERCHECK" ; then
+       echo "WARNING: the operating system that you are using does not"
+       echo "appear to support getpeereid(), getpeerucred() or the"
+       echo "SO_PEERCRED getsockopt() option. These facilities are used to"
+       echo "enforce security checks to prevent unauthorised connections to"
+       echo "ssh-agent. Their absence increases the risk that a malicious"
+       echo "user can connect to your agent."
+       echo ""
+fi
+
+if test "$AUDIT_MODULE" = "bsm" ; then
+       echo "WARNING: BSM audit support is currently considered EXPERIMENTAL."
+       echo "See the Solaris section in README.platform for details."
+fi
diff --git a/.pc/gssapi.patch/configure.ac b/.pc/gssapi.patch/configure.ac
new file mode 100644 (file)
index 0000000..7a91527
--- /dev/null
@@ -0,0 +1,4291 @@
+# $Id: configure.ac,v 1.480 2011/08/18 04:48:24 tim Exp $
+#
+# Copyright (c) 1999-2004 Damien Miller
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org])
+AC_REVISION($Revision: 1.480 $)
+AC_CONFIG_SRCDIR([ssh.c])
+AC_LANG([C])
+
+AC_CONFIG_HEADER([config.h])
+AC_PROG_CC
+AC_CANONICAL_HOST
+AC_C_BIGENDIAN
+
+# Checks for programs.
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+AC_PROG_EGREP
+AC_PATH_PROG([AR], [ar])
+AC_PATH_PROG([CAT], [cat])
+AC_PATH_PROG([KILL], [kill])
+AC_PATH_PROGS([PERL], [perl5 perl])
+AC_PATH_PROG([SED], [sed])
+AC_SUBST([PERL])
+AC_PATH_PROG([ENT], [ent])
+AC_SUBST([ENT])
+AC_PATH_PROG([TEST_MINUS_S_SH], [bash])
+AC_PATH_PROG([TEST_MINUS_S_SH], [ksh])
+AC_PATH_PROG([TEST_MINUS_S_SH], [sh])
+AC_PATH_PROG([SH], [sh])
+AC_PATH_PROG([GROFF], [groff])
+AC_PATH_PROG([NROFF], [nroff])
+AC_PATH_PROG([MANDOC], [mandoc])
+AC_SUBST([TEST_SHELL], [sh])
+
+dnl select manpage formatter
+if test "x$MANDOC" != "x" ; then
+       MANFMT="$MANDOC"
+elif test "x$NROFF" != "x" ; then
+       MANFMT="$NROFF -mandoc"
+elif test "x$GROFF" != "x" ; then
+       MANFMT="$GROFF -mandoc -Tascii"
+else
+       AC_MSG_WARN([no manpage formatted found])
+       MANFMT="false"
+fi
+AC_SUBST([MANFMT])
+
+dnl for buildpkg.sh
+AC_PATH_PROG([PATH_GROUPADD_PROG], [groupadd], [groupadd],
+       [/usr/sbin${PATH_SEPARATOR}/etc])
+AC_PATH_PROG([PATH_USERADD_PROG], [useradd], [useradd],
+       [/usr/sbin${PATH_SEPARATOR}/etc])
+AC_CHECK_PROG([MAKE_PACKAGE_SUPPORTED], [pkgmk], [yes], [no])
+if test -x /sbin/sh; then
+       AC_SUBST([STARTUP_SCRIPT_SHELL], [/sbin/sh])
+else
+       AC_SUBST([STARTUP_SCRIPT_SHELL], [/bin/sh])
+fi
+
+# System features
+AC_SYS_LARGEFILE
+
+if test -z "$AR" ; then
+       AC_MSG_ERROR([*** 'ar' missing, please install or fix your \$PATH ***])
+fi
+
+# Use LOGIN_PROGRAM from environment if possible
+if test ! -z "$LOGIN_PROGRAM" ; then
+       AC_DEFINE_UNQUOTED([LOGIN_PROGRAM_FALLBACK], ["$LOGIN_PROGRAM"],
+               [If your header files don't define LOGIN_PROGRAM,
+               then use this (detected) from environment and PATH])
+else
+       # Search for login
+       AC_PATH_PROG([LOGIN_PROGRAM_FALLBACK], [login])
+       if test ! -z "$LOGIN_PROGRAM_FALLBACK" ; then
+               AC_DEFINE_UNQUOTED([LOGIN_PROGRAM_FALLBACK], ["$LOGIN_PROGRAM_FALLBACK"])
+       fi
+fi
+
+AC_PATH_PROG([PATH_PASSWD_PROG], [passwd])
+if test ! -z "$PATH_PASSWD_PROG" ; then
+       AC_DEFINE_UNQUOTED([_PATH_PASSWD_PROG], ["$PATH_PASSWD_PROG"],
+               [Full path of your "passwd" program])
+fi
+
+if test -z "$LD" ; then
+       LD=$CC
+fi
+AC_SUBST([LD])
+
+AC_C_INLINE
+
+AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include <limits.h>])
+AC_CHECK_DECL([SYSTR_POLICY_KILL], [have_systr_policy_kill=1], , [
+       #include <sys/types.h>
+       #include <sys/param.h>
+       #include <dev/systrace.h>
+])
+AC_CHECK_DECL([RLIMIT_NPROC],
+    [AC_DEFINE([HAVE_RLIMIT_NPROC], [], [sys/resource.h has RLIMIT_NPROC])], , [
+       #include <sys/types.h>
+       #include <sys/resource.h>
+])
+
+use_stack_protector=1
+AC_ARG_WITH([stackprotect],
+    [  --without-stackprotect  Don't use compiler's stack protection], [
+    if test "x$withval" = "xno"; then
+       use_stack_protector=0
+    fi ])
+
+
+if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
+       OSSH_CHECK_CFLAG_COMPILE([-Wall])
+       OSSH_CHECK_CFLAG_COMPILE([-Wpointer-arith])
+       OSSH_CHECK_CFLAG_COMPILE([-Wuninitialized])
+       OSSH_CHECK_CFLAG_COMPILE([-Wsign-compare])
+       OSSH_CHECK_CFLAG_COMPILE([-Wformat-security])
+       OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign])
+       OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result])
+       OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing])
+       AC_MSG_CHECKING([gcc version])
+       GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'`
+       case $GCC_VER in
+               1.*) no_attrib_nonnull=1 ;;
+               2.8* | 2.9*)
+                    no_attrib_nonnull=1
+                    ;;
+               2.*) no_attrib_nonnull=1 ;;
+               *) ;;
+       esac
+       AC_MSG_RESULT([$GCC_VER])
+
+       AC_MSG_CHECKING([if $CC accepts -fno-builtin-memset])
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -fno-builtin-memset"
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <string.h> ]],
+                       [[ char b[10]; memset(b, 0, sizeof(b)); ]])],
+               [ AC_MSG_RESULT([yes]) ],
+               [ AC_MSG_RESULT([no])
+                 CFLAGS="$saved_CFLAGS" ]
+       )
+
+       # -fstack-protector-all doesn't always work for some GCC versions
+       # and/or platforms, so we test if we can.  If it's not supported
+       # on a given platform gcc will emit a warning so we use -Werror.
+       if test "x$use_stack_protector" = "x1"; then
+           for t in -fstack-protector-all -fstack-protector; do
+               AC_MSG_CHECKING([if $CC supports $t])
+               saved_CFLAGS="$CFLAGS"
+               saved_LDFLAGS="$LDFLAGS"
+               CFLAGS="$CFLAGS $t -Werror"
+               LDFLAGS="$LDFLAGS $t -Werror"
+               AC_LINK_IFELSE(
+                       [AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+                       [[
+       char x[256];
+       snprintf(x, sizeof(x), "XXX");
+                        ]])],
+                   [ AC_MSG_RESULT([yes])
+                     CFLAGS="$saved_CFLAGS $t"
+                     LDFLAGS="$saved_LDFLAGS $t"
+                     AC_MSG_CHECKING([if $t works])
+                     AC_RUN_IFELSE(
+                       [AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+                       [[
+       char x[256];
+       snprintf(x, sizeof(x), "XXX");
+                       ]])],
+                       [ AC_MSG_RESULT([yes])
+                         break ],
+                       [ AC_MSG_RESULT([no]) ],
+                       [ AC_MSG_WARN([cross compiling: cannot test])
+                         break ]
+                     )
+                   ],
+                   [ AC_MSG_RESULT([no]) ]
+               )
+               CFLAGS="$saved_CFLAGS"
+               LDFLAGS="$saved_LDFLAGS"
+           done
+       fi
+
+       if test -z "$have_llong_max"; then
+               # retry LLONG_MAX with -std=gnu99, needed on some Linuxes
+               unset ac_cv_have_decl_LLONG_MAX
+               saved_CFLAGS="$CFLAGS"
+               CFLAGS="$CFLAGS -std=gnu99"
+               AC_CHECK_DECL([LLONG_MAX],
+                   [have_llong_max=1],
+                   [CFLAGS="$saved_CFLAGS"],
+                   [#include <limits.h>]
+               )
+       fi
+fi
+
+if test "x$no_attrib_nonnull" != "x1" ; then
+       AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull])
+fi
+
+AC_ARG_WITH([rpath],
+       [  --without-rpath         Disable auto-added -R linker paths],
+       [
+               if test "x$withval" = "xno" ; then
+                       need_dash_r=""
+               fi
+               if test "x$withval" = "xyes" ; then
+                       need_dash_r=1
+               fi
+       ]
+)
+
+# Allow user to specify flags
+AC_ARG_WITH([cflags],
+       [  --with-cflags           Specify additional flags to pass to compiler],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       CFLAGS="$CFLAGS $withval"
+               fi
+       ]
+)
+AC_ARG_WITH([cppflags],
+       [  --with-cppflags         Specify additional flags to pass to preprocessor] ,
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       CPPFLAGS="$CPPFLAGS $withval"
+               fi
+       ]
+)
+AC_ARG_WITH([ldflags],
+       [  --with-ldflags          Specify additional flags to pass to linker],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       LDFLAGS="$LDFLAGS $withval"
+               fi
+       ]
+)
+AC_ARG_WITH([libs],
+       [  --with-libs             Specify additional libraries to link with],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       LIBS="$LIBS $withval"
+               fi
+       ]
+)
+AC_ARG_WITH([Werror],
+       [  --with-Werror           Build main code with -Werror],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"; then
+                       werror_flags="-Werror"
+                       if test "x${withval}" != "xyes"; then
+                               werror_flags="$withval"
+                       fi
+               fi
+       ]
+)
+
+AC_CHECK_HEADERS([ \
+       bstring.h \
+       crypt.h \
+       crypto/sha2.h \
+       dirent.h \
+       endian.h \
+       features.h \
+       fcntl.h \
+       floatingpoint.h \
+       getopt.h \
+       glob.h \
+       ia.h \
+       iaf.h \
+       limits.h \
+       login.h \
+       maillock.h \
+       ndir.h \
+       net/if_tun.h \
+       netdb.h \
+       netgroup.h \
+       pam/pam_appl.h \
+       paths.h \
+       poll.h \
+       pty.h \
+       readpassphrase.h \
+       rpc/types.h \
+       security/pam_appl.h \
+       sha2.h \
+       shadow.h \
+       stddef.h \
+       stdint.h \
+       string.h \
+       strings.h \
+       sys/audit.h \
+       sys/bitypes.h \
+       sys/bsdtty.h \
+       sys/cdefs.h \
+       sys/dir.h \
+       sys/mman.h \
+       sys/ndir.h \
+       sys/poll.h \
+       sys/prctl.h \
+       sys/pstat.h \
+       sys/select.h \
+       sys/stat.h \
+       sys/stream.h \
+       sys/stropts.h \
+       sys/strtio.h \
+       sys/statvfs.h \
+       sys/sysmacros.h \
+       sys/time.h \
+       sys/timers.h \
+       sys/un.h \
+       time.h \
+       tmpdir.h \
+       ttyent.h \
+       ucred.h \
+       unistd.h \
+       usersec.h \
+       util.h \
+       utime.h \
+       utmp.h \
+       utmpx.h \
+       vis.h \
+])
+
+# lastlog.h requires sys/time.h to be included first on Solaris
+AC_CHECK_HEADERS([lastlog.h], [], [], [
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+])
+
+# sys/ptms.h requires sys/stream.h to be included first on Solaris
+AC_CHECK_HEADERS([sys/ptms.h], [], [], [
+#ifdef HAVE_SYS_STREAM_H
+# include <sys/stream.h>
+#endif
+])
+
+# login_cap.h requires sys/types.h on NetBSD
+AC_CHECK_HEADERS([login_cap.h], [], [], [
+#include <sys/types.h>
+])
+
+# older BSDs need sys/param.h before sys/mount.h
+AC_CHECK_HEADERS([sys/mount.h], [], [], [
+#include <sys/param.h>
+])
+
+# Messages for features tested for in target-specific section
+SIA_MSG="no"
+SPC_MSG="no"
+SP_MSG="no"
+
+# Check for some target-specific stuff
+case "$host" in
+*-*-aix*)
+       # Some versions of VAC won't allow macro redefinitions at
+       # -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that
+       # particularly with older versions of vac or xlc.
+       # It also throws errors about null macro argments, but these are
+       # not fatal.
+       AC_MSG_CHECKING([if compiler allows macro redefinitions])
+       AC_COMPILE_IFELSE(
+           [AC_LANG_PROGRAM([[
+#define testmacro foo
+#define testmacro bar]],
+           [[ exit(0); ]])],
+           [ AC_MSG_RESULT([yes]) ],
+           [ AC_MSG_RESULT([no])
+             CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`"
+             LD="`echo $LD | sed 's/-qlanglvl\=ansi//g'`"
+             CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`"
+             CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`"
+           ]
+       )
+
+       AC_MSG_CHECKING([how to specify blibpath for linker ($LD)])
+       if (test -z "$blibpath"); then
+               blibpath="/usr/lib:/lib"
+       fi
+       saved_LDFLAGS="$LDFLAGS"
+       if test "$GCC" = "yes"; then
+               flags="-Wl,-blibpath: -Wl,-rpath, -blibpath:"
+       else
+               flags="-blibpath: -Wl,-blibpath: -Wl,-rpath,"
+       fi
+       for tryflags in $flags ;do
+               if (test -z "$blibflags"); then
+                       LDFLAGS="$saved_LDFLAGS $tryflags$blibpath"
+                       AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
+                       [blibflags=$tryflags], [])
+               fi
+       done
+       if (test -z "$blibflags"); then
+               AC_MSG_RESULT([not found])
+               AC_MSG_ERROR([*** must be able to specify blibpath on AIX - check config.log])
+       else
+               AC_MSG_RESULT([$blibflags])
+       fi
+       LDFLAGS="$saved_LDFLAGS"
+       dnl Check for authenticate.  Might be in libs.a on older AIXes
+       AC_CHECK_FUNC([authenticate], [AC_DEFINE([WITH_AIXAUTHENTICATE], [1],
+               [Define if you want to enable AIX4's authenticate function])],
+               [AC_CHECK_LIB([s], [authenticate],
+                       [ AC_DEFINE([WITH_AIXAUTHENTICATE])
+                               LIBS="$LIBS -ls"
+                       ])
+               ])
+       dnl Check for various auth function declarations in headers.
+       AC_CHECK_DECLS([authenticate, loginrestrictions, loginsuccess,
+           passwdexpired, setauthdb], , , [#include <usersec.h>])
+       dnl Check if loginfailed is declared and takes 4 arguments (AIX >= 5.2)
+       AC_CHECK_DECLS([loginfailed],
+           [AC_MSG_CHECKING([if loginfailed takes 4 arguments])
+           AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <usersec.h> ]],
+               [[ (void)loginfailed("user","host","tty",0); ]])],
+               [AC_MSG_RESULT([yes])
+               AC_DEFINE([AIX_LOGINFAILED_4ARG], [1],
+                       [Define if your AIX loginfailed() function
+                       takes 4 arguments (AIX >= 5.2)])], [AC_MSG_RESULT([no])
+           ])],
+           [],
+           [#include <usersec.h>]
+       )
+       AC_CHECK_FUNCS([getgrset setauthdb])
+       AC_CHECK_DECL([F_CLOSEM],
+           AC_DEFINE([HAVE_FCNTL_CLOSEM], [1], [Use F_CLOSEM fcntl for closefrom]),
+           [],
+           [ #include <limits.h>
+             #include <fcntl.h> ]
+       )
+       check_for_aix_broken_getaddrinfo=1
+       AC_DEFINE([BROKEN_REALPATH], [1], [Define if you have a broken realpath.])
+       AC_DEFINE([SETEUID_BREAKS_SETUID], [1],
+           [Define if your platform breaks doing a seteuid before a setuid])
+       AC_DEFINE([BROKEN_SETREUID], [1], [Define if your setreuid() is broken])
+       AC_DEFINE([BROKEN_SETREGID], [1], [Define if your setregid() is broken])
+       dnl AIX handles lastlog as part of its login message
+       AC_DEFINE([DISABLE_LASTLOG], [1], [Define if you don't want to use lastlog])
+       AC_DEFINE([LOGIN_NEEDS_UTMPX], [1],
+               [Some systems need a utmpx entry for /bin/login to work])
+       AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV],
+               [Define to a Set Process Title type if your system is
+               supported by bsd-setproctitle.c])
+       AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1],
+           [AIX 5.2 and 5.3 (and presumably newer) require this])
+       AC_DEFINE([PTY_ZEROREAD], [1], [read(1) can return 0 for a non-closed fd])
+       ;;
+*-*-cygwin*)
+       check_for_libcrypt_later=1
+       LIBS="$LIBS /usr/lib/textreadmode.o"
+       AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin])
+       AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()])
+       AC_DEFINE([DISABLE_SHADOW], [1],
+               [Define if you want to disable shadow passwords])
+       AC_DEFINE([NO_X11_UNIX_SOCKETS], [1],
+               [Define if X11 doesn't support AF_UNIX sockets on that system])
+       AC_DEFINE([NO_IPPORT_RESERVED_CONCEPT], [1],
+               [Define if the concept of ports only accessible to
+               superusers isn't known])
+       AC_DEFINE([DISABLE_FD_PASSING], [1],
+               [Define if your platform needs to skip post auth
+               file descriptor passing])
+       AC_DEFINE([SSH_IOBUFSZ], [65535], [Windows is sensitive to read buffer size])
+       AC_DEFINE([FILESYSTEM_NO_BACKSLASH], [1], [File names may not contain backslash characters]) 
+       ;;
+*-*-dgux*)
+       AC_DEFINE([IP_TOS_IS_BROKEN], [1],
+               [Define if your system choked on IP TOS setting])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       ;;
+*-*-darwin*)
+       AC_MSG_CHECKING([if we have working getaddrinfo])
+       AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include <mach-o/dyld.h>
+main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
+               exit(0);
+       else
+               exit(1);
+}
+                       ]])],
+       [AC_MSG_RESULT([working])],
+       [AC_MSG_RESULT([buggy])
+       AC_DEFINE([BROKEN_GETADDRINFO], [1],
+               [getaddrinfo is broken (if present)])
+       ],
+       [AC_MSG_RESULT([assume it is working])])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect])
+       AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1],
+               [Define if your resolver libs need this for getrrsetbyname])
+       AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
+       AC_DEFINE([SSH_TUN_COMPAT_AF], [1],
+           [Use tunnel device compatibility to OpenBSD])
+       AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
+           [Prepend the address family to IP tunnel traffic])
+       m4_pattern_allow([AU_IPv])
+       AC_CHECK_DECL([AU_IPv4], [], 
+           AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
+           [#include <bsm/audit.h>]
+       AC_DEFINE([LASTLOG_WRITE_PUTUTXLINE], [1],
+           [Define if pututxline updates lastlog too])
+       )
+       AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV],
+               [Define to a Set Process Title type if your system is
+               supported by bsd-setproctitle.c])
+       AC_CHECK_FUNCS([sandbox_init])
+       AC_CHECK_HEADERS([sandbox.h])
+       ;;
+*-*-dragonfly*)
+       SSHDLIBS="$SSHDLIBS -lcrypt"
+       ;;
+*-*-haiku*) 
+    LIBS="$LIBS -lbsd "
+    AC_CHECK_LIB([network], [socket])
+    AC_DEFINE([HAVE_U_INT64_T])
+    MANTYPE=man 
+    ;; 
+*-*-hpux*)
+       # first we define all of the options common to all HP-UX releases
+       CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
+       IPADDR_IN_DISPLAY=yes
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([LOGIN_NO_ENDOPT], [1],
+           [Define if your login program cannot handle end of options ("--")])
+       AC_DEFINE([LOGIN_NEEDS_UTMPX])
+       AC_DEFINE([LOCKED_PASSWD_STRING], ["*"],
+               [String used in /etc/passwd to denote locked account])
+       AC_DEFINE([SPT_TYPE], [SPT_PSTAT])
+       maildir="/var/mail"
+       LIBS="$LIBS -lsec"
+       AC_CHECK_LIB([xnet], [t_error], ,
+           [AC_MSG_ERROR([*** -lxnet needed on HP-UX - check config.log ***])])
+
+       # next, we define all of the options specific to major releases
+       case "$host" in
+       *-*-hpux10*)
+               if test -z "$GCC"; then
+                       CFLAGS="$CFLAGS -Ae"
+               fi
+               ;;
+       *-*-hpux11*)
+               AC_DEFINE([PAM_SUN_CODEBASE], [1],
+                       [Define if you are using Solaris-derived PAM which
+                       passes pam_messages to the conversation function
+                       with an extra level of indirection])
+               AC_DEFINE([DISABLE_UTMP], [1],
+                       [Define if you don't want to use utmp])
+               AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins])
+               check_for_hpux_broken_getaddrinfo=1
+               check_for_conflicting_getspnam=1
+               ;;
+       esac
+
+       # lastly, we define options specific to minor releases
+       case "$host" in
+       *-*-hpux10.26)
+               AC_DEFINE([HAVE_SECUREWARE], [1],
+                       [Define if you have SecureWare-based
+                       protected password database])
+               disable_ptmx_check=yes
+               LIBS="$LIBS -lsecpw"
+               ;;
+       esac
+       ;;
+*-*-irix5*)
+       PATH="$PATH:/usr/etc"
+       AC_DEFINE([BROKEN_INET_NTOA], [1],
+               [Define if you system's inet_ntoa is busted
+               (e.g. Irix gcc issue)])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([WITH_ABBREV_NO_TTY], [1],
+               [Define if you shouldn't strip 'tty' from your
+               ttyname in [uw]tmp])
+       AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
+       ;;
+*-*-irix6*)
+       PATH="$PATH:/usr/etc"
+       AC_DEFINE([WITH_IRIX_ARRAY], [1],
+               [Define if you have/want arrays
+               (cluster-wide session managment, not C arrays)])
+       AC_DEFINE([WITH_IRIX_PROJECT], [1],
+               [Define if you want IRIX project management])
+       AC_DEFINE([WITH_IRIX_AUDIT], [1],
+               [Define if you want IRIX audit trails])
+       AC_CHECK_FUNC([jlimit_startjob], [AC_DEFINE([WITH_IRIX_JOBS], [1],
+               [Define if you want IRIX kernel jobs])])
+       AC_DEFINE([BROKEN_INET_NTOA])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([BROKEN_UPDWTMPX], [1], [updwtmpx is broken (if present)])
+       AC_DEFINE([WITH_ABBREV_NO_TTY])
+       AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
+       ;;
+*-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
+       check_for_libcrypt_later=1
+       AC_DEFINE([PAM_TTY_KLUDGE])
+       AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"])
+       AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV])
+       AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts])
+       AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins])
+       ;;
+*-*-linux*)
+       no_dev_ptmx=1
+       check_for_libcrypt_later=1
+       check_for_openpty_ctty_bug=1
+       AC_DEFINE([PAM_TTY_KLUDGE], [1],
+               [Work around problematic Linux PAM modules handling of PAM_TTY])
+       AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"],
+               [String used in /etc/passwd to denote locked account])
+       AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV])
+       AC_DEFINE([LINK_OPNOTSUPP_ERRNO], [EPERM],
+               [Define to whatever link() returns for "not supported"
+               if it doesn't return EOPNOTSUPP.])
+       AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts])
+       AC_DEFINE([USE_BTMP])
+       AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer])
+       inet6_default_4in6=yes
+       case `uname -r` in
+       1.*|2.0.*)
+               AC_DEFINE([BROKEN_CMSG_TYPE], [1],
+                       [Define if cmsg_type is not passed correctly])
+               ;;
+       esac
+       # tun(4) forwarding compat code
+       AC_CHECK_HEADERS([linux/if_tun.h])
+       if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then
+               AC_DEFINE([SSH_TUN_LINUX], [1],
+                   [Open tunnel devices the Linux tun/tap way])
+               AC_DEFINE([SSH_TUN_COMPAT_AF], [1],
+                   [Use tunnel device compatibility to OpenBSD])
+               AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
+                   [Prepend the address family to IP tunnel traffic])
+       fi
+       ;;
+mips-sony-bsd|mips-sony-newsos4)
+       AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to acquire controlling tty])
+       SONY=1
+       ;;
+*-*-netbsd*)
+       check_for_libcrypt_before=1
+       if test "x$withval" != "xno" ; then
+               need_dash_r=1
+       fi
+       AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
+       AC_CHECK_HEADER([net/if_tap.h], ,
+           AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support]))
+       AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
+           [Prepend the address family to IP tunnel traffic])
+       ;;
+*-*-freebsd*)
+       check_for_libcrypt_later=1
+       AC_DEFINE([LOCKED_PASSWD_PREFIX], ["*LOCKED*"], [Account locked with pw(1)])
+       AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
+       AC_CHECK_HEADER([net/if_tap.h], ,
+           AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support]))
+       AC_DEFINE([BROKEN_GLOB], [1], [FreeBSD glob does not do what we need])
+       ;;
+*-*-bsdi*)
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       ;;
+*-next-*)
+       conf_lastlog_location="/usr/adm/lastlog"
+       conf_utmp_location=/etc/utmp
+       conf_wtmp_location=/usr/adm/wtmp
+       maildir=/usr/spool/mail
+       AC_DEFINE([HAVE_NEXT], [1], [Define if you are on NeXT])
+       AC_DEFINE([BROKEN_REALPATH])
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([BROKEN_SAVED_UIDS], [1], [Needed for NeXT])
+       ;;
+*-*-openbsd*)
+       AC_DEFINE([HAVE_ATTRIBUTE__SENTINEL__], [1], [OpenBSD's gcc has sentinel])
+       AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD's gcc has bounded])
+       AC_DEFINE([SSH_TUN_OPENBSD], [1], [Open tunnel devices the OpenBSD way])
+       AC_DEFINE([SYSLOG_R_SAFE_IN_SIGHAND], [1],
+           [syslog_r function is safe to use in in a signal handler])
+       ;;
+*-*-solaris*)
+       if test "x$withval" != "xno" ; then
+               need_dash_r=1
+       fi
+       AC_DEFINE([PAM_SUN_CODEBASE])
+       AC_DEFINE([LOGIN_NEEDS_UTMPX])
+       AC_DEFINE([LOGIN_NEEDS_TERM], [1],
+               [Some versions of /bin/login need the TERM supplied
+               on the commandline])
+       AC_DEFINE([PAM_TTY_KLUDGE])
+       AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1],
+               [Define if pam_chauthtok wants real uid set
+               to the unpriv'ed user])
+       AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
+       # Pushing STREAMS modules will cause sshd to acquire a controlling tty.
+       AC_DEFINE([SSHD_ACQUIRES_CTTY], [1],
+               [Define if sshd somehow reacquires a controlling TTY
+               after setsid()])
+       AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd
+               in case the name is longer than 8 chars])
+       AC_DEFINE([BROKEN_TCGETATTR_ICANON], [1], [tcgetattr with ICANON may hang])
+       external_path_file=/etc/default/login
+       # hardwire lastlog location (can't detect it on some versions)
+       conf_lastlog_location="/var/adm/lastlog"
+       AC_MSG_CHECKING([for obsolete utmp and wtmp in solaris2.x])
+       sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'`
+       if test "$sol2ver" -ge 8; then
+               AC_MSG_RESULT([yes])
+               AC_DEFINE([DISABLE_UTMP])
+               AC_DEFINE([DISABLE_WTMP], [1],
+                       [Define if you don't want to use wtmp])
+       else
+               AC_MSG_RESULT([no])
+       fi
+       AC_ARG_WITH([solaris-contracts],
+               [  --with-solaris-contracts Enable Solaris process contracts (experimental)],
+               [
+               AC_CHECK_LIB([contract], [ct_tmpl_activate],
+                       [ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1],
+                               [Define if you have Solaris process contracts])
+                         SSHDLIBS="$SSHDLIBS -lcontract"
+                         SPC_MSG="yes" ], )
+               ],
+       )
+       AC_ARG_WITH([solaris-projects],
+               [  --with-solaris-projects Enable Solaris projects (experimental)],
+               [
+               AC_CHECK_LIB([project], [setproject],
+                       [ AC_DEFINE([USE_SOLARIS_PROJECTS], [1],
+                               [Define if you have Solaris projects])
+                       SSHDLIBS="$SSHDLIBS -lproject"
+                       SP_MSG="yes" ], )
+               ],
+       )
+       ;;
+*-*-sunos4*)
+       CPPFLAGS="$CPPFLAGS -DSUNOS4"
+       AC_CHECK_FUNCS([getpwanam])
+       AC_DEFINE([PAM_SUN_CODEBASE])
+       conf_utmp_location=/etc/utmp
+       conf_wtmp_location=/var/adm/wtmp
+       conf_lastlog_location=/var/adm/lastlog
+       AC_DEFINE([USE_PIPES])
+       ;;
+*-ncr-sysv*)
+       LIBS="$LIBS -lc89"
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([SSHD_ACQUIRES_CTTY])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       ;;
+*-sni-sysv*)
+       # /usr/ucblib MUST NOT be searched on ReliantUNIX
+       AC_CHECK_LIB([dl], [dlsym], ,)
+       # -lresolv needs to be at the end of LIBS or DNS lookups break
+       AC_CHECK_LIB([resolv], [res_query], [ LIBS="$LIBS -lresolv" ])
+       IPADDR_IN_DISPLAY=yes
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([IP_TOS_IS_BROKEN])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([SSHD_ACQUIRES_CTTY])
+       external_path_file=/etc/default/login
+       # /usr/ucblib/libucb.a no longer needed on ReliantUNIX
+       # Attention: always take care to bind libsocket and libnsl before libc,
+       # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog
+       ;;
+# UnixWare 1.x, UnixWare 2.x, and others based on code from Univel.
+*-*-sysv4.2*)
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd])
+       AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
+       ;;
+# UnixWare 7.x, OpenUNIX 8
+*-*-sysv5*)
+       CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf"
+       AC_DEFINE([UNIXWARE_LONG_PASSWORDS], [1], [Support passwords > 8 chars])
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_GETADDRINFO])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([PASSWD_NEEDS_USERNAME])
+       case "$host" in
+       *-*-sysv5SCO_SV*)       # SCO OpenServer 6.x
+               maildir=/var/spool/mail
+               TEST_SHELL=/u95/bin/sh
+               AC_DEFINE([BROKEN_LIBIAF], [1],
+                       [ia_uinfo routines not supported by OS yet])
+               AC_DEFINE([BROKEN_UPDWTMPX])
+               AC_CHECK_LIB([prot], [getluid], [ LIBS="$LIBS -lprot"
+                       AC_CHECK_FUNCS([getluid setluid], , , [-lprot])
+                       AC_DEFINE([HAVE_SECUREWARE])
+                       AC_DEFINE([DISABLE_SHADOW])
+                       ], , )
+               ;;
+       *)      AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
+               check_for_libcrypt_later=1
+               ;;
+       esac
+       ;;
+*-*-sysv*)
+       ;;
+# SCO UNIX and OEM versions of SCO UNIX
+*-*-sco3.2v4*)
+       AC_MSG_ERROR("This Platform is no longer supported.")
+       ;;
+# SCO OpenServer 5.x
+*-*-sco3.2v5*)
+       if test -z "$GCC"; then
+               CFLAGS="$CFLAGS -belf"
+       fi
+       LIBS="$LIBS -lprot -lx -ltinfo -lm"
+       no_dev_ptmx=1
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([HAVE_SECUREWARE])
+       AC_DEFINE([DISABLE_SHADOW])
+       AC_DEFINE([DISABLE_FD_PASSING])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_GETADDRINFO])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([WITH_ABBREV_NO_TTY])
+       AC_DEFINE([BROKEN_UPDWTMPX])
+       AC_DEFINE([PASSWD_NEEDS_USERNAME])
+       AC_CHECK_FUNCS([getluid setluid])
+       MANTYPE=man
+       TEST_SHELL=ksh
+       ;;
+*-*-unicosmk*)
+       AC_DEFINE([NO_SSH_LASTLOG], [1],
+               [Define if you don't want to use lastlog in session.c])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([DISABLE_FD_PASSING])
+       LDFLAGS="$LDFLAGS"
+       LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
+       MANTYPE=cat
+       ;;
+*-*-unicosmp*)
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([WITH_ABBREV_NO_TTY])
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([DISABLE_FD_PASSING])
+       LDFLAGS="$LDFLAGS"
+       LIBS="$LIBS -lgen -lacid -ldb"
+       MANTYPE=cat
+       ;;
+*-*-unicos*)
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([DISABLE_FD_PASSING])
+       AC_DEFINE([NO_SSH_LASTLOG])
+       LDFLAGS="$LDFLAGS -Wl,-Dmsglevel=334:fatal"
+       LIBS="$LIBS -lgen -lrsc -lshare -luex -lacm"
+       MANTYPE=cat
+       ;;
+*-dec-osf*)
+       AC_MSG_CHECKING([for Digital Unix SIA])
+       no_osfsia=""
+       AC_ARG_WITH([osfsia],
+               [  --with-osfsia           Enable Digital Unix SIA],
+               [
+                       if test "x$withval" = "xno" ; then
+                               AC_MSG_RESULT([disabled])
+                               no_osfsia=1
+                       fi
+               ],
+       )
+       if test -z "$no_osfsia" ; then
+               if test -f /etc/sia/matrix.conf; then
+                       AC_MSG_RESULT([yes])
+                       AC_DEFINE([HAVE_OSF_SIA], [1],
+                               [Define if you have Digital Unix Security
+                               Integration Architecture])
+                       AC_DEFINE([DISABLE_LOGIN], [1],
+                               [Define if you don't want to use your
+                               system's login() call])
+                       AC_DEFINE([DISABLE_FD_PASSING])
+                       LIBS="$LIBS -lsecurity -ldb -lm -laud"
+                       SIA_MSG="yes"
+               else
+                       AC_MSG_RESULT([no])
+                       AC_DEFINE([LOCKED_PASSWD_SUBSTR], ["Nologin"],
+                         [String used in /etc/passwd to denote locked account])
+               fi
+       fi
+       AC_DEFINE([BROKEN_GETADDRINFO])
+       AC_DEFINE([SETEUID_BREAKS_SETUID])
+       AC_DEFINE([BROKEN_SETREUID])
+       AC_DEFINE([BROKEN_SETREGID])
+       AC_DEFINE([BROKEN_READV_COMPARISON], [1], [Can't do comparisons on readv])
+       ;;
+
+*-*-nto-qnx*)
+       AC_DEFINE([USE_PIPES])
+       AC_DEFINE([NO_X11_UNIX_SOCKETS])
+       AC_DEFINE([MISSING_NFDBITS], [1], [Define on *nto-qnx systems])
+       AC_DEFINE([MISSING_HOWMANY], [1], [Define on *nto-qnx systems])
+       AC_DEFINE([MISSING_FD_MASK], [1], [Define on *nto-qnx systems])
+       AC_DEFINE([DISABLE_LASTLOG])
+       AC_DEFINE([SSHD_ACQUIRES_CTTY])
+       AC_DEFINE([BROKEN_SHADOW_EXPIRE], [1], [QNX shadow support is broken])
+       enable_etc_default_login=no     # has incompatible /etc/default/login
+       case "$host" in
+       *-*-nto-qnx6*)
+               AC_DEFINE([DISABLE_FD_PASSING])
+               ;;
+       esac
+       ;;
+
+*-*-ultrix*)
+       AC_DEFINE([BROKEN_GETGROUPS], [1], [getgroups(0,NULL) will return -1])
+       AC_DEFINE([BROKEN_MMAP], [1], [Ultrix mmap can't map files])
+       AC_DEFINE([NEED_SETPGRP])
+       AC_DEFINE([HAVE_SYS_SYSLOG_H], [1], [Force use of sys/syslog.h on Ultrix])
+       ;;
+
+*-*-lynxos)
+        CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"
+       AC_DEFINE([MISSING_HOWMANY])
+        AC_DEFINE([BROKEN_SETVBUF], [1], [LynxOS has broken setvbuf() implementation])
+        ;;
+esac
+
+AC_MSG_CHECKING([compiler and flags for sanity])
+AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]], [[ exit(0); ]])],
+       [       AC_MSG_RESULT([yes]) ],
+       [
+               AC_MSG_RESULT([no])
+               AC_MSG_ERROR([*** compiler cannot create working executables, check config.log ***])
+       ],
+       [       AC_MSG_WARN([cross compiling: not checking compiler sanity]) ]
+)
+
+dnl Checks for header files.
+# Checks for libraries.
+AC_CHECK_FUNC([yp_match], , [AC_CHECK_LIB([nsl], [yp_match])])
+AC_CHECK_FUNC([setsockopt], , [AC_CHECK_LIB([socket], [setsockopt])])
+
+dnl IRIX and Solaris 2.5.1 have dirname() in libgen
+AC_CHECK_FUNCS([dirname], [AC_CHECK_HEADERS([libgen.h])] , [
+       AC_CHECK_LIB([gen], [dirname], [
+               AC_CACHE_CHECK([for broken dirname],
+                       ac_cv_have_broken_dirname, [
+                       save_LIBS="$LIBS"
+                       LIBS="$LIBS -lgen"
+                       AC_RUN_IFELSE(
+                               [AC_LANG_SOURCE([[
+#include <libgen.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+    char *s, buf[32];
+
+    strncpy(buf,"/etc", 32);
+    s = dirname(buf);
+    if (!s || strncmp(s, "/", 32) != 0) {
+       exit(1);
+    } else {
+       exit(0);
+    }
+}
+                               ]])],
+                               [ ac_cv_have_broken_dirname="no" ],
+                               [ ac_cv_have_broken_dirname="yes" ],
+                               [ ac_cv_have_broken_dirname="no" ],
+                       )
+                       LIBS="$save_LIBS"
+               ])
+               if test "x$ac_cv_have_broken_dirname" = "xno" ; then
+                       LIBS="$LIBS -lgen"
+                       AC_DEFINE([HAVE_DIRNAME])
+                       AC_CHECK_HEADERS([libgen.h])
+               fi
+       ])
+])
+
+AC_CHECK_FUNC([getspnam], ,
+       [AC_CHECK_LIB([gen], [getspnam], [LIBS="$LIBS -lgen"])])
+AC_SEARCH_LIBS([basename], [gen], [AC_DEFINE([HAVE_BASENAME], [1],
+       [Define if you have the basename function.])])
+
+dnl zlib is required
+AC_ARG_WITH([zlib],
+       [  --with-zlib=PATH        Use zlib in PATH],
+       [ if test "x$withval" = "xno" ; then
+               AC_MSG_ERROR([*** zlib is required ***])
+         elif test "x$withval" != "xyes"; then
+               if test -d "$withval/lib"; then
+                       if test -n "${need_dash_r}"; then
+                               LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                       else
+                               LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                       fi
+               else
+                       if test -n "${need_dash_r}"; then
+                               LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+                       else
+                               LDFLAGS="-L${withval} ${LDFLAGS}"
+                       fi
+               fi
+               if test -d "$withval/include"; then
+                       CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+               else
+                       CPPFLAGS="-I${withval} ${CPPFLAGS}"
+               fi
+       fi ]
+)
+
+AC_CHECK_HEADER([zlib.h], ,[AC_MSG_ERROR([*** zlib.h missing - please install first or check config.log ***])])
+AC_CHECK_LIB([z], [deflate], ,
+       [
+               saved_CPPFLAGS="$CPPFLAGS"
+               saved_LDFLAGS="$LDFLAGS"
+               save_LIBS="$LIBS"
+               dnl Check default zlib install dir
+               if test -n "${need_dash_r}"; then
+                       LDFLAGS="-L/usr/local/lib -R/usr/local/lib ${saved_LDFLAGS}"
+               else
+                       LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}"
+               fi
+               CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}"
+               LIBS="$LIBS -lz"
+               AC_TRY_LINK_FUNC([deflate], [AC_DEFINE([HAVE_LIBZ])],
+                       [
+                               AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***])
+                       ]
+               )
+       ]
+)
+
+AC_ARG_WITH([zlib-version-check],
+       [  --without-zlib-version-check Disable zlib version check],
+       [  if test "x$withval" = "xno" ; then
+               zlib_check_nonfatal=1
+          fi
+       ]
+)
+
+AC_MSG_CHECKING([for possibly buggy zlib])
+AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <zlib.h>
+       ]],
+       [[
+       int a=0, b=0, c=0, d=0, n, v;
+       n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d);
+       if (n != 3 && n != 4)
+               exit(1);
+       v = a*1000000 + b*10000 + c*100 + d;
+       fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v);
+
+       /* 1.1.4 is OK */
+       if (a == 1 && b == 1 && c >= 4)
+               exit(0);
+
+       /* 1.2.3 and up are OK */
+       if (v >= 1020300)
+               exit(0);
+
+       exit(2);
+       ]])],
+       AC_MSG_RESULT([no]),
+       [ AC_MSG_RESULT([yes])
+         if test -z "$zlib_check_nonfatal" ; then
+               AC_MSG_ERROR([*** zlib too old - check config.log ***
+Your reported zlib version has known security problems.  It's possible your
+vendor has fixed these problems without changing the version number.  If you
+are sure this is the case, you can disable the check by running
+"./configure --without-zlib-version-check".
+If you are in doubt, upgrade zlib to version 1.2.3 or greater.
+See http://www.gzip.org/zlib/ for details.])
+         else
+               AC_MSG_WARN([zlib version may have security problems])
+         fi
+       ],
+       [       AC_MSG_WARN([cross compiling: not checking zlib version]) ]
+)
+
+dnl UnixWare 2.x
+AC_CHECK_FUNC([strcasecmp],
+       [], [ AC_CHECK_LIB([resolv], [strcasecmp], [LIBS="$LIBS -lresolv"]) ]
+)
+AC_CHECK_FUNCS([utimes],
+       [], [ AC_CHECK_LIB([c89], [utimes], [AC_DEFINE([HAVE_UTIMES])
+                                       LIBS="$LIBS -lc89"]) ]
+)
+
+dnl    Checks for libutil functions
+AC_CHECK_HEADERS([libutil.h])
+AC_SEARCH_LIBS([login], [util bsd], [AC_DEFINE([HAVE_LOGIN], [1],
+       [Define if your libraries define login()])])
+AC_CHECK_FUNCS([fmt_scaled logout updwtmp logwtmp])
+
+AC_FUNC_STRFTIME
+
+# Check for ALTDIRFUNC glob() extension
+AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support])
+AC_EGREP_CPP([FOUNDIT],
+       [
+               #include <glob.h>
+               #ifdef GLOB_ALTDIRFUNC
+               FOUNDIT
+               #endif
+       ],
+       [
+               AC_DEFINE([GLOB_HAS_ALTDIRFUNC], [1],
+                       [Define if your system glob() function has
+                       the GLOB_ALTDIRFUNC extension])
+               AC_MSG_RESULT([yes])
+       ],
+       [
+               AC_MSG_RESULT([no])
+       ]
+)
+
+# Check for g.gl_matchc glob() extension
+AC_MSG_CHECKING([for gl_matchc field in glob_t])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <glob.h> ]],
+       [[ glob_t g; g.gl_matchc = 1; ]])],
+       [
+               AC_DEFINE([GLOB_HAS_GL_MATCHC], [1],
+                       [Define if your system glob() function has
+                       gl_matchc options in glob_t])
+               AC_MSG_RESULT([yes])
+       ], [
+               AC_MSG_RESULT([no])
+])
+
+# Check for g.gl_statv glob() extension
+AC_MSG_CHECKING([for gl_statv and GLOB_KEEPSTAT extensions for glob])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <glob.h> ]], [[
+#ifndef GLOB_KEEPSTAT
+#error "glob does not support GLOB_KEEPSTAT extension"
+#endif
+glob_t g;
+g.gl_statv = NULL;
+]])],
+       [
+               AC_DEFINE([GLOB_HAS_GL_STATV], [1],
+                       [Define if your system glob() function has
+                       gl_statv options in glob_t])
+               AC_MSG_RESULT([yes])
+       ], [
+               AC_MSG_RESULT([no])
+       
+])
+
+AC_CHECK_DECLS([GLOB_NOMATCH], , , [#include <glob.h>])
+
+AC_MSG_CHECKING([whether struct dirent allocates space for d_name])
+AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <dirent.h>]],
+       [[
+       struct dirent d;
+       exit(sizeof(d.d_name)<=sizeof(char));
+       ]])],
+       [AC_MSG_RESULT([yes])],
+       [
+               AC_MSG_RESULT([no])
+               AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME], [1],
+                       [Define if your struct dirent expects you to
+                       allocate extra space for d_name])
+       ],
+       [
+               AC_MSG_WARN([cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME])
+               AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME])
+       ]
+)
+
+AC_MSG_CHECKING([for /proc/pid/fd directory])
+if test -d "/proc/$$/fd" ; then
+       AC_DEFINE([HAVE_PROC_PID], [1], [Define if you have /proc/$pid/fd])
+       AC_MSG_RESULT([yes])
+else
+       AC_MSG_RESULT([no])
+fi
+
+# Check whether user wants S/Key support
+SKEY_MSG="no"
+AC_ARG_WITH([skey],
+       [  --with-skey[[=PATH]]      Enable S/Key support (optionally in PATH)],
+       [
+               if test "x$withval" != "xno" ; then
+
+                       if test "x$withval" != "xyes" ; then
+                               CPPFLAGS="$CPPFLAGS -I${withval}/include"
+                               LDFLAGS="$LDFLAGS -L${withval}/lib"
+                       fi
+
+                       AC_DEFINE([SKEY], [1], [Define if you want S/Key support])
+                       LIBS="-lskey $LIBS"
+                       SKEY_MSG="yes"
+
+                       AC_MSG_CHECKING([for s/key support])
+                       AC_LINK_IFELSE(
+                               [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <skey.h>
+                               ]], [[
+       char *ff = skey_keyinfo(""); ff="";
+       exit(0);
+                               ]])],
+                               [AC_MSG_RESULT([yes])],
+                               [
+                                       AC_MSG_RESULT([no])
+                                       AC_MSG_ERROR([** Incomplete or missing s/key libraries.])
+                               ])
+                       AC_MSG_CHECKING([if skeychallenge takes 4 arguments])
+                       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <skey.h>
+                               ]], [[
+       (void)skeychallenge(NULL,"name","",0);
+                               ]])],
+                       [
+                               AC_MSG_RESULT([yes])
+                               AC_DEFINE([SKEYCHALLENGE_4ARG], [1],
+                                       [Define if your skeychallenge()
+                                       function takes 4 arguments (NetBSD)])],
+                       [
+                               AC_MSG_RESULT([no])
+                       ])
+               fi
+       ]
+)
+
+# Check whether user wants TCP wrappers support
+TCPW_MSG="no"
+AC_ARG_WITH([tcp-wrappers],
+       [  --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)],
+       [
+               if test "x$withval" != "xno" ; then
+                       saved_LIBS="$LIBS"
+                       saved_LDFLAGS="$LDFLAGS"
+                       saved_CPPFLAGS="$CPPFLAGS"
+                       if test -n "${withval}" && \
+                           test "x${withval}" != "xyes"; then
+                               if test -d "${withval}/lib"; then
+                                       if test -n "${need_dash_r}"; then
+                                               LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                                       else
+                                               LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                                       fi
+                               else
+                                       if test -n "${need_dash_r}"; then
+                                               LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+                                       else
+                                               LDFLAGS="-L${withval} ${LDFLAGS}"
+                                       fi
+                               fi
+                               if test -d "${withval}/include"; then
+                                       CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+                               else
+                                       CPPFLAGS="-I${withval} ${CPPFLAGS}"
+                               fi
+                       fi
+                       LIBS="-lwrap $LIBS"
+                       AC_MSG_CHECKING([for libwrap])
+                       AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <tcpd.h>
+int deny_severity = 0, allow_severity = 0;
+                               ]], [[
+       hosts_access(0);
+                               ]])], [
+                                       AC_MSG_RESULT([yes])
+                                       AC_DEFINE([LIBWRAP], [1],
+                                               [Define if you want
+                                               TCP Wrappers support])
+                                       SSHDLIBS="$SSHDLIBS -lwrap"
+                                       TCPW_MSG="yes"
+                               ], [
+                                       AC_MSG_ERROR([*** libwrap missing])
+                               
+                       ])
+                       LIBS="$saved_LIBS"
+               fi
+       ]
+)
+
+# Check whether user wants libedit support
+LIBEDIT_MSG="no"
+AC_ARG_WITH([libedit],
+       [  --with-libedit[[=PATH]]   Enable libedit support for sftp],
+       [ if test "x$withval" != "xno" ; then
+               if test "x$withval" = "xyes" ; then
+                       AC_PATH_PROG([PKGCONFIG], [pkg-config], [no])
+                       if test "x$PKGCONFIG" != "xno"; then
+                               AC_MSG_CHECKING([if $PKGCONFIG knows about libedit])
+                               if "$PKGCONFIG" libedit; then
+                                       AC_MSG_RESULT([yes])
+                                       use_pkgconfig_for_libedit=yes
+                               else
+                                       AC_MSG_RESULT([no])
+                               fi
+                       fi
+               else
+                       CPPFLAGS="$CPPFLAGS -I${withval}/include"
+                       if test -n "${need_dash_r}"; then
+                               LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                       else
+                               LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                       fi
+               fi
+               if test "x$use_pkgconfig_for_libedit" = "xyes"; then
+                       LIBEDIT=`$PKGCONFIG --libs-only-l libedit`
+                       CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`"
+               else
+                       LIBEDIT="-ledit -lcurses"
+               fi
+               OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'`
+               AC_CHECK_LIB([edit], [el_init],
+                       [ AC_DEFINE([USE_LIBEDIT], [1], [Use libedit for sftp])
+                         LIBEDIT_MSG="yes"
+                         AC_SUBST([LIBEDIT])
+                       ],
+                       [ AC_MSG_ERROR([libedit not found]) ],
+                       [ $OTHERLIBS ]
+               )
+               AC_MSG_CHECKING([if libedit version is compatible])
+               AC_COMPILE_IFELSE(
+                   [AC_LANG_PROGRAM([[ #include <histedit.h> ]],
+                   [[
+       int i = H_SETSIZE;
+       el_init("", NULL, NULL, NULL);
+       exit(0);
+                   ]])],
+                   [ AC_MSG_RESULT([yes]) ],
+                   [ AC_MSG_RESULT([no])
+                     AC_MSG_ERROR([libedit version is not compatible]) ]
+               )
+       fi ]
+)
+
+AUDIT_MODULE=none
+AC_ARG_WITH([audit],
+       [  --with-audit=module     Enable audit support (modules=debug,bsm,linux)],
+       [
+         AC_MSG_CHECKING([for supported audit module])
+         case "$withval" in
+         bsm)
+               AC_MSG_RESULT([bsm])
+               AUDIT_MODULE=bsm
+               dnl    Checks for headers, libs and functions
+               AC_CHECK_HEADERS([bsm/audit.h], [],
+                   [AC_MSG_ERROR([BSM enabled and bsm/audit.h not found])],
+                   [
+#ifdef HAVE_TIME_H
+# include <time.h>
+#endif
+                   ]
+)
+               AC_CHECK_LIB([bsm], [getaudit], [],
+                   [AC_MSG_ERROR([BSM enabled and required library not found])])
+               AC_CHECK_FUNCS([getaudit], [],
+                   [AC_MSG_ERROR([BSM enabled and required function not found])])
+               # These are optional
+               AC_CHECK_FUNCS([getaudit_addr aug_get_machine])
+               AC_DEFINE([USE_BSM_AUDIT], [1], [Use BSM audit module])
+               ;;
+         linux)
+               AC_MSG_RESULT([linux])
+               AUDIT_MODULE=linux
+               dnl    Checks for headers, libs and functions
+               AC_CHECK_HEADERS([libaudit.h])
+               SSHDLIBS="$SSHDLIBS -laudit"
+               AC_DEFINE([USE_LINUX_AUDIT], [1], [Use Linux audit module])
+               ;;
+         debug)
+               AUDIT_MODULE=debug
+               AC_MSG_RESULT([debug])
+               AC_DEFINE([SSH_AUDIT_EVENTS], [1], [Use audit debugging module])
+               ;;
+         no)
+               AC_MSG_RESULT([no])
+               ;;
+         *)
+               AC_MSG_ERROR([Unknown audit module $withval])
+               ;;
+       esac ]
+)
+
+dnl    Checks for library functions. Please keep in alphabetical order
+AC_CHECK_FUNCS([ \
+       arc4random \
+       arc4random_buf \
+       arc4random_uniform \
+       asprintf \
+       b64_ntop \
+       __b64_ntop \
+       b64_pton \
+       __b64_pton \
+       bcopy \
+       bindresvport_sa \
+       clock \
+       closefrom \
+       dirfd \
+       fchmod \
+       fchown \
+       freeaddrinfo \
+       fstatvfs \
+       futimes \
+       getaddrinfo \
+       getcwd \
+       getgrouplist \
+       getnameinfo \
+       getopt \
+       getpeereid \
+       getpeerucred \
+       _getpty \
+       getrlimit \
+       getttyent \
+       glob \
+       group_from_gid \
+       inet_aton \
+       inet_ntoa \
+       inet_ntop \
+       innetgr \
+       login_getcapbool \
+       md5_crypt \
+       memmove \
+       mkdtemp \
+       mmap \
+       ngetaddrinfo \
+       nsleep \
+       ogetaddrinfo \
+       openlog_r \
+       openpty \
+       poll \
+       prctl \
+       pstat \
+       readpassphrase \
+       realpath \
+       recvmsg \
+       rresvport_af \
+       sendmsg \
+       setdtablesize \
+       setegid \
+       setenv \
+       seteuid \
+       setgroupent \
+       setgroups \
+       setlogin \
+       setpassent\
+       setpcred \
+       setproctitle \
+       setregid \
+       setreuid \
+       setrlimit \
+       setsid \
+       setvbuf \
+       sigaction \
+       sigvec \
+       snprintf \
+       socketpair \
+       statfs \
+       statvfs \
+       strdup \
+       strerror \
+       strlcat \
+       strlcpy \
+       strmode \
+       strnvis \
+       strptime \
+       strtonum \
+       strtoll \
+       strtoul \
+       swap32 \
+       sysconf \
+       tcgetpgrp \
+       timingsafe_bcmp \
+       truncate \
+       unsetenv \
+       updwtmpx \
+       user_from_uid \
+       vasprintf \
+       vhangup \
+       vsnprintf \
+       waitpid \
+])
+
+AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM(
+           [[ #include <ctype.h> ]],
+           [[ return (isblank('a')); ]])],
+       [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).])
+])
+
+# PKCS#11 support requires dlopen() and co
+AC_SEARCH_LIBS([dlopen], [dl],
+    [AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])]
+)
+
+# IRIX has a const char return value for gai_strerror()
+AC_CHECK_FUNCS([gai_strerror], [
+       AC_DEFINE([HAVE_GAI_STRERROR])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+const char *gai_strerror(int);
+                       ]], [[
+       char *str;
+       str = gai_strerror(0);
+                       ]])], [
+               AC_DEFINE([HAVE_CONST_GAI_STRERROR_PROTO], [1],
+               [Define if gai_strerror() returns const char *])], [])])
+
+AC_SEARCH_LIBS([nanosleep], [rt posix4], [AC_DEFINE([HAVE_NANOSLEEP], [1],
+       [Some systems put nanosleep outside of libc])])
+
+dnl Make sure prototypes are defined for these before using them.
+AC_CHECK_DECL([getrusage], [AC_CHECK_FUNCS([getrusage])])
+AC_CHECK_DECL([strsep],
+       [AC_CHECK_FUNCS([strsep])],
+       [],
+       [
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+       ])
+
+dnl tcsendbreak might be a macro
+AC_CHECK_DECL([tcsendbreak],
+       [AC_DEFINE([HAVE_TCSENDBREAK])],
+       [AC_CHECK_FUNCS([tcsendbreak])],
+       [#include <termios.h>]
+)
+
+AC_CHECK_DECLS([h_errno], , ,[#include <netdb.h>])
+
+AC_CHECK_DECLS([SHUT_RD], , ,
+       [
+#include <sys/types.h>
+#include <sys/socket.h>
+       ])
+
+AC_CHECK_DECLS([O_NONBLOCK], , ,
+       [
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+       ])
+
+AC_CHECK_DECLS([writev], , , [
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+       ])
+
+AC_CHECK_DECLS([MAXSYMLINKS], , , [
+#include <sys/param.h>
+       ])
+
+AC_CHECK_DECLS([offsetof], , , [
+#include <stddef.h>
+       ])
+
+AC_CHECK_FUNCS([setresuid], [
+       dnl Some platorms have setresuid that isn't implemented, test for this
+       AC_MSG_CHECKING([if setresuid seems to work])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <stdlib.h>
+#include <errno.h>
+               ]], [[
+       errno=0;
+       setresuid(0,0,0);
+       if (errno==ENOSYS)
+               exit(1);
+       else
+               exit(0);
+               ]])],
+               [AC_MSG_RESULT([yes])],
+               [AC_DEFINE([BROKEN_SETRESUID], [1],
+                       [Define if your setresuid() is broken])
+                AC_MSG_RESULT([not implemented])],
+               [AC_MSG_WARN([cross compiling: not checking setresuid])]
+       )
+])
+
+AC_CHECK_FUNCS([setresgid], [
+       dnl Some platorms have setresgid that isn't implemented, test for this
+       AC_MSG_CHECKING([if setresgid seems to work])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <stdlib.h>
+#include <errno.h>
+               ]], [[
+       errno=0;
+       setresgid(0,0,0);
+       if (errno==ENOSYS)
+               exit(1);
+       else
+               exit(0);
+               ]])],
+               [AC_MSG_RESULT([yes])],
+               [AC_DEFINE([BROKEN_SETRESGID], [1],
+                       [Define if your setresgid() is broken])
+                AC_MSG_RESULT([not implemented])],
+               [AC_MSG_WARN([cross compiling: not checking setresuid])]
+       )
+])
+
+dnl    Checks for time functions
+AC_CHECK_FUNCS([gettimeofday time])
+dnl    Checks for utmp functions
+AC_CHECK_FUNCS([endutent getutent getutid getutline pututline setutent])
+AC_CHECK_FUNCS([utmpname])
+dnl    Checks for utmpx functions
+AC_CHECK_FUNCS([endutxent getutxent getutxid getutxline getutxuser pututxline])
+AC_CHECK_FUNCS([setutxdb setutxent utmpxname])
+dnl    Checks for lastlog functions
+AC_CHECK_FUNCS([getlastlogxbyname])
+
+AC_CHECK_FUNC([daemon],
+       [AC_DEFINE([HAVE_DAEMON], [1], [Define if your libraries define daemon()])],
+       [AC_CHECK_LIB([bsd], [daemon],
+               [LIBS="$LIBS -lbsd"; AC_DEFINE([HAVE_DAEMON])])]
+)
+
+AC_CHECK_FUNC([getpagesize],
+       [AC_DEFINE([HAVE_GETPAGESIZE], [1],
+               [Define if your libraries define getpagesize()])],
+       [AC_CHECK_LIB([ucb], [getpagesize],
+               [LIBS="$LIBS -lucb"; AC_DEFINE([HAVE_GETPAGESIZE])])]
+)
+
+# Check for broken snprintf
+if test "x$ac_cv_func_snprintf" = "xyes" ; then
+       AC_MSG_CHECKING([whether snprintf correctly terminates long strings])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+               [[
+       char b[5];
+       snprintf(b,5,"123456789");
+       exit(b[4]!='\0'); 
+               ]])],
+               [AC_MSG_RESULT([yes])],
+               [
+                       AC_MSG_RESULT([no])
+                       AC_DEFINE([BROKEN_SNPRINTF], [1],
+                               [Define if your snprintf is busted])
+                       AC_MSG_WARN([****** Your snprintf() function is broken, complain to your vendor])
+               ],
+               [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ]
+       )
+fi
+
+# If we don't have a working asprintf, then we strongly depend on vsnprintf
+# returning the right thing on overflow: the number of characters it tried to
+# create (as per SUSv3)
+if test "x$ac_cv_func_asprintf" != "xyes" && \
+   test "x$ac_cv_func_vsnprintf" = "xyes" ; then
+       AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+int x_snprintf(char *str,size_t count,const char *fmt,...)
+{
+       size_t ret; va_list ap;
+       va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap);
+       return ret;
+}
+               ]], [[
+       char x[1];
+       exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1);
+               ]])],
+               [AC_MSG_RESULT([yes])],
+               [
+                       AC_MSG_RESULT([no])
+                       AC_DEFINE([BROKEN_SNPRINTF], [1],
+                               [Define if your snprintf is busted])
+                       AC_MSG_WARN([****** Your vsnprintf() function is broken, complain to your vendor])
+               ],
+               [ AC_MSG_WARN([cross compiling: Assuming working vsnprintf()]) ]
+       )
+fi
+
+# On systems where [v]snprintf is broken, but is declared in stdio,
+# check that the fmt argument is const char * or just char *.
+# This is only useful for when BROKEN_SNPRINTF
+AC_MSG_CHECKING([whether snprintf can declare const char *fmt])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <stdio.h>
+int snprintf(char *a, size_t b, const char *c, ...) { return 0; }
+               ]], [[
+       snprintf(0, 0, 0);
+               ]])],
+   [AC_MSG_RESULT([yes])
+    AC_DEFINE([SNPRINTF_CONST], [const],
+              [Define as const if snprintf() can declare const char *fmt])],
+   [AC_MSG_RESULT([no])
+    AC_DEFINE([SNPRINTF_CONST], [/* not const */])])
+
+# Check for missing getpeereid (or equiv) support
+NO_PEERCHECK=""
+if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then
+       AC_MSG_CHECKING([whether system supports SO_PEERCRED getsockopt])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>]], [[int i = SO_PEERCRED;]])],
+               [ AC_MSG_RESULT([yes])
+                 AC_DEFINE([HAVE_SO_PEERCRED], [1], [Have PEERCRED socket option])
+               ], [AC_MSG_RESULT([no])
+               NO_PEERCHECK=1
+        ])
+fi
+
+dnl see whether mkstemp() requires XXXXXX
+if test "x$ac_cv_func_mkdtemp" = "xyes" ; then
+AC_MSG_CHECKING([for (overly) strict mkstemp])
+AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <stdlib.h>
+       ]], [[
+       char template[]="conftest.mkstemp-test";
+       if (mkstemp(template) == -1)
+               exit(1);
+       unlink(template);
+       exit(0);
+       ]])],
+       [
+               AC_MSG_RESULT([no])
+       ],
+       [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE([HAVE_STRICT_MKSTEMP], [1], [Silly mkstemp()])
+       ],
+       [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE([HAVE_STRICT_MKSTEMP])
+       ]
+)
+fi
+
+dnl make sure that openpty does not reacquire controlling terminal
+if test ! -z "$check_for_openpty_ctty_bug"; then
+       AC_MSG_CHECKING([if openpty correctly handles controlling tty])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+               ]], [[
+       pid_t pid;
+       int fd, ptyfd, ttyfd, status;
+
+       pid = fork();
+       if (pid < 0) {          /* failed */
+               exit(1);
+       } else if (pid > 0) {   /* parent */
+               waitpid(pid, &status, 0);
+               if (WIFEXITED(status))
+                       exit(WEXITSTATUS(status));
+               else
+                       exit(2);
+       } else {                /* child */
+               close(0); close(1); close(2);
+               setsid();
+               openpty(&ptyfd, &ttyfd, NULL, NULL, NULL);
+               fd = open("/dev/tty", O_RDWR | O_NOCTTY);
+               if (fd >= 0)
+                       exit(3);        /* Acquired ctty: broken */
+               else
+                       exit(0);        /* Did not acquire ctty: OK */
+       }
+               ]])],
+               [
+                       AC_MSG_RESULT([yes])
+               ],
+               [
+                       AC_MSG_RESULT([no])
+                       AC_DEFINE([SSHD_ACQUIRES_CTTY])
+               ],
+               [
+                       AC_MSG_RESULT([cross-compiling, assuming yes])
+               ]
+       )
+fi
+
+if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
+    test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then
+       AC_MSG_CHECKING([if getaddrinfo seems to work])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#define TEST_PORT "2222"
+               ]], [[
+       int err, sock;
+       struct addrinfo *gai_ai, *ai, hints;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = AI_PASSIVE;
+
+       err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
+       if (err != 0) {
+               fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
+               exit(1);
+       }
+
+       for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET6)
+                       continue;
+
+               err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
+                   sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV);
+
+               if (err != 0) {
+                       if (err == EAI_SYSTEM)
+                               perror("getnameinfo EAI_SYSTEM");
+                       else
+                               fprintf(stderr, "getnameinfo failed: %s\n",
+                                   gai_strerror(err));
+                       exit(2);
+               }
+
+               sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+               if (sock < 0)
+                       perror("socket");
+               if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       if (errno == EBADF)
+                               exit(3);
+               }
+       }
+       exit(0);
+               ]])],
+               [
+                       AC_MSG_RESULT([yes])
+               ],
+               [
+                       AC_MSG_RESULT([no])
+                       AC_DEFINE([BROKEN_GETADDRINFO])
+               ],
+               [
+                       AC_MSG_RESULT([cross-compiling, assuming yes])
+               ]
+       )
+fi
+
+if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
+    test "x$check_for_aix_broken_getaddrinfo" = "x1"; then
+       AC_MSG_CHECKING([if getaddrinfo seems to work])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#define TEST_PORT "2222"
+               ]], [[
+       int err, sock;
+       struct addrinfo *gai_ai, *ai, hints;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = PF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = AI_PASSIVE;
+
+       err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
+       if (err != 0) {
+               fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
+               exit(1);
+       }
+
+       for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                       continue;
+
+               err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
+                   sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV);
+
+               if (ai->ai_family == AF_INET && err != 0) {
+                       perror("getnameinfo");
+                       exit(2);
+               }
+       }
+       exit(0);
+               ]])],
+               [
+                       AC_MSG_RESULT([yes])
+                       AC_DEFINE([AIX_GETNAMEINFO_HACK], [1],
+                               [Define if you have a getaddrinfo that fails
+                               for the all-zeros IPv6 address])
+               ],
+               [
+                       AC_MSG_RESULT([no])
+                       AC_DEFINE([BROKEN_GETADDRINFO])
+               ],
+               [
+                       AC_MSG_RESULT([cross-compiling, assuming no])
+               ]
+       )
+fi
+
+if test "x$check_for_conflicting_getspnam" = "x1"; then
+       AC_MSG_CHECKING([for conflicting getspnam in shadow.h])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <shadow.h> ]],
+               [[ exit(0); ]])],
+               [
+                       AC_MSG_RESULT([no])
+               ],
+               [
+                       AC_MSG_RESULT([yes])
+                       AC_DEFINE([GETSPNAM_CONFLICTING_DEFS], [1],
+                           [Conflicting defs for getspnam])
+               ]
+       )
+fi
+
+AC_FUNC_GETPGRP
+
+# Search for OpenSSL
+saved_CPPFLAGS="$CPPFLAGS"
+saved_LDFLAGS="$LDFLAGS"
+AC_ARG_WITH([ssl-dir],
+       [  --with-ssl-dir=PATH     Specify path to OpenSSL installation ],
+       [
+               if test "x$withval" != "xno" ; then
+                       case "$withval" in
+                               # Relative paths
+                               ./*|../*)       withval="`pwd`/$withval"
+                       esac
+                       if test -d "$withval/lib"; then
+                               if test -n "${need_dash_r}"; then
+                                       LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+                               else
+                                       LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+                               fi
+                       elif test -d "$withval/lib64"; then
+                               if test -n "${need_dash_r}"; then
+                                       LDFLAGS="-L${withval}/lib64 -R${withval}/lib64 ${LDFLAGS}"
+                               else
+                                       LDFLAGS="-L${withval}/lib64 ${LDFLAGS}"
+                               fi
+                       else
+                               if test -n "${need_dash_r}"; then
+                                       LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+                               else
+                                       LDFLAGS="-L${withval} ${LDFLAGS}"
+                               fi
+                       fi
+                       if test -d "$withval/include"; then
+                               CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+                       else
+                               CPPFLAGS="-I${withval} ${CPPFLAGS}"
+                       fi
+               fi
+       ]
+)
+LIBS="-lcrypto $LIBS"
+AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1],
+       [Define if your ssl headers are included
+       with #include <openssl/header.h>])],
+       [
+               dnl Check default openssl install dir
+               if test -n "${need_dash_r}"; then
+                       LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}"
+               else
+                       LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}"
+               fi
+               CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}"
+               AC_CHECK_HEADER([openssl/opensslv.h], ,
+                   [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])])
+               AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL])],
+                       [
+                               AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***])
+                       ]
+               )
+       ]
+)
+
+# Determine OpenSSL header version
+AC_MSG_CHECKING([OpenSSL header version])
+AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <string.h>
+#include <openssl/opensslv.h>
+#define DATA "conftest.sslincver"
+       ]], [[
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+       if ((rc = fprintf(fd ,"%x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0)
+               exit(1);
+
+       exit(0);
+       ]])],
+       [
+               ssl_header_ver=`cat conftest.sslincver`
+               AC_MSG_RESULT([$ssl_header_ver])
+       ],
+       [
+               AC_MSG_RESULT([not found])
+               AC_MSG_ERROR([OpenSSL version header not found.])
+       ],
+       [
+               AC_MSG_WARN([cross compiling: not checking])
+       ]
+)
+
+# Determine OpenSSL library version
+AC_MSG_CHECKING([OpenSSL library version])
+AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <string.h>
+#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
+#define DATA "conftest.ssllibver"
+       ]], [[
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+       if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0)
+               exit(1);
+
+       exit(0);
+       ]])],
+       [
+               ssl_library_ver=`cat conftest.ssllibver`
+               AC_MSG_RESULT([$ssl_library_ver])
+       ],
+       [
+               AC_MSG_RESULT([not found])
+               AC_MSG_ERROR([OpenSSL library not found.])
+       ],
+       [
+               AC_MSG_WARN([cross compiling: not checking])
+       ]
+)
+
+AC_ARG_WITH([openssl-header-check],
+       [  --without-openssl-header-check Disable OpenSSL version consistency check],
+       [  if test "x$withval" = "xno" ; then
+               openssl_check_nonfatal=1
+          fi
+       ]
+)
+
+# Sanity check OpenSSL headers
+AC_MSG_CHECKING([whether OpenSSL's headers match the library])
+AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <string.h>
+#include <openssl/opensslv.h>
+       ]], [[
+       exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1);
+       ]])],
+       [
+               AC_MSG_RESULT([yes])
+       ],
+       [
+               AC_MSG_RESULT([no])
+               if test "x$openssl_check_nonfatal" = "x"; then
+                       AC_MSG_ERROR([Your OpenSSL headers do not match your
+library. Check config.log for details.
+If you are sure your installation is consistent, you can disable the check
+by running "./configure --without-openssl-header-check".
+Also see contrib/findssl.sh for help identifying header/library mismatches.
+])
+               else
+                       AC_MSG_WARN([Your OpenSSL headers do not match your
+library. Check config.log for details.
+Also see contrib/findssl.sh for help identifying header/library mismatches.])
+               fi
+       ],
+       [
+               AC_MSG_WARN([cross compiling: not checking])
+       ]
+)
+
+AC_MSG_CHECKING([if programs using OpenSSL functions will link])
+AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]],
+       [[ SSLeay_add_all_algorithms(); ]])],
+       [
+               AC_MSG_RESULT([yes])
+       ],
+       [
+               AC_MSG_RESULT([no])
+               saved_LIBS="$LIBS"
+               LIBS="$LIBS -ldl"
+               AC_MSG_CHECKING([if programs using OpenSSL need -ldl])
+               AC_LINK_IFELSE(
+                       [AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]],
+                       [[ SSLeay_add_all_algorithms(); ]])],
+                       [
+                               AC_MSG_RESULT([yes])
+                       ],
+                       [
+                               AC_MSG_RESULT([no])
+                               LIBS="$saved_LIBS"
+                       ]
+               )
+       ]
+)
+
+AC_CHECK_FUNCS([RSA_generate_key_ex DSA_generate_parameters_ex BN_is_prime_ex RSA_get_default_method])
+
+AC_ARG_WITH([ssl-engine],
+       [  --with-ssl-engine       Enable OpenSSL (hardware) ENGINE support ],
+       [ if test "x$withval" != "xno" ; then
+               AC_MSG_CHECKING([for OpenSSL ENGINE support])
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <openssl/engine.h>
+                       ]], [[
+       ENGINE_load_builtin_engines();
+       ENGINE_register_all_complete();
+                       ]])],
+                       [ AC_MSG_RESULT([yes])
+                         AC_DEFINE([USE_OPENSSL_ENGINE], [1],
+                            [Enable OpenSSL engine support])
+                       ], [ AC_MSG_ERROR([OpenSSL ENGINE support not found])
+               ])
+         fi ]
+)
+
+# Check for OpenSSL without EVP_aes_{192,256}_cbc
+AC_MSG_CHECKING([whether OpenSSL has crippled AES support])
+AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <string.h>
+#include <openssl/evp.h>
+       ]], [[
+       exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL);
+       ]])],
+       [
+               AC_MSG_RESULT([no])
+       ],
+       [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE([OPENSSL_LOBOTOMISED_AES], [1],
+                   [libcrypto is missing AES 192 and 256 bit functions])
+       ]
+)
+
+AC_MSG_CHECKING([if EVP_DigestUpdate returns an int])
+AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <string.h>
+#include <openssl/evp.h>
+       ]], [[
+       if(EVP_DigestUpdate(NULL, NULL,0))
+               exit(0);
+       ]])],
+       [
+               AC_MSG_RESULT([yes])
+       ],
+       [
+               AC_MSG_RESULT([no])
+               AC_DEFINE([OPENSSL_EVP_DIGESTUPDATE_VOID], [1],
+                   [Define if EVP_DigestUpdate returns void])
+       ]
+)
+
+# Some systems want crypt() from libcrypt, *not* the version in OpenSSL,
+# because the system crypt() is more featureful.
+if test "x$check_for_libcrypt_before" = "x1"; then
+       AC_CHECK_LIB([crypt], [crypt])
+fi
+
+# Some Linux systems (Slackware) need crypt() from libcrypt, *not* the
+# version in OpenSSL.
+if test "x$check_for_libcrypt_later" = "x1"; then
+       AC_CHECK_LIB([crypt], [crypt], [LIBS="$LIBS -lcrypt"])
+fi
+
+# Search for SHA256 support in libc and/or OpenSSL
+AC_CHECK_FUNCS([SHA256_Update EVP_sha256], [TEST_SSH_SHA256=yes],
+    [TEST_SSH_SHA256=no])
+AC_SUBST([TEST_SSH_SHA256])
+
+# Check complete ECC support in OpenSSL
+AC_MSG_CHECKING([whether OpenSSL has complete ECC support])
+AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
+# error "OpenSSL < 0.9.8g has unreliable ECC code"
+#endif
+       ]], [[
+       EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
+       const EVP_MD *m = EVP_sha512(); /* We need this too */
+       ]])],
+       [
+               AC_MSG_RESULT([yes])
+               AC_DEFINE([OPENSSL_HAS_ECC], [1],
+                   [libcrypto includes complete ECC support])
+               TEST_SSH_ECC=yes
+               COMMENT_OUT_ECC=""
+       ],
+       [
+               AC_MSG_RESULT([no])
+               TEST_SSH_ECC=no
+               COMMENT_OUT_ECC="#no ecc#"
+       ]
+)
+AC_SUBST([TEST_SSH_ECC])
+AC_SUBST([COMMENT_OUT_ECC])
+
+saved_LIBS="$LIBS"
+AC_CHECK_LIB([iaf], [ia_openinfo], [
+       LIBS="$LIBS -liaf"
+       AC_CHECK_FUNCS([set_id], [SSHDLIBS="$SSHDLIBS -liaf"
+                               AC_DEFINE([HAVE_LIBIAF], [1],
+                       [Define if system has libiaf that supports set_id])
+                               ])
+])
+LIBS="$saved_LIBS"
+
+### Configure cryptographic random number support
+
+# Check wheter OpenSSL seeds itself
+AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded])
+AC_RUN_IFELSE(
+       [AC_LANG_PROGRAM([[
+#include <string.h>
+#include <openssl/rand.h>
+       ]], [[
+       exit(RAND_status() == 1 ? 0 : 1);
+       ]])],
+       [
+               OPENSSL_SEEDS_ITSELF=yes
+               AC_MSG_RESULT([yes])
+       ],
+       [
+               AC_MSG_RESULT([no])
+       ],
+       [
+               AC_MSG_WARN([cross compiling: assuming yes])
+               # This is safe, since we will fatal() at runtime if
+               # OpenSSL is not seeded correctly.
+               OPENSSL_SEEDS_ITSELF=yes
+       ]
+)
+
+# PRNGD TCP socket
+AC_ARG_WITH([prngd-port],
+       [  --with-prngd-port=PORT  read entropy from PRNGD/EGD TCP localhost:PORT],
+       [
+               case "$withval" in
+               no)
+                       withval=""
+                       ;;
+               [[0-9]]*)
+                       ;;
+               *)
+                       AC_MSG_ERROR([You must specify a numeric port number for --with-prngd-port])
+                       ;;
+               esac
+               if test ! -z "$withval" ; then
+                       PRNGD_PORT="$withval"
+                       AC_DEFINE_UNQUOTED([PRNGD_PORT], [$PRNGD_PORT],
+                               [Port number of PRNGD/EGD random number socket])
+               fi
+       ]
+)
+
+# PRNGD Unix domain socket
+AC_ARG_WITH([prngd-socket],
+       [  --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)],
+       [
+               case "$withval" in
+               yes)
+                       withval="/var/run/egd-pool"
+                       ;;
+               no)
+                       withval=""
+                       ;;
+               /*)
+                       ;;
+               *)
+                       AC_MSG_ERROR([You must specify an absolute path to the entropy socket])
+                       ;;
+               esac
+
+               if test ! -z "$withval" ; then
+                       if test ! -z "$PRNGD_PORT" ; then
+                               AC_MSG_ERROR([You may not specify both a PRNGD/EGD port and socket])
+                       fi
+                       if test ! -r "$withval" ; then
+                               AC_MSG_WARN([Entropy socket is not readable])
+                       fi
+                       PRNGD_SOCKET="$withval"
+                       AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"],
+                               [Location of PRNGD/EGD random number socket])
+               fi
+       ],
+       [
+               # Check for existing socket only if we don't have a random device already
+               if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then
+                       AC_MSG_CHECKING([for PRNGD/EGD socket])
+                       # Insert other locations here
+                       for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do
+                               if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then
+                                       PRNGD_SOCKET="$sock"
+                                       AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"])
+                                       break;
+                               fi
+                       done
+                       if test ! -z "$PRNGD_SOCKET" ; then
+                               AC_MSG_RESULT([$PRNGD_SOCKET])
+                       else
+                               AC_MSG_RESULT([not found])
+                       fi
+               fi
+       ]
+)
+
+# Which randomness source do we use?
+if test ! -z "$PRNGD_PORT" ; then
+       RAND_MSG="PRNGd port $PRNGD_PORT"
+elif test ! -z "$PRNGD_SOCKET" ; then
+       RAND_MSG="PRNGd socket $PRNGD_SOCKET"
+elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then
+       AC_DEFINE([OPENSSL_PRNG_ONLY], [1],
+               [Define if you want OpenSSL's internally seeded PRNG only])
+       RAND_MSG="OpenSSL internal ONLY"
+else
+       AC_MSG_ERROR([OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options])
+fi
+
+# Check for PAM libs
+PAM_MSG="no"
+AC_ARG_WITH([pam],
+       [  --with-pam              Enable PAM support ],
+       [
+               if test "x$withval" != "xno" ; then
+                       if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \
+                          test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then
+                               AC_MSG_ERROR([PAM headers not found])
+                       fi
+
+                       saved_LIBS="$LIBS"
+                       AC_CHECK_LIB([dl], [dlopen], , )
+                       AC_CHECK_LIB([pam], [pam_set_item], , [AC_MSG_ERROR([*** libpam missing])])
+                       AC_CHECK_FUNCS([pam_getenvlist])
+                       AC_CHECK_FUNCS([pam_putenv])
+                       LIBS="$saved_LIBS"
+
+                       PAM_MSG="yes"
+
+                       SSHDLIBS="$SSHDLIBS -lpam"
+                       AC_DEFINE([USE_PAM], [1],
+                               [Define if you want to enable PAM support])
+
+                       if test $ac_cv_lib_dl_dlopen = yes; then
+                               case "$LIBS" in
+                               *-ldl*)
+                                       # libdl already in LIBS
+                                       ;;
+                               *)
+                                       SSHDLIBS="$SSHDLIBS -ldl"
+                                       ;;
+                               esac
+                       fi
+               fi
+       ]
+)
+
+# Check for older PAM
+if test "x$PAM_MSG" = "xyes" ; then
+       # Check PAM strerror arguments (old PAM)
+       AC_MSG_CHECKING([whether pam_strerror takes only one argument])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <stdlib.h>
+#if defined(HAVE_SECURITY_PAM_APPL_H)
+#include <security/pam_appl.h>
+#elif defined (HAVE_PAM_PAM_APPL_H)
+#include <pam/pam_appl.h>
+#endif
+               ]], [[
+(void)pam_strerror((pam_handle_t *)NULL, -1);
+               ]])], [AC_MSG_RESULT([no])], [
+                       AC_DEFINE([HAVE_OLD_PAM], [1],
+                               [Define if you have an old version of PAM
+                               which takes only one argument to pam_strerror])
+                       AC_MSG_RESULT([yes])
+                       PAM_MSG="yes (old library)"
+               
+       ])
+fi
+
+SSH_PRIVSEP_USER=sshd
+AC_ARG_WITH([privsep-user],
+       [  --with-privsep-user=user Specify non-privileged user for privilege separation],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       SSH_PRIVSEP_USER=$withval
+               fi
+       ]
+)
+AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"],
+       [non-privileged user for privilege separation])
+AC_SUBST([SSH_PRIVSEP_USER])
+
+# Decide which sandbox style to use
+sandbox_arg=""
+AC_ARG_WITH([sandbox],
+       [  --with-sandbox=style    Specify privilege separation sandbox (no, darwin, rlimit, systrace)],
+       [
+               if test "x$withval" = "xyes" ; then
+                       sandbox_arg=""
+               else
+                       sandbox_arg="$withval"
+               fi
+       ]
+)
+if test "x$sandbox_arg" = "xsystrace" || \
+   ( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then
+       test "x$have_systr_policy_kill" != "x1" && \
+               AC_MSG_ERROR([systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support])
+       SANDBOX_STYLE="systrace"
+       AC_DEFINE([SANDBOX_SYSTRACE], [1], [Sandbox using systrace(4)])
+elif test "x$sandbox_arg" = "xdarwin" || \
+     ( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \
+       test "x$ac_cv_header_sandbox_h" = "xyes") ; then
+       test "x$ac_cv_func_sandbox_init" != "xyes" -o \
+            "x$ac_cv_header_sandbox_h" != "xyes" && \
+               AC_MSG_ERROR([Darwin seatbelt sandbox requires sandbox.h and sandbox_init function])
+       SANDBOX_STYLE="darwin"
+       AC_DEFINE([SANDBOX_DARWIN], [1], [Sandbox using Darwin sandbox_init(3)])
+elif test "x$sandbox_arg" = "xrlimit" || \
+     ( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" ) ; then
+       test "x$ac_cv_func_setrlimit" != "xyes" && \
+               AC_MSG_ERROR([rlimit sandbox requires setrlimit function])
+       SANDBOX_STYLE="rlimit"
+       AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)])
+elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
+     test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
+       SANDBOX_STYLE="none"
+       AC_DEFINE([SANDBOX_NULL], [1], [no privsep sandboxing])
+else
+       AC_MSG_ERROR([unsupported --with-sandbox])
+fi
+
+# Cheap hack to ensure NEWS-OS libraries are arranged right.
+if test ! -z "$SONY" ; then
+  LIBS="$LIBS -liberty";
+fi
+
+# Check for  long long datatypes
+AC_CHECK_TYPES([long long, unsigned long long, long double])
+
+# Check datatype sizes
+AC_CHECK_SIZEOF([char], [1])
+AC_CHECK_SIZEOF([short int], [2])
+AC_CHECK_SIZEOF([int], [4])
+AC_CHECK_SIZEOF([long int], [4])
+AC_CHECK_SIZEOF([long long int], [8])
+
+# Sanity check long long for some platforms (AIX)
+if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
+       ac_cv_sizeof_long_long_int=0
+fi
+
+# compute LLONG_MIN and LLONG_MAX if we don't know them.
+if test -z "$have_llong_max"; then
+       AC_MSG_CHECKING([for max value of long long])
+       AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <stdio.h>
+/* Why is this so damn hard? */
+#ifdef __GNUC__
+# undef __GNUC__
+#endif
+#define __USE_ISOC99
+#include <limits.h>
+#define DATA "conftest.llminmax"
+#define my_abs(a) ((a) < 0 ? ((a) * -1) : (a))
+
+/*
+ * printf in libc on some platforms (eg old Tru64) does not understand %lld so
+ * we do this the hard way.
+ */
+static int
+fprint_ll(FILE *f, long long n)
+{
+       unsigned int i;
+       int l[sizeof(long long) * 8];
+
+       if (n < 0)
+               if (fprintf(f, "-") < 0)
+                       return -1;
+       for (i = 0; n != 0; i++) {
+               l[i] = my_abs(n % 10);
+               n /= 10;
+       }
+       do {
+               if (fprintf(f, "%d", l[--i]) < 0)
+                       return -1;
+       } while (i != 0);
+       if (fprintf(f, " ") < 0)
+               return -1;
+       return 0;
+}
+               ]], [[
+       FILE *f;
+       long long i, llmin, llmax = 0;
+
+       if((f = fopen(DATA,"w")) == NULL)
+               exit(1);
+
+#if defined(LLONG_MIN) && defined(LLONG_MAX)
+       fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n");
+       llmin = LLONG_MIN;
+       llmax = LLONG_MAX;
+#else
+       fprintf(stderr, "Calculating  LLONG_MIN and LLONG_MAX\n");
+       /* This will work on one's complement and two's complement */
+       for (i = 1; i > llmax; i <<= 1, i++)
+               llmax = i;
+       llmin = llmax + 1LL;    /* wrap */
+#endif
+
+       /* Sanity check */
+       if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax
+           || llmax - 1 > llmax || llmin == llmax || llmin == 0
+           || llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) {
+               fprintf(f, "unknown unknown\n");
+               exit(2);
+       }
+
+       if (fprint_ll(f, llmin) < 0)
+               exit(3);
+       if (fprint_ll(f, llmax) < 0)
+               exit(4);
+       if (fclose(f) < 0)
+               exit(5);
+       exit(0);
+               ]])],
+               [
+                       llong_min=`$AWK '{print $1}' conftest.llminmax`
+                       llong_max=`$AWK '{print $2}' conftest.llminmax`
+
+                       AC_MSG_RESULT([$llong_max])
+                       AC_DEFINE_UNQUOTED([LLONG_MAX], [${llong_max}LL],
+                           [max value of long long calculated by configure])
+                       AC_MSG_CHECKING([for min value of long long])
+                       AC_MSG_RESULT([$llong_min])
+                       AC_DEFINE_UNQUOTED([LLONG_MIN], [${llong_min}LL],
+                           [min value of long long calculated by configure])
+               ],
+               [
+                       AC_MSG_RESULT([not found])
+               ],
+               [
+                       AC_MSG_WARN([cross compiling: not checking])
+               ]
+       )
+fi
+
+
+# More checks for data types
+AC_CACHE_CHECK([for u_int type], ac_cv_have_u_int, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ u_int a; a = 1;]])],
+       [ ac_cv_have_u_int="yes" ], [ ac_cv_have_u_int="no" 
+       ])
+])
+if test "x$ac_cv_have_u_int" = "xyes" ; then
+       AC_DEFINE([HAVE_U_INT], [1], [define if you have u_int data type])
+       have_u_int=1
+fi
+
+AC_CACHE_CHECK([for intXX_t types], ac_cv_have_intxx_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])],
+       [ ac_cv_have_intxx_t="yes" ], [ ac_cv_have_intxx_t="no" 
+       ])
+])
+if test "x$ac_cv_have_intxx_t" = "xyes" ; then
+       AC_DEFINE([HAVE_INTXX_T], [1], [define if you have intxx_t data type])
+       have_intxx_t=1
+fi
+
+if (test -z "$have_intxx_t" && \
+          test "x$ac_cv_header_stdint_h" = "xyes")
+then
+    AC_MSG_CHECKING([for intXX_t types in stdint.h])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdint.h> ]],
+       [[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])],
+               [
+                       AC_DEFINE([HAVE_INTXX_T])
+                       AC_MSG_RESULT([yes])
+               ], [ AC_MSG_RESULT([no]) 
+       ])
+fi
+
+AC_CACHE_CHECK([for int64_t type], ac_cv_have_int64_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <sys/socket.h>
+#ifdef HAVE_SYS_BITYPES_H
+# include <sys/bitypes.h>
+#endif
+               ]], [[
+int64_t a; a = 1;
+               ]])],
+       [ ac_cv_have_int64_t="yes" ], [ ac_cv_have_int64_t="no" 
+       ])
+])
+if test "x$ac_cv_have_int64_t" = "xyes" ; then
+       AC_DEFINE([HAVE_INT64_T], [1], [define if you have int64_t data type])
+fi
+
+AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])],
+       [ ac_cv_have_u_intxx_t="yes" ], [ ac_cv_have_u_intxx_t="no" 
+       ])
+])
+if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then
+       AC_DEFINE([HAVE_U_INTXX_T], [1], [define if you have u_intxx_t data type])
+       have_u_intxx_t=1
+fi
+
+if test -z "$have_u_intxx_t" ; then
+    AC_MSG_CHECKING([for u_intXX_t types in sys/socket.h])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/socket.h> ]],
+       [[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])],
+               [
+                       AC_DEFINE([HAVE_U_INTXX_T])
+                       AC_MSG_RESULT([yes])
+               ], [ AC_MSG_RESULT([no]) 
+       ])
+fi
+
+AC_CACHE_CHECK([for u_int64_t types], ac_cv_have_u_int64_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ u_int64_t a; a = 1;]])],
+       [ ac_cv_have_u_int64_t="yes" ], [ ac_cv_have_u_int64_t="no" 
+       ])
+])
+if test "x$ac_cv_have_u_int64_t" = "xyes" ; then
+       AC_DEFINE([HAVE_U_INT64_T], [1], [define if you have u_int64_t data type])
+       have_u_int64_t=1
+fi
+
+if test -z "$have_u_int64_t" ; then
+    AC_MSG_CHECKING([for u_int64_t type in sys/bitypes.h])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/bitypes.h> ]],
+       [[ u_int64_t a; a = 1]])],
+               [
+                       AC_DEFINE([HAVE_U_INT64_T])
+                       AC_MSG_RESULT([yes])
+               ], [ AC_MSG_RESULT([no]) 
+       ])
+fi
+
+if test -z "$have_u_intxx_t" ; then
+       AC_CACHE_CHECK([for uintXX_t types], ac_cv_have_uintxx_t, [
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+                       ]], [[
+       uint8_t a;
+       uint16_t b;
+       uint32_t c;
+       a = b = c = 1;
+                       ]])],
+               [ ac_cv_have_uintxx_t="yes" ], [ ac_cv_have_uintxx_t="no" 
+               ])
+       ])
+       if test "x$ac_cv_have_uintxx_t" = "xyes" ; then
+               AC_DEFINE([HAVE_UINTXX_T], [1],
+                       [define if you have uintxx_t data type])
+       fi
+fi
+
+if test -z "$have_uintxx_t" ; then
+    AC_MSG_CHECKING([for uintXX_t types in stdint.h])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdint.h> ]],
+       [[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;]])],
+               [
+                       AC_DEFINE([HAVE_UINTXX_T])
+                       AC_MSG_RESULT([yes])
+               ], [ AC_MSG_RESULT([no]) 
+       ])
+fi
+
+if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \
+          test "x$ac_cv_header_sys_bitypes_h" = "xyes")
+then
+       AC_MSG_CHECKING([for intXX_t and u_intXX_t types in sys/bitypes.h])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/bitypes.h>
+               ]], [[
+                       int8_t a; int16_t b; int32_t c;
+                       u_int8_t e; u_int16_t f; u_int32_t g;
+                       a = b = c = e = f = g = 1;
+               ]])],
+               [
+                       AC_DEFINE([HAVE_U_INTXX_T])
+                       AC_DEFINE([HAVE_INTXX_T])
+                       AC_MSG_RESULT([yes])
+               ], [AC_MSG_RESULT([no])
+       ])
+fi
+
+
+AC_CACHE_CHECK([for u_char], ac_cv_have_u_char, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ u_char foo; foo = 125; ]])],
+       [ ac_cv_have_u_char="yes" ], [ ac_cv_have_u_char="no" 
+       ])
+])
+if test "x$ac_cv_have_u_char" = "xyes" ; then
+       AC_DEFINE([HAVE_U_CHAR], [1], [define if you have u_char data type])
+fi
+
+TYPE_SOCKLEN_T
+
+AC_CHECK_TYPES([sig_atomic_t], , , [#include <signal.h>])
+AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [
+#include <sys/types.h>
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+])
+
+AC_CHECK_TYPES([in_addr_t, in_port_t], , ,
+[#include <sys/types.h>
+#include <netinet/in.h>])
+
+AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ size_t foo; foo = 1235; ]])],
+       [ ac_cv_have_size_t="yes" ], [ ac_cv_have_size_t="no" 
+       ])
+])
+if test "x$ac_cv_have_size_t" = "xyes" ; then
+       AC_DEFINE([HAVE_SIZE_T], [1], [define if you have size_t data type])
+fi
+
+AC_CACHE_CHECK([for ssize_t], ac_cv_have_ssize_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ ssize_t foo; foo = 1235; ]])],
+       [ ac_cv_have_ssize_t="yes" ], [ ac_cv_have_ssize_t="no" 
+       ])
+])
+if test "x$ac_cv_have_ssize_t" = "xyes" ; then
+       AC_DEFINE([HAVE_SSIZE_T], [1], [define if you have ssize_t data type])
+fi
+
+AC_CACHE_CHECK([for clock_t], ac_cv_have_clock_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <time.h> ]],
+       [[ clock_t foo; foo = 1235; ]])],
+       [ ac_cv_have_clock_t="yes" ], [ ac_cv_have_clock_t="no" 
+       ])
+])
+if test "x$ac_cv_have_clock_t" = "xyes" ; then
+       AC_DEFINE([HAVE_CLOCK_T], [1], [define if you have clock_t data type])
+fi
+
+AC_CACHE_CHECK([for sa_family_t], ac_cv_have_sa_family_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+               ]], [[ sa_family_t foo; foo = 1235; ]])],
+       [ ac_cv_have_sa_family_t="yes" ],
+       [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+               ]], [[ sa_family_t foo; foo = 1235; ]])],
+               [ ac_cv_have_sa_family_t="yes" ],
+               [ ac_cv_have_sa_family_t="no" ]
+       )
+       ])
+])
+if test "x$ac_cv_have_sa_family_t" = "xyes" ; then
+       AC_DEFINE([HAVE_SA_FAMILY_T], [1],
+               [define if you have sa_family_t data type])
+fi
+
+AC_CACHE_CHECK([for pid_t], ac_cv_have_pid_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ pid_t foo; foo = 1235; ]])],
+       [ ac_cv_have_pid_t="yes" ], [ ac_cv_have_pid_t="no" 
+       ])
+])
+if test "x$ac_cv_have_pid_t" = "xyes" ; then
+       AC_DEFINE([HAVE_PID_T], [1], [define if you have pid_t data type])
+fi
+
+AC_CACHE_CHECK([for mode_t], ac_cv_have_mode_t, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
+       [[ mode_t foo; foo = 1235; ]])],
+       [ ac_cv_have_mode_t="yes" ], [ ac_cv_have_mode_t="no" 
+       ])
+])
+if test "x$ac_cv_have_mode_t" = "xyes" ; then
+       AC_DEFINE([HAVE_MODE_T], [1], [define if you have mode_t data type])
+fi
+
+
+AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+               ]], [[ struct sockaddr_storage s; ]])],
+       [ ac_cv_have_struct_sockaddr_storage="yes" ],
+       [ ac_cv_have_struct_sockaddr_storage="no" 
+       ])
+])
+if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
+       AC_DEFINE([HAVE_STRUCT_SOCKADDR_STORAGE], [1],
+               [define if you have struct sockaddr_storage data type])
+fi
+
+AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <netinet/in.h>
+               ]], [[ struct sockaddr_in6 s; s.sin6_family = 0; ]])],
+       [ ac_cv_have_struct_sockaddr_in6="yes" ],
+       [ ac_cv_have_struct_sockaddr_in6="no" 
+       ])
+])
+if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
+       AC_DEFINE([HAVE_STRUCT_SOCKADDR_IN6], [1],
+               [define if you have struct sockaddr_in6 data type])
+fi
+
+AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <netinet/in.h>
+               ]], [[ struct in6_addr s; s.s6_addr[0] = 0; ]])],
+       [ ac_cv_have_struct_in6_addr="yes" ],
+       [ ac_cv_have_struct_in6_addr="no" 
+       ])
+])
+if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
+       AC_DEFINE([HAVE_STRUCT_IN6_ADDR], [1],
+               [define if you have struct in6_addr data type])
+
+dnl Now check for sin6_scope_id
+       AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id], , ,
+               [
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <netinet/in.h>
+               ])
+fi
+
+AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+               ]], [[ struct addrinfo s; s.ai_flags = AI_PASSIVE; ]])],
+       [ ac_cv_have_struct_addrinfo="yes" ],
+       [ ac_cv_have_struct_addrinfo="no" 
+       ])
+])
+if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
+       AC_DEFINE([HAVE_STRUCT_ADDRINFO], [1],
+               [define if you have struct addrinfo data type])
+fi
+
+AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/time.h> ]],
+       [[ struct timeval tv; tv.tv_sec = 1;]])],
+       [ ac_cv_have_struct_timeval="yes" ],
+       [ ac_cv_have_struct_timeval="no" 
+       ])
+])
+if test "x$ac_cv_have_struct_timeval" = "xyes" ; then
+       AC_DEFINE([HAVE_STRUCT_TIMEVAL], [1], [define if you have struct timeval])
+       have_struct_timeval=1
+fi
+
+AC_CHECK_TYPES([struct timespec])
+
+# We need int64_t or else certian parts of the compile will fail.
+if test "x$ac_cv_have_int64_t" = "xno" && \
+       test "x$ac_cv_sizeof_long_int" != "x8" && \
+       test "x$ac_cv_sizeof_long_long_int" = "x0" ; then
+       echo "OpenSSH requires int64_t support.  Contact your vendor or install"
+       echo "an alternative compiler (I.E., GCC) before continuing."
+       echo ""
+       exit 1;
+else
+dnl test snprintf (broken on SCO w/gcc)
+       AC_RUN_IFELSE(
+               [AC_LANG_SOURCE([[
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_SNPRINTF
+main()
+{
+       char buf[50];
+       char expected_out[50];
+       int mazsize = 50 ;
+#if (SIZEOF_LONG_INT == 8)
+       long int num = 0x7fffffffffffffff;
+#else
+       long long num = 0x7fffffffffffffffll;
+#endif
+       strcpy(expected_out, "9223372036854775807");
+       snprintf(buf, mazsize, "%lld", num);
+       if(strcmp(buf, expected_out) != 0)
+               exit(1);
+       exit(0);
+}
+#else
+main() { exit(0); }
+#endif
+               ]])], [ true ], [ AC_DEFINE([BROKEN_SNPRINTF]) ],
+               AC_MSG_WARN([cross compiling: Assuming working snprintf()])
+       )
+fi
+
+dnl Checks for structure members
+OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmp.h], [HAVE_HOST_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmpx.h], [HAVE_HOST_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([syslen], [utmpx.h], [HAVE_SYSLEN_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_pid], [utmp.h], [HAVE_PID_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmp.h], [HAVE_TYPE_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmpx.h], [HAVE_TYPE_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmp.h], [HAVE_TV_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmp.h], [HAVE_ID_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmpx.h], [HAVE_ID_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmp.h], [HAVE_ADDR_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmpx.h], [HAVE_ADDR_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmp.h], [HAVE_ADDR_V6_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmpx.h], [HAVE_ADDR_V6_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_exit], [utmp.h], [HAVE_EXIT_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmp.h], [HAVE_TIME_IN_UTMP])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX])
+
+AC_CHECK_MEMBERS([struct stat.st_blksize])
+AC_CHECK_MEMBER([struct __res_state.retrans], [], [AC_DEFINE([__res_state], [state],
+       [Define if we don't have struct __res_state in resolv.h])],
+[
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+])
+
+AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage],
+               ac_cv_have_ss_family_in_struct_ss, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+               ]], [[ struct sockaddr_storage s; s.ss_family = 1; ]])],
+       [ ac_cv_have_ss_family_in_struct_ss="yes" ],
+       [ ac_cv_have_ss_family_in_struct_ss="no" ])
+])
+if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then
+       AC_DEFINE([HAVE_SS_FAMILY_IN_SS], [1], [Fields in struct sockaddr_storage])
+fi
+
+AC_CACHE_CHECK([for __ss_family field in struct sockaddr_storage],
+               ac_cv_have___ss_family_in_struct_ss, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+               ]], [[ struct sockaddr_storage s; s.__ss_family = 1; ]])],
+       [ ac_cv_have___ss_family_in_struct_ss="yes" ],
+       [ ac_cv_have___ss_family_in_struct_ss="no" 
+       ])
+])
+if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
+       AC_DEFINE([HAVE___SS_FAMILY_IN_SS], [1],
+               [Fields in struct sockaddr_storage])
+fi
+
+AC_CACHE_CHECK([for pw_class field in struct passwd],
+               ac_cv_have_pw_class_in_struct_passwd, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <pwd.h> ]],
+       [[ struct passwd p; p.pw_class = 0; ]])],
+       [ ac_cv_have_pw_class_in_struct_passwd="yes" ],
+       [ ac_cv_have_pw_class_in_struct_passwd="no" 
+       ])
+])
+if test "x$ac_cv_have_pw_class_in_struct_passwd" = "xyes" ; then
+       AC_DEFINE([HAVE_PW_CLASS_IN_PASSWD], [1],
+               [Define if your password has a pw_class field])
+fi
+
+AC_CACHE_CHECK([for pw_expire field in struct passwd],
+               ac_cv_have_pw_expire_in_struct_passwd, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <pwd.h> ]],
+       [[ struct passwd p; p.pw_expire = 0; ]])],
+       [ ac_cv_have_pw_expire_in_struct_passwd="yes" ],
+       [ ac_cv_have_pw_expire_in_struct_passwd="no" 
+       ])
+])
+if test "x$ac_cv_have_pw_expire_in_struct_passwd" = "xyes" ; then
+       AC_DEFINE([HAVE_PW_EXPIRE_IN_PASSWD], [1],
+               [Define if your password has a pw_expire field])
+fi
+
+AC_CACHE_CHECK([for pw_change field in struct passwd],
+               ac_cv_have_pw_change_in_struct_passwd, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <pwd.h> ]],
+       [[ struct passwd p; p.pw_change = 0; ]])],
+       [ ac_cv_have_pw_change_in_struct_passwd="yes" ],
+       [ ac_cv_have_pw_change_in_struct_passwd="no" 
+       ])
+])
+if test "x$ac_cv_have_pw_change_in_struct_passwd" = "xyes" ; then
+       AC_DEFINE([HAVE_PW_CHANGE_IN_PASSWD], [1],
+               [Define if your password has a pw_change field])
+fi
+
+dnl make sure we're using the real structure members and not defines
+AC_CACHE_CHECK([for msg_accrights field in struct msghdr],
+               ac_cv_have_accrights_in_msghdr, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+               ]], [[
+#ifdef msg_accrights
+#error "msg_accrights is a macro"
+exit(1);
+#endif
+struct msghdr m;
+m.msg_accrights = 0;
+exit(0);
+               ]])],
+               [ ac_cv_have_accrights_in_msghdr="yes" ],
+               [ ac_cv_have_accrights_in_msghdr="no" ]
+       )
+])
+if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then
+       AC_DEFINE([HAVE_ACCRIGHTS_IN_MSGHDR], [1],
+               [Define if your system uses access rights style
+               file descriptor passing])
+fi
+
+AC_MSG_CHECKING([if struct statvfs.f_fsid is integral type])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+       ]], [[ struct statvfs s; s.f_fsid = 0; ]])],
+       [ AC_MSG_RESULT([yes]) ],
+       [ AC_MSG_RESULT([no])
+
+       AC_MSG_CHECKING([if fsid_t has member val])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/statvfs.h>
+       ]], [[ fsid_t t; t.val[0] = 0; ]])],
+       [ AC_MSG_RESULT([yes])
+         AC_DEFINE([FSID_HAS_VAL], [1], [fsid_t has member val]) ],
+       [ AC_MSG_RESULT([no]) ])
+
+       AC_MSG_CHECKING([if f_fsid has member __val])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/statvfs.h>
+       ]], [[ fsid_t t; t.__val[0] = 0; ]])],
+       [ AC_MSG_RESULT([yes])
+         AC_DEFINE([FSID_HAS___VAL], [1], [fsid_t has member __val]) ],
+       [ AC_MSG_RESULT([no]) ])
+])
+
+AC_CACHE_CHECK([for msg_control field in struct msghdr],
+               ac_cv_have_control_in_msghdr, [
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+               ]], [[
+#ifdef msg_control
+#error "msg_control is a macro"
+exit(1);
+#endif
+struct msghdr m;
+m.msg_control = 0;
+exit(0);
+               ]])],
+               [ ac_cv_have_control_in_msghdr="yes" ],
+               [ ac_cv_have_control_in_msghdr="no" ]
+       )
+])
+if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then
+       AC_DEFINE([HAVE_CONTROL_IN_MSGHDR], [1],
+               [Define if your system uses ancillary data style
+               file descriptor passing])
+fi
+
+AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+               [[ extern char *__progname; printf("%s", __progname); ]])],
+       [ ac_cv_libc_defines___progname="yes" ],
+       [ ac_cv_libc_defines___progname="no" 
+       ])
+])
+if test "x$ac_cv_libc_defines___progname" = "xyes" ; then
+       AC_DEFINE([HAVE___PROGNAME], [1], [Define if libc defines __progname])
+fi
+
+AC_CACHE_CHECK([whether $CC implements __FUNCTION__], ac_cv_cc_implements___FUNCTION__, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+               [[ printf("%s", __FUNCTION__); ]])],
+       [ ac_cv_cc_implements___FUNCTION__="yes" ],
+       [ ac_cv_cc_implements___FUNCTION__="no" 
+       ])
+])
+if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then
+       AC_DEFINE([HAVE___FUNCTION__], [1],
+               [Define if compiler implements __FUNCTION__])
+fi
+
+AC_CACHE_CHECK([whether $CC implements __func__], ac_cv_cc_implements___func__, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+               [[ printf("%s", __func__); ]])],
+       [ ac_cv_cc_implements___func__="yes" ],
+       [ ac_cv_cc_implements___func__="no" 
+       ])
+])
+if test "x$ac_cv_cc_implements___func__" = "xyes" ; then
+       AC_DEFINE([HAVE___func__], [1], [Define if compiler implements __func__])
+fi
+
+AC_CACHE_CHECK([whether va_copy exists], ac_cv_have_va_copy, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <stdarg.h>
+va_list x,y;
+               ]], [[ va_copy(x,y); ]])],
+       [ ac_cv_have_va_copy="yes" ],
+       [ ac_cv_have_va_copy="no" 
+       ])
+])
+if test "x$ac_cv_have_va_copy" = "xyes" ; then
+       AC_DEFINE([HAVE_VA_COPY], [1], [Define if va_copy exists])
+fi
+
+AC_CACHE_CHECK([whether __va_copy exists], ac_cv_have___va_copy, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <stdarg.h>
+va_list x,y;
+               ]], [[ __va_copy(x,y); ]])],
+       [ ac_cv_have___va_copy="yes" ], [ ac_cv_have___va_copy="no" 
+       ])
+])
+if test "x$ac_cv_have___va_copy" = "xyes" ; then
+       AC_DEFINE([HAVE___VA_COPY], [1], [Define if __va_copy exists])
+fi
+
+AC_CACHE_CHECK([whether getopt has optreset support],
+               ac_cv_have_getopt_optreset, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <getopt.h> ]],
+               [[ extern int optreset; optreset = 0; ]])],
+       [ ac_cv_have_getopt_optreset="yes" ],
+       [ ac_cv_have_getopt_optreset="no" 
+       ])
+])
+if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then
+       AC_DEFINE([HAVE_GETOPT_OPTRESET], [1],
+               [Define if your getopt(3) defines and uses optreset])
+fi
+
+AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+[[ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);]])],
+       [ ac_cv_libc_defines_sys_errlist="yes" ],
+       [ ac_cv_libc_defines_sys_errlist="no" 
+       ])
+])
+if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then
+       AC_DEFINE([HAVE_SYS_ERRLIST], [1],
+               [Define if your system defines sys_errlist[]])
+fi
+
+
+AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [
+       AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+[[ extern int sys_nerr; printf("%i", sys_nerr);]])],
+       [ ac_cv_libc_defines_sys_nerr="yes" ],
+       [ ac_cv_libc_defines_sys_nerr="no" 
+       ])
+])
+if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
+       AC_DEFINE([HAVE_SYS_NERR], [1], [Define if your system defines sys_nerr])
+fi
+
+# Check libraries needed by DNS fingerprint support
+AC_SEARCH_LIBS([getrrsetbyname], [resolv],
+       [AC_DEFINE([HAVE_GETRRSETBYNAME], [1],
+               [Define if getrrsetbyname() exists])],
+       [
+               # Needed by our getrrsetbyname()
+               AC_SEARCH_LIBS([res_query], [resolv])
+               AC_SEARCH_LIBS([dn_expand], [resolv])
+               AC_MSG_CHECKING([if res_query will link])
+               AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+                               ]], [[
+       res_query (0, 0, 0, 0, 0);
+                               ]])],
+                   AC_MSG_RESULT([yes]),
+                  [AC_MSG_RESULT([no])
+                   saved_LIBS="$LIBS"
+                   LIBS="$LIBS -lresolv"
+                   AC_MSG_CHECKING([for res_query in -lresolv])
+                   AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+                               ]], [[
+       res_query (0, 0, 0, 0, 0);
+                               ]])],
+                       [AC_MSG_RESULT([yes])],
+                       [LIBS="$saved_LIBS"
+                        AC_MSG_RESULT([no])])
+                   ])
+               AC_CHECK_FUNCS([_getshort _getlong])
+               AC_CHECK_DECLS([_getshort, _getlong], , ,
+                   [#include <sys/types.h>
+                   #include <arpa/nameser.h>])
+               AC_CHECK_MEMBER([HEADER.ad],
+                       [AC_DEFINE([HAVE_HEADER_AD], [1],
+                           [Define if HEADER.ad exists in arpa/nameser.h])], ,
+                       [#include <arpa/nameser.h>])
+       ])
+
+AC_MSG_CHECKING([if struct __res_state _res is an extern])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+extern struct __res_state _res;
+               ]], [[ ]])],
+               [AC_MSG_RESULT([yes])
+                AC_DEFINE([HAVE__RES_EXTERN], [1],
+                   [Define if you have struct __res_state _res as an extern])
+               ],
+               [ AC_MSG_RESULT([no]) ]
+)
+
+# Check whether user wants SELinux support
+SELINUX_MSG="no"
+LIBSELINUX=""
+AC_ARG_WITH([selinux],
+       [  --with-selinux          Enable SELinux support],
+       [ if test "x$withval" != "xno" ; then
+               save_LIBS="$LIBS"
+               AC_DEFINE([WITH_SELINUX], [1],
+                       [Define if you want SELinux support.])
+               SELINUX_MSG="yes"
+               AC_CHECK_HEADER([selinux/selinux.h], ,
+                       AC_MSG_ERROR([SELinux support requires selinux.h header]))
+               AC_CHECK_LIB([selinux], [setexeccon],
+                       [ LIBSELINUX="-lselinux"
+                         LIBS="$LIBS -lselinux"
+                       ],
+                       AC_MSG_ERROR([SELinux support requires libselinux library]))
+               SSHLIBS="$SSHLIBS $LIBSELINUX"
+               SSHDLIBS="$SSHDLIBS $LIBSELINUX"
+               AC_CHECK_FUNCS([getseuserbyname get_default_context_with_level])
+               LIBS="$save_LIBS"
+       fi ]
+)
+AC_SUBST([SSHLIBS])
+AC_SUBST([SSHDLIBS])
+
+# Check whether user wants Kerberos 5 support
+KRB5_MSG="no"
+AC_ARG_WITH([kerberos5],
+       [  --with-kerberos5=PATH   Enable Kerberos 5 support],
+       [ if test "x$withval" != "xno" ; then
+               if test "x$withval" = "xyes" ; then
+                       KRB5ROOT="/usr/local"
+               else
+                       KRB5ROOT=${withval}
+               fi
+
+               AC_DEFINE([KRB5], [1], [Define if you want Kerberos 5 support])
+               KRB5_MSG="yes"
+
+               AC_PATH_PROG([KRB5CONF], [krb5-config],
+                            [$KRB5ROOT/bin/krb5-config],
+                            [$KRB5ROOT/bin:$PATH])
+               if test -x $KRB5CONF ; then
+
+                       AC_MSG_CHECKING([for gssapi support])
+                       if $KRB5CONF | grep gssapi >/dev/null ; then
+                               AC_MSG_RESULT([yes])
+                               AC_DEFINE([GSSAPI], [1],
+                                       [Define this if you want GSSAPI
+                                       support in the version 2 protocol])
+                               k5confopts=gssapi
+                       else
+                               AC_MSG_RESULT([no])
+                               k5confopts=""
+                       fi
+                       K5CFLAGS="`$KRB5CONF --cflags $k5confopts`"
+                       K5LIBS="`$KRB5CONF --libs $k5confopts`"
+                       CPPFLAGS="$CPPFLAGS $K5CFLAGS"
+                       AC_MSG_CHECKING([whether we are using Heimdal])
+                       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <krb5.h>
+                               ]], [[ char *tmp = heimdal_version; ]])],
+                               [ AC_MSG_RESULT([yes])
+                               AC_DEFINE([HEIMDAL], [1],
+                               [Define this if you are using the Heimdal
+                               version of Kerberos V5]) ],
+                               [AC_MSG_RESULT([no])
+                       ])
+               else
+                       CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include"
+                       LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib"
+                       AC_MSG_CHECKING([whether we are using Heimdal])
+                       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <krb5.h>
+                               ]], [[ char *tmp = heimdal_version; ]])],
+                                       [ AC_MSG_RESULT([yes])
+                                        AC_DEFINE([HEIMDAL])
+                                        K5LIBS="-lkrb5"
+                                        K5LIBS="$K5LIBS -lcom_err -lasn1"
+                                        AC_CHECK_LIB([roken], [net_write],
+                                          [K5LIBS="$K5LIBS -lroken"])
+                                        AC_CHECK_LIB([des], [des_cbc_encrypt],
+                                          [K5LIBS="$K5LIBS -ldes"])
+                                      ], [ AC_MSG_RESULT([no])
+                                        K5LIBS="-lkrb5 -lk5crypto -lcom_err"
+                                      
+                       ])
+                       AC_SEARCH_LIBS([dn_expand], [resolv])
+
+                       AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context],
+                               [ AC_DEFINE([GSSAPI])
+                                 K5LIBS="-lgssapi_krb5 $K5LIBS" ],
+                               [ AC_CHECK_LIB([gssapi], [gss_init_sec_context],
+                                       [ AC_DEFINE([GSSAPI])
+                                         K5LIBS="-lgssapi $K5LIBS" ],
+                                       AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail]),
+                                       $K5LIBS)
+                               ],
+                               $K5LIBS)
+
+                       AC_CHECK_HEADER([gssapi.h], ,
+                               [ unset ac_cv_header_gssapi_h
+                                 CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+                                 AC_CHECK_HEADERS([gssapi.h], ,
+                                       AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail])
+                                 )
+                               ]
+                       )
+
+                       oldCPP="$CPPFLAGS"
+                       CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+                       AC_CHECK_HEADER([gssapi_krb5.h], ,
+                                       [ CPPFLAGS="$oldCPP" ])
+
+               fi
+               if test ! -z "$need_dash_r" ; then
+                       LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
+               fi
+               if test ! -z "$blibpath" ; then
+                       blibpath="$blibpath:${KRB5ROOT}/lib"
+               fi
+
+               AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h])
+               AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h])
+               AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h])
+
+               LIBS="$LIBS $K5LIBS"
+               AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1],
+                       [Define this if you want to use libkafs' AFS support])])
+       fi
+       ]
+)
+
+# Looking for programs, paths and files
+
+PRIVSEP_PATH=/var/empty
+AC_ARG_WITH([privsep-path],
+       [  --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       PRIVSEP_PATH=$withval
+               fi
+       ]
+)
+AC_SUBST([PRIVSEP_PATH])
+
+AC_ARG_WITH([xauth],
+       [  --with-xauth=PATH       Specify path to xauth program ],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       xauth_path=$withval
+               fi
+       ],
+       [
+               TestPath="$PATH"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/bin/X11"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/X11R6/bin"
+               TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin"
+               AC_PATH_PROG([xauth_path], [xauth], , [$TestPath])
+               if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then
+                       xauth_path="/usr/openwin/bin/xauth"
+               fi
+       ]
+)
+
+STRIP_OPT=-s
+AC_ARG_ENABLE([strip],
+       [  --disable-strip         Disable calling strip(1) on install],
+       [
+               if test "x$enableval" = "xno" ; then
+                       STRIP_OPT=
+               fi
+       ]
+)
+AC_SUBST([STRIP_OPT])
+
+if test -z "$xauth_path" ; then
+       XAUTH_PATH="undefined"
+       AC_SUBST([XAUTH_PATH])
+else
+       AC_DEFINE_UNQUOTED([XAUTH_PATH], ["$xauth_path"],
+               [Define if xauth is found in your path])
+       XAUTH_PATH=$xauth_path
+       AC_SUBST([XAUTH_PATH])
+fi
+
+dnl # --with-maildir=/path/to/mail gets top priority.
+dnl # if maildir is set in the platform case statement above we use that.
+dnl # Otherwise we run a program to get the dir from system headers.
+dnl # We first look for _PATH_MAILDIR then MAILDIR then _PATH_MAIL
+dnl # If we find _PATH_MAILDIR we do nothing because that is what
+dnl # session.c expects anyway. Otherwise we set to the value found
+dnl # stripping any trailing slash. If for some strage reason our program
+dnl # does not find what it needs, we default to /var/spool/mail.
+# Check for mail directory
+AC_ARG_WITH([maildir],
+    [  --with-maildir=/path/to/mail    Specify your system mail directory],
+    [
+       if test "X$withval" != X  &&  test "x$withval" != xno  &&  \
+           test "x${withval}" != xyes; then
+               AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$withval"],
+            [Set this to your mail directory if you do not have _PATH_MAILDIR])
+           fi
+     ],[
+       if test "X$maildir" != "X"; then
+           AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"])
+       else
+           AC_MSG_CHECKING([Discovering system mail directory])
+           AC_RUN_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_MAILLOCK_H
+#include <maillock.h>
+#endif
+#define DATA "conftest.maildir"
+       ]], [[
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+#if defined (_PATH_MAILDIR)
+       if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0)
+               exit(1);
+#elif defined (MAILDIR)
+       if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0)
+               exit(1);
+#elif defined (_PATH_MAIL)
+       if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0)
+               exit(1);
+#else
+       exit (2);
+#endif
+
+       exit(0);
+               ]])],
+               [
+                   maildir_what=`awk -F: '{print $1}' conftest.maildir`
+                   maildir=`awk -F: '{print $2}' conftest.maildir \
+                       | sed 's|/$||'`
+                   AC_MSG_RESULT([Using: $maildir from $maildir_what])
+                   if test "x$maildir_what" != "x_PATH_MAILDIR"; then
+                       AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"])
+                   fi
+               ],
+               [
+                   if test "X$ac_status" = "X2";then
+# our test program didn't find it. Default to /var/spool/mail
+                       AC_MSG_RESULT([Using: default value of /var/spool/mail])
+                       AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["/var/spool/mail"])
+                    else
+                       AC_MSG_RESULT([*** not found ***])
+                    fi
+               ],
+               [
+                       AC_MSG_WARN([cross compiling: use --with-maildir=/path/to/mail])
+               ]
+           )
+       fi
+    ]
+) # maildir
+
+if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then
+       AC_MSG_WARN([cross compiling: Disabling /dev/ptmx test])
+       disable_ptmx_check=yes
+fi
+if test -z "$no_dev_ptmx" ; then
+       if test "x$disable_ptmx_check" != "xyes" ; then
+               AC_CHECK_FILE(["/dev/ptmx"],
+                       [
+                               AC_DEFINE_UNQUOTED([HAVE_DEV_PTMX], [1],
+                                       [Define if you have /dev/ptmx])
+                               have_dev_ptmx=1
+                       ]
+               )
+       fi
+fi
+
+if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then
+       AC_CHECK_FILE(["/dev/ptc"],
+               [
+                       AC_DEFINE_UNQUOTED([HAVE_DEV_PTS_AND_PTC], [1],
+                               [Define if you have /dev/ptc])
+                       have_dev_ptc=1
+               ]
+       )
+else
+       AC_MSG_WARN([cross compiling: Disabling /dev/ptc test])
+fi
+
+# Options from here on. Some of these are preset by platform above
+AC_ARG_WITH([mantype],
+       [  --with-mantype=man|cat|doc  Set man page type],
+       [
+               case "$withval" in
+               man|cat|doc)
+                       MANTYPE=$withval
+                       ;;
+               *)
+                       AC_MSG_ERROR([invalid man type: $withval])
+                       ;;
+               esac
+       ]
+)
+if test -z "$MANTYPE"; then
+       TestPath="/usr/bin${PATH_SEPARATOR}/usr/ucb"
+       AC_PATH_PROGS([NROFF], [nroff awf], [/bin/false], [$TestPath])
+       if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then
+               MANTYPE=doc
+       elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then
+               MANTYPE=man
+       else
+               MANTYPE=cat
+       fi
+fi
+AC_SUBST([MANTYPE])
+if test "$MANTYPE" = "doc"; then
+       mansubdir=man;
+else
+       mansubdir=$MANTYPE;
+fi
+AC_SUBST([mansubdir])
+
+# Check whether to enable MD5 passwords
+MD5_MSG="no"
+AC_ARG_WITH([md5-passwords],
+       [  --with-md5-passwords    Enable use of MD5 passwords],
+       [
+               if test "x$withval" != "xno" ; then
+                       AC_DEFINE([HAVE_MD5_PASSWORDS], [1],
+                               [Define if you want to allow MD5 passwords])
+                       MD5_MSG="yes"
+               fi
+       ]
+)
+
+# Whether to disable shadow password support
+AC_ARG_WITH([shadow],
+       [  --without-shadow        Disable shadow password support],
+       [
+               if test "x$withval" = "xno" ; then
+                       AC_DEFINE([DISABLE_SHADOW])
+                       disable_shadow=yes
+               fi
+       ]
+)
+
+if test -z "$disable_shadow" ; then
+       AC_MSG_CHECKING([if the systems has expire shadow information])
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <shadow.h>
+struct spwd sp;
+               ]], [[ sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ]])],
+               [ sp_expire_available=yes ], [
+       ])
+
+       if test "x$sp_expire_available" = "xyes" ; then
+               AC_MSG_RESULT([yes])
+               AC_DEFINE([HAS_SHADOW_EXPIRE], [1],
+                   [Define if you want to use shadow password expire field])
+       else
+               AC_MSG_RESULT([no])
+       fi
+fi
+
+# Use ip address instead of hostname in $DISPLAY
+if test ! -z "$IPADDR_IN_DISPLAY" ; then
+       DISPLAY_HACK_MSG="yes"
+       AC_DEFINE([IPADDR_IN_DISPLAY], [1],
+               [Define if you need to use IP address
+               instead of hostname in $DISPLAY])
+else
+       DISPLAY_HACK_MSG="no"
+       AC_ARG_WITH([ipaddr-display],
+               [  --with-ipaddr-display   Use ip address instead of hostname in \$DISPLAY],
+               [
+                       if test "x$withval" != "xno" ; then
+                               AC_DEFINE([IPADDR_IN_DISPLAY])
+                               DISPLAY_HACK_MSG="yes"
+                       fi
+               ]
+       )
+fi
+
+# check for /etc/default/login and use it if present.
+AC_ARG_ENABLE([etc-default-login],
+       [  --disable-etc-default-login Disable using PATH from /etc/default/login [no]],
+       [ if test "x$enableval" = "xno"; then
+               AC_MSG_NOTICE([/etc/default/login handling disabled])
+               etc_default_login=no
+         else
+               etc_default_login=yes
+         fi ],
+       [ if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes";
+         then
+               AC_MSG_WARN([cross compiling: not checking /etc/default/login])
+               etc_default_login=no
+         else
+               etc_default_login=yes
+         fi ]
+)
+
+if test "x$etc_default_login" != "xno"; then
+       AC_CHECK_FILE(["/etc/default/login"],
+           [ external_path_file=/etc/default/login ])
+       if test "x$external_path_file" = "x/etc/default/login"; then
+               AC_DEFINE([HAVE_ETC_DEFAULT_LOGIN], [1],
+                       [Define if your system has /etc/default/login])
+       fi
+fi
+
+dnl BSD systems use /etc/login.conf so --with-default-path= has no effect
+if test $ac_cv_func_login_getcapbool = "yes" && \
+       test $ac_cv_header_login_cap_h = "yes" ; then
+       external_path_file=/etc/login.conf
+fi
+
+# Whether to mess with the default path
+SERVER_PATH_MSG="(default)"
+AC_ARG_WITH([default-path],
+       [  --with-default-path=    Specify default \$PATH environment for server],
+       [
+               if test "x$external_path_file" = "x/etc/login.conf" ; then
+                       AC_MSG_WARN([
+--with-default-path=PATH has no effect on this system.
+Edit /etc/login.conf instead.])
+               elif test "x$withval" != "xno" ; then
+                       if test ! -z "$external_path_file" ; then
+                               AC_MSG_WARN([
+--with-default-path=PATH will only be used if PATH is not defined in
+$external_path_file .])
+                       fi
+                       user_path="$withval"
+                       SERVER_PATH_MSG="$withval"
+               fi
+       ],
+       [ if test "x$external_path_file" = "x/etc/login.conf" ; then
+               AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf])
+       else
+               if test ! -z "$external_path_file" ; then
+                       AC_MSG_WARN([
+If PATH is defined in $external_path_file, ensure the path to scp is included,
+otherwise scp will not work.])
+               fi
+               AC_RUN_IFELSE(
+                       [AC_LANG_PROGRAM([[
+/* find out what STDPATH is */
+#include <stdio.h>
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+#ifndef _PATH_STDPATH
+# ifdef _PATH_USERPATH /* Irix */
+#  define _PATH_STDPATH _PATH_USERPATH
+# else
+#  define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
+# endif
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#define DATA "conftest.stdpath"
+                       ]], [[
+       FILE *fd;
+       int rc;
+
+       fd = fopen(DATA,"w");
+       if(fd == NULL)
+               exit(1);
+
+       if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0)
+               exit(1);
+
+       exit(0);
+               ]])],
+               [ user_path=`cat conftest.stdpath` ],
+               [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ],
+               [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ]
+       )
+# make sure $bindir is in USER_PATH so scp will work
+               t_bindir=`eval echo ${bindir}`
+               case $t_bindir in
+                       NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;;
+               esac
+               case $t_bindir in
+                       NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;;
+               esac
+               echo $user_path | grep ":$t_bindir"  > /dev/null 2>&1
+               if test $? -ne 0  ; then
+                       echo $user_path | grep "^$t_bindir"  > /dev/null 2>&1
+                       if test $? -ne 0  ; then
+                               user_path=$user_path:$t_bindir
+                               AC_MSG_RESULT([Adding $t_bindir to USER_PATH so scp will work])
+                       fi
+               fi
+       fi ]
+)
+if test "x$external_path_file" != "x/etc/login.conf" ; then
+       AC_DEFINE_UNQUOTED([USER_PATH], ["$user_path"], [Specify default $PATH])
+       AC_SUBST([user_path])
+fi
+
+# Set superuser path separately to user path
+AC_ARG_WITH([superuser-path],
+       [  --with-superuser-path=  Specify different path for super-user],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       AC_DEFINE_UNQUOTED([SUPERUSER_PATH], ["$withval"],
+                               [Define if you want a different $PATH
+                               for the superuser])
+                       superuser_path=$withval
+               fi
+       ]
+)
+
+
+AC_MSG_CHECKING([if we need to convert IPv4 in IPv6-mapped addresses])
+IPV4_IN6_HACK_MSG="no"
+AC_ARG_WITH(4in6,
+       [  --with-4in6             Check for and convert IPv4 in IPv6 mapped addresses],
+       [
+               if test "x$withval" != "xno" ; then
+                       AC_MSG_RESULT([yes])
+                       AC_DEFINE([IPV4_IN_IPV6], [1],
+                               [Detect IPv4 in IPv6 mapped addresses
+                               and treat as IPv4])
+                       IPV4_IN6_HACK_MSG="yes"
+               else
+                       AC_MSG_RESULT([no])
+               fi
+       ], [
+               if test "x$inet6_default_4in6" = "xyes"; then
+                       AC_MSG_RESULT([yes (default)])
+                       AC_DEFINE([IPV4_IN_IPV6])
+                       IPV4_IN6_HACK_MSG="yes"
+               else
+                       AC_MSG_RESULT([no (default)])
+               fi
+       ]
+)
+
+# Whether to enable BSD auth support
+BSD_AUTH_MSG=no
+AC_ARG_WITH([bsd-auth],
+       [  --with-bsd-auth         Enable BSD auth support],
+       [
+               if test "x$withval" != "xno" ; then
+                       AC_DEFINE([BSD_AUTH], [1],
+                               [Define if you have BSD auth support])
+                       BSD_AUTH_MSG=yes
+               fi
+       ]
+)
+
+# Where to place sshd.pid
+piddir=/var/run
+# make sure the directory exists
+if test ! -d $piddir ; then
+       piddir=`eval echo ${sysconfdir}`
+       case $piddir in
+               NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;;
+       esac
+fi
+
+AC_ARG_WITH([pid-dir],
+       [  --with-pid-dir=PATH     Specify location of ssh.pid file],
+       [
+               if test -n "$withval"  &&  test "x$withval" != "xno"  &&  \
+                   test "x${withval}" != "xyes"; then
+                       piddir=$withval
+                       if test ! -d $piddir ; then
+                       AC_MSG_WARN([** no $piddir directory on this system **])
+                       fi
+               fi
+       ]
+)
+
+AC_DEFINE_UNQUOTED([_PATH_SSH_PIDDIR], ["$piddir"], 
+       [Specify location of ssh.pid])
+AC_SUBST([piddir])
+
+dnl allow user to disable some login recording features
+AC_ARG_ENABLE([lastlog],
+       [  --disable-lastlog       disable use of lastlog even if detected [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_LASTLOG])
+               fi
+       ]
+)
+AC_ARG_ENABLE([utmp],
+       [  --disable-utmp          disable use of utmp even if detected [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_UTMP])
+               fi
+       ]
+)
+AC_ARG_ENABLE([utmpx],
+       [  --disable-utmpx         disable use of utmpx even if detected [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_UTMPX], [1],
+                               [Define if you don't want to use utmpx])
+               fi
+       ]
+)
+AC_ARG_ENABLE([wtmp],
+       [  --disable-wtmp          disable use of wtmp even if detected [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_WTMP])
+               fi
+       ]
+)
+AC_ARG_ENABLE([wtmpx],
+       [  --disable-wtmpx         disable use of wtmpx even if detected [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_WTMPX], [1],
+                               [Define if you don't want to use wtmpx])
+               fi
+       ]
+)
+AC_ARG_ENABLE([libutil],
+       [  --disable-libutil       disable use of libutil (login() etc.) [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_LOGIN])
+               fi
+       ]
+)
+AC_ARG_ENABLE([pututline],
+       [  --disable-pututline     disable use of pututline() etc. ([uw]tmp) [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_PUTUTLINE], [1],
+                               [Define if you don't want to use pututline()
+                               etc. to write [uw]tmp])
+               fi
+       ]
+)
+AC_ARG_ENABLE([pututxline],
+       [  --disable-pututxline    disable use of pututxline() etc. ([uw]tmpx) [no]],
+       [
+               if test "x$enableval" = "xno" ; then
+                       AC_DEFINE([DISABLE_PUTUTXLINE], [1],
+                               [Define if you don't want to use pututxline()
+                               etc. to write [uw]tmpx])
+               fi
+       ]
+)
+AC_ARG_WITH([lastlog],
+  [  --with-lastlog=FILE|DIR specify lastlog location [common locations]],
+       [
+               if test "x$withval" = "xno" ; then
+                       AC_DEFINE([DISABLE_LASTLOG])
+               elif test -n "$withval"  &&  test "x${withval}" != "xyes"; then
+                       conf_lastlog_location=$withval
+               fi
+       ]
+)
+
+dnl lastlog, [uw]tmpx? detection
+dnl  NOTE: set the paths in the platform section to avoid the
+dnl   need for command-line parameters
+dnl lastlog and [uw]tmp are subject to a file search if all else fails
+
+dnl lastlog detection
+dnl  NOTE: the code itself will detect if lastlog is a directory
+AC_MSG_CHECKING([if your system defines LASTLOG_FILE])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_LASTLOG_H
+#  include <lastlog.h>
+#endif
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+#ifdef HAVE_LOGIN_H
+# include <login.h>
+#endif
+       ]], [[ char *lastlog = LASTLOG_FILE; ]])],
+               [ AC_MSG_RESULT([yes]) ],
+               [
+               AC_MSG_RESULT([no])
+               AC_MSG_CHECKING([if your system defines _PATH_LASTLOG])
+               AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_LASTLOG_H
+#  include <lastlog.h>
+#endif
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+               ]], [[ char *lastlog = _PATH_LASTLOG; ]])],
+               [ AC_MSG_RESULT([yes]) ],
+               [
+                       AC_MSG_RESULT([no])
+                       system_lastlog_path=no
+               ])
+])
+
+if test -z "$conf_lastlog_location"; then
+       if test x"$system_lastlog_path" = x"no" ; then
+               for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do
+                               if (test -d "$f" || test -f "$f") ; then
+                                       conf_lastlog_location=$f
+                               fi
+               done
+               if test -z "$conf_lastlog_location"; then
+                       AC_MSG_WARN([** Cannot find lastlog **])
+                       dnl Don't define DISABLE_LASTLOG - that means we don't try wtmp/wtmpx
+               fi
+       fi
+fi
+
+if test -n "$conf_lastlog_location"; then
+       AC_DEFINE_UNQUOTED([CONF_LASTLOG_FILE], ["$conf_lastlog_location"],
+               [Define if you want to specify the path to your lastlog file])
+fi
+
+dnl utmp detection
+AC_MSG_CHECKING([if your system defines UTMP_FILE])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+       ]], [[ char *utmp = UTMP_FILE; ]])],
+       [ AC_MSG_RESULT([yes]) ],
+       [ AC_MSG_RESULT([no])
+         system_utmp_path=no 
+])
+if test -z "$conf_utmp_location"; then
+       if test x"$system_utmp_path" = x"no" ; then
+               for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do
+                       if test -f $f ; then
+                               conf_utmp_location=$f
+                       fi
+               done
+               if test -z "$conf_utmp_location"; then
+                       AC_DEFINE([DISABLE_UTMP])
+               fi
+       fi
+fi
+if test -n "$conf_utmp_location"; then
+       AC_DEFINE_UNQUOTED([CONF_UTMP_FILE], ["$conf_utmp_location"],
+               [Define if you want to specify the path to your utmp file])
+fi
+
+dnl wtmp detection
+AC_MSG_CHECKING([if your system defines WTMP_FILE])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+       ]], [[ char *wtmp = WTMP_FILE; ]])],
+       [ AC_MSG_RESULT([yes]) ],
+       [ AC_MSG_RESULT([no])
+         system_wtmp_path=no 
+])
+if test -z "$conf_wtmp_location"; then
+       if test x"$system_wtmp_path" = x"no" ; then
+               for f in /usr/adm/wtmp /var/log/wtmp; do
+                       if test -f $f ; then
+                               conf_wtmp_location=$f
+                       fi
+               done
+               if test -z "$conf_wtmp_location"; then
+                       AC_DEFINE([DISABLE_WTMP])
+               fi
+       fi
+fi
+if test -n "$conf_wtmp_location"; then
+       AC_DEFINE_UNQUOTED([CONF_WTMP_FILE], ["$conf_wtmp_location"],
+               [Define if you want to specify the path to your wtmp file])
+fi
+
+
+dnl wtmpx detection
+AC_MSG_CHECKING([if your system defines WTMPX_FILE])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <utmp.h>
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#ifdef HAVE_PATHS_H
+#  include <paths.h>
+#endif
+       ]], [[ char *wtmpx = WTMPX_FILE; ]])],
+       [ AC_MSG_RESULT([yes]) ],
+       [ AC_MSG_RESULT([no])
+         system_wtmpx_path=no 
+])
+if test -z "$conf_wtmpx_location"; then
+       if test x"$system_wtmpx_path" = x"no" ; then
+               AC_DEFINE([DISABLE_WTMPX])
+       fi
+else
+       AC_DEFINE_UNQUOTED([CONF_WTMPX_FILE], ["$conf_wtmpx_location"],
+               [Define if you want to specify the path to your wtmpx file])
+fi
+
+
+if test ! -z "$blibpath" ; then
+       LDFLAGS="$LDFLAGS $blibflags$blibpath"
+       AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile])
+fi
+
+dnl Adding -Werror to CFLAGS early prevents configure tests from running.
+dnl Add now.
+CFLAGS="$CFLAGS $werror_flags"
+
+if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
+       TEST_SSH_IPV6=no
+else
+       TEST_SSH_IPV6=yes
+fi
+AC_CHECK_DECL([BROKEN_GETADDRINFO],  [TEST_SSH_IPV6=no])
+AC_SUBST([TEST_SSH_IPV6], [$TEST_SSH_IPV6])
+
+AC_EXEEXT
+AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
+       openbsd-compat/Makefile openbsd-compat/regress/Makefile \
+       survey.sh])
+AC_OUTPUT
+
+# Print summary of options
+
+# Someone please show me a better way :)
+A=`eval echo ${prefix}` ; A=`eval echo ${A}`
+B=`eval echo ${bindir}` ; B=`eval echo ${B}`
+C=`eval echo ${sbindir}` ; C=`eval echo ${C}`
+D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}`
+E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}`
+F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}`
+G=`eval echo ${piddir}` ; G=`eval echo ${G}`
+H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}`
+I=`eval echo ${user_path}` ; I=`eval echo ${I}`
+J=`eval echo ${superuser_path}` ; J=`eval echo ${J}`
+
+echo ""
+echo "OpenSSH has been configured with the following options:"
+echo "                     User binaries: $B"
+echo "                   System binaries: $C"
+echo "               Configuration files: $D"
+echo "                   Askpass program: $E"
+echo "                      Manual pages: $F"
+echo "                          PID file: $G"
+echo "  Privilege separation chroot path: $H"
+if test "x$external_path_file" = "x/etc/login.conf" ; then
+echo "   At runtime, sshd will use the path defined in $external_path_file"
+echo "   Make sure the path to scp is present, otherwise scp will not work"
+else
+echo "            sshd default user PATH: $I"
+       if test ! -z "$external_path_file"; then
+echo "   (If PATH is set in $external_path_file it will be used instead. If"
+echo "   used, ensure the path to scp is present, otherwise scp will not work.)"
+       fi
+fi
+if test ! -z "$superuser_path" ; then
+echo "          sshd superuser user PATH: $J"
+fi
+echo "                    Manpage format: $MANTYPE"
+echo "                       PAM support: $PAM_MSG"
+echo "                   OSF SIA support: $SIA_MSG"
+echo "                 KerberosV support: $KRB5_MSG"
+echo "                   SELinux support: $SELINUX_MSG"
+echo "                 Smartcard support: $SCARD_MSG"
+echo "                     S/KEY support: $SKEY_MSG"
+echo "              TCP Wrappers support: $TCPW_MSG"
+echo "              MD5 password support: $MD5_MSG"
+echo "                   libedit support: $LIBEDIT_MSG"
+echo "  Solaris process contract support: $SPC_MSG"
+echo "           Solaris project support: $SP_MSG"
+echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
+echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
+echo "                  BSD Auth support: $BSD_AUTH_MSG"
+echo "              Random number source: $RAND_MSG"
+echo "             Privsep sandbox style: $SANDBOX_STYLE"
+
+echo ""
+
+echo "              Host: ${host}"
+echo "          Compiler: ${CC}"
+echo "    Compiler flags: ${CFLAGS}"
+echo "Preprocessor flags: ${CPPFLAGS}"
+echo "      Linker flags: ${LDFLAGS}"
+echo "         Libraries: ${LIBS}"
+if test ! -z "${SSHDLIBS}"; then
+echo "         +for sshd: ${SSHDLIBS}"
+fi
+if test ! -z "${SSHLIBS}"; then
+echo "          +for ssh: ${SSHLIBS}"
+fi
+
+echo ""
+
+if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then
+       echo "SVR4 style packages are supported with \"make package\""
+       echo ""
+fi
+
+if test "x$PAM_MSG" = "xyes" ; then
+       echo "PAM is enabled. You may need to install a PAM control file "
+       echo "for sshd, otherwise password authentication may fail. "
+       echo "Example PAM control files can be found in the contrib/ "
+       echo "subdirectory"
+       echo ""
+fi
+
+if test ! -z "$NO_PEERCHECK" ; then
+       echo "WARNING: the operating system that you are using does not"
+       echo "appear to support getpeereid(), getpeerucred() or the"
+       echo "SO_PEERCRED getsockopt() option. These facilities are used to"
+       echo "enforce security checks to prevent unauthorised connections to"
+       echo "ssh-agent. Their absence increases the risk that a malicious"
+       echo "user can connect to your agent."
+       echo ""
+fi
+
+if test "$AUDIT_MODULE" = "bsm" ; then
+       echo "WARNING: BSM audit support is currently considered EXPERIMENTAL."
+       echo "See the Solaris section in README.platform for details."
+fi
diff --git a/.pc/gssapi.patch/gss-genr.c b/.pc/gssapi.patch/gss-genr.c
new file mode 100644 (file)
index 0000000..842f385
--- /dev/null
@@ -0,0 +1,281 @@
+/* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */
+
+/*
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#ifdef GSSAPI
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "log.h"
+#include "ssh2.h"
+
+#include "ssh-gss.h"
+
+extern u_char *session_id2;
+extern u_int session_id2_len;
+
+/* Check that the OID in a data stream matches that in the context */
+int
+ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
+{
+       return (ctx != NULL && ctx->oid != GSS_C_NO_OID &&
+           ctx->oid->length == len &&
+           memcmp(ctx->oid->elements, data, len) == 0);
+}
+
+/* Set the contexts OID from a data stream */
+void
+ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len)
+{
+       if (ctx->oid != GSS_C_NO_OID) {
+               xfree(ctx->oid->elements);
+               xfree(ctx->oid);
+       }
+       ctx->oid = xmalloc(sizeof(gss_OID_desc));
+       ctx->oid->length = len;
+       ctx->oid->elements = xmalloc(len);
+       memcpy(ctx->oid->elements, data, len);
+}
+
+/* Set the contexts OID */
+void
+ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid)
+{
+       ssh_gssapi_set_oid_data(ctx, oid->elements, oid->length);
+}
+
+/* All this effort to report an error ... */
+void
+ssh_gssapi_error(Gssctxt *ctxt)
+{
+       char *s;
+
+       s = ssh_gssapi_last_error(ctxt, NULL, NULL);
+       debug("%s", s);
+       xfree(s);
+}
+
+char *
+ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
+    OM_uint32 *minor_status)
+{
+       OM_uint32 lmin;
+       gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
+       OM_uint32 ctx;
+       Buffer b;
+       char *ret;
+
+       buffer_init(&b);
+
+       if (major_status != NULL)
+               *major_status = ctxt->major;
+       if (minor_status != NULL)
+               *minor_status = ctxt->minor;
+
+       ctx = 0;
+       /* The GSSAPI error */
+       do {
+               gss_display_status(&lmin, ctxt->major,
+                   GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg);
+
+               buffer_append(&b, msg.value, msg.length);
+               buffer_put_char(&b, '\n');
+
+               gss_release_buffer(&lmin, &msg);
+       } while (ctx != 0);
+
+       /* The mechanism specific error */
+       do {
+               gss_display_status(&lmin, ctxt->minor,
+                   GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg);
+
+               buffer_append(&b, msg.value, msg.length);
+               buffer_put_char(&b, '\n');
+
+               gss_release_buffer(&lmin, &msg);
+       } while (ctx != 0);
+
+       buffer_put_char(&b, '\0');
+       ret = xmalloc(buffer_len(&b));
+       buffer_get(&b, ret, buffer_len(&b));
+       buffer_free(&b);
+       return (ret);
+}
+
+/*
+ * Initialise our GSSAPI context. We use this opaque structure to contain all
+ * of the data which both the client and server need to persist across
+ * {accept,init}_sec_context calls, so that when we do it from the userauth
+ * stuff life is a little easier
+ */
+void
+ssh_gssapi_build_ctx(Gssctxt **ctx)
+{
+       *ctx = xcalloc(1, sizeof (Gssctxt));
+       (*ctx)->context = GSS_C_NO_CONTEXT;
+       (*ctx)->name = GSS_C_NO_NAME;
+       (*ctx)->oid = GSS_C_NO_OID;
+       (*ctx)->creds = GSS_C_NO_CREDENTIAL;
+       (*ctx)->client = GSS_C_NO_NAME;
+       (*ctx)->client_creds = GSS_C_NO_CREDENTIAL;
+}
+
+/* Delete our context, providing it has been built correctly */
+void
+ssh_gssapi_delete_ctx(Gssctxt **ctx)
+{
+       OM_uint32 ms;
+
+       if ((*ctx) == NULL)
+               return;
+       if ((*ctx)->context != GSS_C_NO_CONTEXT)
+               gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER);
+       if ((*ctx)->name != GSS_C_NO_NAME)
+               gss_release_name(&ms, &(*ctx)->name);
+       if ((*ctx)->oid != GSS_C_NO_OID) {
+               xfree((*ctx)->oid->elements);
+               xfree((*ctx)->oid);
+               (*ctx)->oid = GSS_C_NO_OID;
+       }
+       if ((*ctx)->creds != GSS_C_NO_CREDENTIAL)
+               gss_release_cred(&ms, &(*ctx)->creds);
+       if ((*ctx)->client != GSS_C_NO_NAME)
+               gss_release_name(&ms, &(*ctx)->client);
+       if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL)
+               gss_release_cred(&ms, &(*ctx)->client_creds);
+
+       xfree(*ctx);
+       *ctx = NULL;
+}
+
+/*
+ * Wrapper to init_sec_context
+ * Requires that the context contains:
+ *     oid
+ *     server name (from ssh_gssapi_import_name)
+ */
+OM_uint32
+ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
+    gss_buffer_desc* send_tok, OM_uint32 *flags)
+{
+       int deleg_flag = 0;
+
+       if (deleg_creds) {
+               deleg_flag = GSS_C_DELEG_FLAG;
+               debug("Delegating credentials");
+       }
+
+       ctx->major = gss_init_sec_context(&ctx->minor,
+           GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
+           GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
+           0, NULL, recv_tok, NULL, send_tok, flags, NULL);
+
+       if (GSS_ERROR(ctx->major))
+               ssh_gssapi_error(ctx);
+
+       return (ctx->major);
+}
+
+/* Create a service name for the given host */
+OM_uint32
+ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
+{
+       gss_buffer_desc gssbuf;
+       char *val;
+
+       xasprintf(&val, "host@%s", host);
+       gssbuf.value = val;
+       gssbuf.length = strlen(gssbuf.value);
+
+       if ((ctx->major = gss_import_name(&ctx->minor,
+           &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name)))
+               ssh_gssapi_error(ctx);
+
+       xfree(gssbuf.value);
+       return (ctx->major);
+}
+
+OM_uint32
+ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
+{
+       if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
+           GSS_C_QOP_DEFAULT, buffer, hash)))
+               ssh_gssapi_error(ctx);
+
+       return (ctx->major);
+}
+
+void
+ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
+    const char *context)
+{
+       buffer_init(b);
+       buffer_put_string(b, session_id2, session_id2_len);
+       buffer_put_char(b, SSH2_MSG_USERAUTH_REQUEST);
+       buffer_put_cstring(b, user);
+       buffer_put_cstring(b, service);
+       buffer_put_cstring(b, context);
+}
+
+int
+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
+{
+       gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
+
+       /* RFC 4462 says we MUST NOT do SPNEGO */
+       if (oid->length == spnego_oid.length && 
+           (memcmp(oid->elements, spnego_oid.elements, oid->length) == 0))
+               return 0; /* false */
+
+       ssh_gssapi_build_ctx(ctx);
+       ssh_gssapi_set_oid(*ctx, oid);
+       major = ssh_gssapi_import_name(*ctx, host);
+       if (!GSS_ERROR(major)) {
+               major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
+                   NULL);
+               gss_release_buffer(&minor, &token);
+               if ((*ctx)->context != GSS_C_NO_CONTEXT)
+                       gss_delete_sec_context(&minor, &(*ctx)->context,
+                           GSS_C_NO_BUFFER);
+       }
+
+       if (GSS_ERROR(major)) 
+               ssh_gssapi_delete_ctx(ctx);
+
+       return (!GSS_ERROR(major));
+}
+
+#endif /* GSSAPI */
diff --git a/.pc/gssapi.patch/gss-serv-krb5.c b/.pc/gssapi.patch/gss-serv-krb5.c
new file mode 100644 (file)
index 0000000..5a625ac
--- /dev/null
@@ -0,0 +1,199 @@
+/* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#ifdef GSSAPI
+#ifdef KRB5
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "log.h"
+#include "servconf.h"
+
+#include "buffer.h"
+#include "ssh-gss.h"
+
+extern ServerOptions options;
+
+#ifdef HEIMDAL
+# include <krb5.h>
+#else
+# ifdef HAVE_GSSAPI_KRB5_H
+#  include <gssapi_krb5.h>
+# elif HAVE_GSSAPI_GSSAPI_KRB5_H
+#  include <gssapi/gssapi_krb5.h>
+# endif
+#endif
+
+static krb5_context krb_context = NULL;
+
+/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
+
+static int
+ssh_gssapi_krb5_init(void)
+{
+       krb5_error_code problem;
+
+       if (krb_context != NULL)
+               return 1;
+
+       problem = krb5_init_context(&krb_context);
+       if (problem) {
+               logit("Cannot initialize krb5 context");
+               return 0;
+       }
+
+       return 1;
+}
+
+/* Check if this user is OK to login. This only works with krb5 - other
+ * GSSAPI mechanisms will need their own.
+ * Returns true if the user is OK to log in, otherwise returns 0
+ */
+
+static int
+ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
+{
+       krb5_principal princ;
+       int retval;
+
+       if (ssh_gssapi_krb5_init() == 0)
+               return 0;
+
+       if ((retval = krb5_parse_name(krb_context, client->exportedname.value,
+           &princ))) {
+               logit("krb5_parse_name(): %.100s",
+                   krb5_get_err_text(krb_context, retval));
+               return 0;
+       }
+       if (krb5_kuserok(krb_context, princ, name)) {
+               retval = 1;
+               logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
+                   name, (char *)client->displayname.value);
+       } else
+               retval = 0;
+
+       krb5_free_principal(krb_context, princ);
+       return retval;
+}
+
+
+/* This writes out any forwarded credentials from the structure populated
+ * during userauth. Called after we have setuid to the user */
+
+static void
+ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
+{
+       krb5_ccache ccache;
+       krb5_error_code problem;
+       krb5_principal princ;
+       OM_uint32 maj_status, min_status;
+       int len;
+
+       if (client->creds == NULL) {
+               debug("No credentials stored");
+               return;
+       }
+
+       if (ssh_gssapi_krb5_init() == 0)
+               return;
+
+#ifdef HEIMDAL
+       if ((problem = krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))) {
+               logit("krb5_cc_gen_new(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               return;
+       }
+#else
+       if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) {
+               logit("ssh_krb5_cc_gen(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               return;
+       }
+#endif /* #ifdef HEIMDAL */
+
+       if ((problem = krb5_parse_name(krb_context,
+           client->exportedname.value, &princ))) {
+               logit("krb5_parse_name(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_cc_destroy(krb_context, ccache);
+               return;
+       }
+
+       if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
+               logit("krb5_cc_initialize(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_free_principal(krb_context, princ);
+               krb5_cc_destroy(krb_context, ccache);
+               return;
+       }
+
+       krb5_free_principal(krb_context, princ);
+
+       if ((maj_status = gss_krb5_copy_ccache(&min_status,
+           client->creds, ccache))) {
+               logit("gss_krb5_copy_ccache() failed");
+               krb5_cc_destroy(krb_context, ccache);
+               return;
+       }
+
+       client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
+       client->store.envvar = "KRB5CCNAME";
+       len = strlen(client->store.filename) + 6;
+       client->store.envval = xmalloc(len);
+       snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               do_pam_putenv(client->store.envvar, client->store.envval);
+#endif
+
+       krb5_cc_close(krb_context, ccache);
+
+       return;
+}
+
+ssh_gssapi_mech gssapi_kerberos_mech = {
+       "toWM5Slw5Ew8Mqkay+al2g==",
+       "Kerberos",
+       {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
+       NULL,
+       &ssh_gssapi_krb5_userok,
+       NULL,
+       &ssh_gssapi_krb5_storecreds
+};
+
+#endif /* KRB5 */
+
+#endif /* GSSAPI */
diff --git a/.pc/gssapi.patch/gss-serv.c b/.pc/gssapi.patch/gss-serv.c
new file mode 100644 (file)
index 0000000..c719c13
--- /dev/null
@@ -0,0 +1,367 @@
+/* $OpenBSD: gss-serv.c,v 1.23 2011/08/01 19:18:15 markus Exp $ */
+
+/*
+ * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#ifdef GSSAPI
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "buffer.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "log.h"
+#include "channels.h"
+#include "session.h"
+#include "misc.h"
+
+#include "ssh-gss.h"
+
+static ssh_gssapi_client gssapi_client =
+    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
+    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
+
+ssh_gssapi_mech gssapi_null_mech =
+    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
+
+#ifdef KRB5
+extern ssh_gssapi_mech gssapi_kerberos_mech;
+#endif
+
+ssh_gssapi_mech* supported_mechs[]= {
+#ifdef KRB5
+       &gssapi_kerberos_mech,
+#endif
+       &gssapi_null_mech,
+};
+
+
+/*
+ * Acquire credentials for a server running on the current host.
+ * Requires that the context structure contains a valid OID
+ */
+
+/* Returns a GSSAPI error code */
+/* Privileged (called from ssh_gssapi_server_ctx) */
+static OM_uint32
+ssh_gssapi_acquire_cred(Gssctxt *ctx)
+{
+       OM_uint32 status;
+       char lname[MAXHOSTNAMELEN];
+       gss_OID_set oidset;
+
+       gss_create_empty_oid_set(&status, &oidset);
+       gss_add_oid_set_member(&status, ctx->oid, &oidset);
+
+       if (gethostname(lname, MAXHOSTNAMELEN)) {
+               gss_release_oid_set(&status, &oidset);
+               return (-1);
+       }
+
+       if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
+               gss_release_oid_set(&status, &oidset);
+               return (ctx->major);
+       }
+
+       if ((ctx->major = gss_acquire_cred(&ctx->minor,
+           ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL)))
+               ssh_gssapi_error(ctx);
+
+       gss_release_oid_set(&status, &oidset);
+       return (ctx->major);
+}
+
+/* Privileged */
+OM_uint32
+ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
+{
+       if (*ctx)
+               ssh_gssapi_delete_ctx(ctx);
+       ssh_gssapi_build_ctx(ctx);
+       ssh_gssapi_set_oid(*ctx, oid);
+       return (ssh_gssapi_acquire_cred(*ctx));
+}
+
+/* Unprivileged */
+void
+ssh_gssapi_supported_oids(gss_OID_set *oidset)
+{
+       int i = 0;
+       OM_uint32 min_status;
+       int present;
+       gss_OID_set supported;
+
+       gss_create_empty_oid_set(&min_status, oidset);
+       gss_indicate_mechs(&min_status, &supported);
+
+       while (supported_mechs[i]->name != NULL) {
+               if (GSS_ERROR(gss_test_oid_set_member(&min_status,
+                   &supported_mechs[i]->oid, supported, &present)))
+                       present = 0;
+               if (present)
+                       gss_add_oid_set_member(&min_status,
+                           &supported_mechs[i]->oid, oidset);
+               i++;
+       }
+
+       gss_release_oid_set(&min_status, &supported);
+}
+
+
+/* Wrapper around accept_sec_context
+ * Requires that the context contains:
+ *    oid
+ *    credentials      (from ssh_gssapi_acquire_cred)
+ */
+/* Privileged */
+OM_uint32
+ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *recv_tok,
+    gss_buffer_desc *send_tok, OM_uint32 *flags)
+{
+       OM_uint32 status;
+       gss_OID mech;
+
+       ctx->major = gss_accept_sec_context(&ctx->minor,
+           &ctx->context, ctx->creds, recv_tok,
+           GSS_C_NO_CHANNEL_BINDINGS, &ctx->client, &mech,
+           send_tok, flags, NULL, &ctx->client_creds);
+
+       if (GSS_ERROR(ctx->major))
+               ssh_gssapi_error(ctx);
+
+       if (ctx->client_creds)
+               debug("Received some client credentials");
+       else
+               debug("Got no client credentials");
+
+       status = ctx->major;
+
+       /* Now, if we're complete and we have the right flags, then
+        * we flag the user as also having been authenticated
+        */
+
+       if (((flags == NULL) || ((*flags & GSS_C_MUTUAL_FLAG) &&
+           (*flags & GSS_C_INTEG_FLAG))) && (ctx->major == GSS_S_COMPLETE)) {
+               if (ssh_gssapi_getclient(ctx, &gssapi_client))
+                       fatal("Couldn't convert client name");
+       }
+
+       return (status);
+}
+
+/*
+ * This parses an exported name, extracting the mechanism specific portion
+ * to use for ACL checking. It verifies that the name belongs the mechanism
+ * originally selected.
+ */
+static OM_uint32
+ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name)
+{
+       u_char *tok;
+       OM_uint32 offset;
+       OM_uint32 oidl;
+
+       tok = ename->value;
+
+       /*
+        * Check that ename is long enough for all of the fixed length
+        * header, and that the initial ID bytes are correct
+        */
+
+       if (ename->length < 6 || memcmp(tok, "\x04\x01", 2) != 0)
+               return GSS_S_FAILURE;
+
+       /*
+        * Extract the OID, and check it. Here GSSAPI breaks with tradition
+        * and does use the OID type and length bytes. To confuse things
+        * there are two lengths - the first including these, and the
+        * second without.
+        */
+
+       oidl = get_u16(tok+2); /* length including next two bytes */
+       oidl = oidl-2; /* turn it into the _real_ length of the variable OID */
+
+       /*
+        * Check the BER encoding for correct type and length, that the
+        * string is long enough and that the OID matches that in our context
+        */
+       if (tok[4] != 0x06 || tok[5] != oidl ||
+           ename->length < oidl+6 ||
+           !ssh_gssapi_check_oid(ctx, tok+6, oidl))
+               return GSS_S_FAILURE;
+
+       offset = oidl+6;
+
+       if (ename->length < offset+4)
+               return GSS_S_FAILURE;
+
+       name->length = get_u32(tok+offset);
+       offset += 4;
+
+       if (UINT_MAX - offset < name->length)
+               return GSS_S_FAILURE;
+       if (ename->length < offset+name->length)
+               return GSS_S_FAILURE;
+
+       name->value = xmalloc(name->length+1);
+       memcpy(name->value, tok+offset, name->length);
+       ((char *)name->value)[name->length] = 0;
+
+       return GSS_S_COMPLETE;
+}
+
+/* Extract the client details from a given context. This can only reliably
+ * be called once for a context */
+
+/* Privileged (called from accept_secure_ctx) */
+OM_uint32
+ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
+{
+       int i = 0;
+
+       gss_buffer_desc ename;
+
+       client->mech = NULL;
+
+       while (supported_mechs[i]->name != NULL) {
+               if (supported_mechs[i]->oid.length == ctx->oid->length &&
+                   (memcmp(supported_mechs[i]->oid.elements,
+                   ctx->oid->elements, ctx->oid->length) == 0))
+                       client->mech = supported_mechs[i];
+               i++;
+       }
+
+       if (client->mech == NULL)
+               return GSS_S_FAILURE;
+
+       if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
+           &client->displayname, NULL))) {
+               ssh_gssapi_error(ctx);
+               return (ctx->major);
+       }
+
+       if ((ctx->major = gss_export_name(&ctx->minor, ctx->client,
+           &ename))) {
+               ssh_gssapi_error(ctx);
+               return (ctx->major);
+       }
+
+       if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename,
+           &client->exportedname))) {
+               return (ctx->major);
+       }
+
+       /* We can't copy this structure, so we just move the pointer to it */
+       client->creds = ctx->client_creds;
+       ctx->client_creds = GSS_C_NO_CREDENTIAL;
+       return (ctx->major);
+}
+
+/* As user - called on fatal/exit */
+void
+ssh_gssapi_cleanup_creds(void)
+{
+       if (gssapi_client.store.filename != NULL) {
+               /* Unlink probably isn't sufficient */
+               debug("removing gssapi cred file\"%s\"",
+                   gssapi_client.store.filename);
+               unlink(gssapi_client.store.filename);
+       }
+}
+
+/* As user */
+void
+ssh_gssapi_storecreds(void)
+{
+       if (gssapi_client.mech && gssapi_client.mech->storecreds) {
+               (*gssapi_client.mech->storecreds)(&gssapi_client);
+       } else
+               debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
+}
+
+/* This allows GSSAPI methods to do things to the childs environment based
+ * on the passed authentication process and credentials.
+ */
+/* As user */
+void
+ssh_gssapi_do_child(char ***envp, u_int *envsizep)
+{
+
+       if (gssapi_client.store.envvar != NULL &&
+           gssapi_client.store.envval != NULL) {
+               debug("Setting %s to %s", gssapi_client.store.envvar,
+                   gssapi_client.store.envval);
+               child_set_env(envp, envsizep, gssapi_client.store.envvar,
+                   gssapi_client.store.envval);
+       }
+}
+
+/* Privileged */
+int
+ssh_gssapi_userok(char *user)
+{
+       OM_uint32 lmin;
+
+       if (gssapi_client.exportedname.length == 0 ||
+           gssapi_client.exportedname.value == NULL) {
+               debug("No suitable client data");
+               return 0;
+       }
+       if (gssapi_client.mech && gssapi_client.mech->userok)
+               if ((*gssapi_client.mech->userok)(&gssapi_client, user))
+                       return 1;
+               else {
+                       /* Destroy delegated credentials if userok fails */
+                       gss_release_buffer(&lmin, &gssapi_client.displayname);
+                       gss_release_buffer(&lmin, &gssapi_client.exportedname);
+                       gss_release_cred(&lmin, &gssapi_client.creds);
+                       memset(&gssapi_client, 0, sizeof(ssh_gssapi_client));
+                       return 0;
+               }
+       else
+               debug("ssh_gssapi_userok: Unknown GSSAPI mechanism");
+       return (0);
+}
+
+/* Privileged */
+OM_uint32
+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+       ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+           gssbuf, gssmic, NULL);
+
+       return (ctx->major);
+}
+
+#endif
diff --git a/.pc/gssapi.patch/kex.c b/.pc/gssapi.patch/kex.c
new file mode 100644 (file)
index 0000000..c65e28f
--- /dev/null
@@ -0,0 +1,610 @@
+/* $OpenBSD: kex.c,v 1.86 2010/09/22 05:01:29 djm Exp $ */
+/*
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/param.h>
+
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/crypto.h>
+
+#include "xmalloc.h"
+#include "ssh2.h"
+#include "buffer.h"
+#include "packet.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "log.h"
+#include "mac.h"
+#include "match.h"
+#include "dispatch.h"
+#include "monitor.h"
+#include "roaming.h"
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+# if defined(HAVE_EVP_SHA256)
+# define evp_ssh_sha256 EVP_sha256
+# else
+extern const EVP_MD *evp_ssh_sha256(void);
+# endif
+#endif
+
+/* prototype */
+static void kex_kexinit_finish(Kex *);
+static void kex_choose_conf(Kex *);
+
+/* Validate KEX method name list */
+int
+kex_names_valid(const char *names)
+{
+       char *s, *cp, *p;
+
+       if (names == NULL || strcmp(names, "") == 0)
+               return 0;
+       s = cp = xstrdup(names);
+       for ((p = strsep(&cp, ",")); p && *p != '\0';
+           (p = strsep(&cp, ","))) {
+               if (strcmp(p, KEX_DHGEX_SHA256) != 0 &&
+                   strcmp(p, KEX_DHGEX_SHA1) != 0 &&
+                   strcmp(p, KEX_DH14) != 0 &&
+                   strcmp(p, KEX_DH1) != 0 &&
+                   (strncmp(p, KEX_ECDH_SHA2_STEM,
+                   sizeof(KEX_ECDH_SHA2_STEM) - 1) != 0 ||
+                   kex_ecdh_name_to_nid(p) == -1)) {
+                       error("Unsupported KEX algorithm \"%.100s\"", p);
+                       xfree(s);
+                       return 0;
+               }
+       }
+       debug3("kex names ok: [%s]", names);
+       xfree(s);
+       return 1;
+}
+
+/* put algorithm proposal into buffer */
+static void
+kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
+{
+       u_int i;
+
+       buffer_clear(b);
+       /*
+        * add a dummy cookie, the cookie will be overwritten by
+        * kex_send_kexinit(), each time a kexinit is set
+        */
+       for (i = 0; i < KEX_COOKIE_LEN; i++)
+               buffer_put_char(b, 0);
+       for (i = 0; i < PROPOSAL_MAX; i++)
+               buffer_put_cstring(b, proposal[i]);
+       buffer_put_char(b, 0);                  /* first_kex_packet_follows */
+       buffer_put_int(b, 0);                   /* uint32 reserved */
+}
+
+/* parse buffer and return algorithm proposal */
+static char **
+kex_buf2prop(Buffer *raw, int *first_kex_follows)
+{
+       Buffer b;
+       u_int i;
+       char **proposal;
+
+       proposal = xcalloc(PROPOSAL_MAX, sizeof(char *));
+
+       buffer_init(&b);
+       buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
+       /* skip cookie */
+       for (i = 0; i < KEX_COOKIE_LEN; i++)
+               buffer_get_char(&b);
+       /* extract kex init proposal strings */
+       for (i = 0; i < PROPOSAL_MAX; i++) {
+               proposal[i] = buffer_get_cstring(&b,NULL);
+               debug2("kex_parse_kexinit: %s", proposal[i]);
+       }
+       /* first kex follows / reserved */
+       i = buffer_get_char(&b);
+       if (first_kex_follows != NULL)
+               *first_kex_follows = i;
+       debug2("kex_parse_kexinit: first_kex_follows %d ", i);
+       i = buffer_get_int(&b);
+       debug2("kex_parse_kexinit: reserved %u ", i);
+       buffer_free(&b);
+       return proposal;
+}
+
+static void
+kex_prop_free(char **proposal)
+{
+       u_int i;
+
+       for (i = 0; i < PROPOSAL_MAX; i++)
+               xfree(proposal[i]);
+       xfree(proposal);
+}
+
+/* ARGSUSED */
+static void
+kex_protocol_error(int type, u_int32_t seq, void *ctxt)
+{
+       error("Hm, kex protocol error: type %d seq %u", type, seq);
+}
+
+static void
+kex_reset_dispatch(void)
+{
+       dispatch_range(SSH2_MSG_TRANSPORT_MIN,
+           SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
+       dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+}
+
+void
+kex_finish(Kex *kex)
+{
+       kex_reset_dispatch();
+
+       packet_start(SSH2_MSG_NEWKEYS);
+       packet_send();
+       /* packet_write_wait(); */
+       debug("SSH2_MSG_NEWKEYS sent");
+
+       debug("expecting SSH2_MSG_NEWKEYS");
+       packet_read_expect(SSH2_MSG_NEWKEYS);
+       packet_check_eom();
+       debug("SSH2_MSG_NEWKEYS received");
+
+       kex->done = 1;
+       buffer_clear(&kex->peer);
+       /* buffer_clear(&kex->my); */
+       kex->flags &= ~KEX_INIT_SENT;
+       xfree(kex->name);
+       kex->name = NULL;
+}
+
+void
+kex_send_kexinit(Kex *kex)
+{
+       u_int32_t rnd = 0;
+       u_char *cookie;
+       u_int i;
+
+       if (kex == NULL) {
+               error("kex_send_kexinit: no kex, cannot rekey");
+               return;
+       }
+       if (kex->flags & KEX_INIT_SENT) {
+               debug("KEX_INIT_SENT");
+               return;
+       }
+       kex->done = 0;
+
+       /* generate a random cookie */
+       if (buffer_len(&kex->my) < KEX_COOKIE_LEN)
+               fatal("kex_send_kexinit: kex proposal too short");
+       cookie = buffer_ptr(&kex->my);
+       for (i = 0; i < KEX_COOKIE_LEN; i++) {
+               if (i % 4 == 0)
+                       rnd = arc4random();
+               cookie[i] = rnd;
+               rnd >>= 8;
+       }
+       packet_start(SSH2_MSG_KEXINIT);
+       packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
+       packet_send();
+       debug("SSH2_MSG_KEXINIT sent");
+       kex->flags |= KEX_INIT_SENT;
+}
+
+/* ARGSUSED */
+void
+kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
+{
+       char *ptr;
+       u_int i, dlen;
+       Kex *kex = (Kex *)ctxt;
+
+       debug("SSH2_MSG_KEXINIT received");
+       if (kex == NULL)
+               fatal("kex_input_kexinit: no kex, cannot rekey");
+
+       ptr = packet_get_raw(&dlen);
+       buffer_append(&kex->peer, ptr, dlen);
+
+       /* discard packet */
+       for (i = 0; i < KEX_COOKIE_LEN; i++)
+               packet_get_char();
+       for (i = 0; i < PROPOSAL_MAX; i++)
+               xfree(packet_get_string(NULL));
+       (void) packet_get_char();
+       (void) packet_get_int();
+       packet_check_eom();
+
+       kex_kexinit_finish(kex);
+}
+
+Kex *
+kex_setup(char *proposal[PROPOSAL_MAX])
+{
+       Kex *kex;
+
+       kex = xcalloc(1, sizeof(*kex));
+       buffer_init(&kex->peer);
+       buffer_init(&kex->my);
+       kex_prop2buf(&kex->my, proposal);
+       kex->done = 0;
+
+       kex_send_kexinit(kex);                                  /* we start */
+       kex_reset_dispatch();
+
+       return kex;
+}
+
+static void
+kex_kexinit_finish(Kex *kex)
+{
+       if (!(kex->flags & KEX_INIT_SENT))
+               kex_send_kexinit(kex);
+
+       kex_choose_conf(kex);
+
+       if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
+           kex->kex[kex->kex_type] != NULL) {
+               (kex->kex[kex->kex_type])(kex);
+       } else {
+               fatal("Unsupported key exchange %d", kex->kex_type);
+       }
+}
+
+static void
+choose_enc(Enc *enc, char *client, char *server)
+{
+       char *name = match_list(client, server, NULL);
+       if (name == NULL)
+               fatal("no matching cipher found: client %s server %s",
+                   client, server);
+       if ((enc->cipher = cipher_by_name(name)) == NULL)
+               fatal("matching cipher is not supported: %s", name);
+       enc->name = name;
+       enc->enabled = 0;
+       enc->iv = NULL;
+       enc->key = NULL;
+       enc->key_len = cipher_keylen(enc->cipher);
+       enc->block_size = cipher_blocksize(enc->cipher);
+}
+
+static void
+choose_mac(Mac *mac, char *client, char *server)
+{
+       char *name = match_list(client, server, NULL);
+       if (name == NULL)
+               fatal("no matching mac found: client %s server %s",
+                   client, server);
+       if (mac_setup(mac, name) < 0)
+               fatal("unsupported mac %s", name);
+       /* truncate the key */
+       if (datafellows & SSH_BUG_HMAC)
+               mac->key_len = 16;
+       mac->name = name;
+       mac->key = NULL;
+       mac->enabled = 0;
+}
+
+static void
+choose_comp(Comp *comp, char *client, char *server)
+{
+       char *name = match_list(client, server, NULL);
+       if (name == NULL)
+               fatal("no matching comp found: client %s server %s", client, server);
+       if (strcmp(name, "zlib@openssh.com") == 0) {
+               comp->type = COMP_DELAYED;
+       } else if (strcmp(name, "zlib") == 0) {
+               comp->type = COMP_ZLIB;
+       } else if (strcmp(name, "none") == 0) {
+               comp->type = COMP_NONE;
+       } else {
+               fatal("unsupported comp %s", name);
+       }
+       comp->name = name;
+}
+
+static void
+choose_kex(Kex *k, char *client, char *server)
+{
+       k->name = match_list(client, server, NULL);
+       if (k->name == NULL)
+               fatal("Unable to negotiate a key exchange method");
+       if (strcmp(k->name, KEX_DH1) == 0) {
+               k->kex_type = KEX_DH_GRP1_SHA1;
+               k->evp_md = EVP_sha1();
+       } else if (strcmp(k->name, KEX_DH14) == 0) {
+               k->kex_type = KEX_DH_GRP14_SHA1;
+               k->evp_md = EVP_sha1();
+       } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) {
+               k->kex_type = KEX_DH_GEX_SHA1;
+               k->evp_md = EVP_sha1();
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+       } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
+               k->kex_type = KEX_DH_GEX_SHA256;
+               k->evp_md = evp_ssh_sha256();
+       } else if (strncmp(k->name, KEX_ECDH_SHA2_STEM,
+           sizeof(KEX_ECDH_SHA2_STEM) - 1) == 0) {
+               k->kex_type = KEX_ECDH_SHA2;
+               k->evp_md = kex_ecdh_name_to_evpmd(k->name);
+#endif
+       } else
+               fatal("bad kex alg %s", k->name);
+}
+
+static void
+choose_hostkeyalg(Kex *k, char *client, char *server)
+{
+       char *hostkeyalg = match_list(client, server, NULL);
+       if (hostkeyalg == NULL)
+               fatal("no hostkey alg");
+       k->hostkey_type = key_type_from_name(hostkeyalg);
+       if (k->hostkey_type == KEY_UNSPEC)
+               fatal("bad hostkey alg '%s'", hostkeyalg);
+       xfree(hostkeyalg);
+}
+
+static int
+proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
+{
+       static int check[] = {
+               PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
+       };
+       int *idx;
+       char *p;
+
+       for (idx = &check[0]; *idx != -1; idx++) {
+               if ((p = strchr(my[*idx], ',')) != NULL)
+                       *p = '\0';
+               if ((p = strchr(peer[*idx], ',')) != NULL)
+                       *p = '\0';
+               if (strcmp(my[*idx], peer[*idx]) != 0) {
+                       debug2("proposal mismatch: my %s peer %s",
+                           my[*idx], peer[*idx]);
+                       return (0);
+               }
+       }
+       debug2("proposals match");
+       return (1);
+}
+
+static void
+kex_choose_conf(Kex *kex)
+{
+       Newkeys *newkeys;
+       char **my, **peer;
+       char **cprop, **sprop;
+       int nenc, nmac, ncomp;
+       u_int mode, ctos, need;
+       int first_kex_follows, type;
+
+       my   = kex_buf2prop(&kex->my, NULL);
+       peer = kex_buf2prop(&kex->peer, &first_kex_follows);
+
+       if (kex->server) {
+               cprop=peer;
+               sprop=my;
+       } else {
+               cprop=my;
+               sprop=peer;
+       }
+
+       /* Check whether server offers roaming */
+       if (!kex->server) {
+               char *roaming;
+               roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL);
+               if (roaming) {
+                       kex->roaming = 1;
+                       xfree(roaming);
+               }
+       }
+
+       /* Algorithm Negotiation */
+       for (mode = 0; mode < MODE_MAX; mode++) {
+               newkeys = xcalloc(1, sizeof(*newkeys));
+               kex->newkeys[mode] = newkeys;
+               ctos = (!kex->server && mode == MODE_OUT) ||
+                   (kex->server && mode == MODE_IN);
+               nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
+               nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
+               ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
+               choose_enc (&newkeys->enc,  cprop[nenc],  sprop[nenc]);
+               choose_mac (&newkeys->mac,  cprop[nmac],  sprop[nmac]);
+               choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
+               debug("kex: %s %s %s %s",
+                   ctos ? "client->server" : "server->client",
+                   newkeys->enc.name,
+                   newkeys->mac.name,
+                   newkeys->comp.name);
+       }
+       choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
+       choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
+           sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
+       need = 0;
+       for (mode = 0; mode < MODE_MAX; mode++) {
+               newkeys = kex->newkeys[mode];
+               if (need < newkeys->enc.key_len)
+                       need = newkeys->enc.key_len;
+               if (need < newkeys->enc.block_size)
+                       need = newkeys->enc.block_size;
+               if (need < newkeys->mac.key_len)
+                       need = newkeys->mac.key_len;
+       }
+       /* XXX need runden? */
+       kex->we_need = need;
+
+       /* ignore the next message if the proposals do not match */
+       if (first_kex_follows && !proposals_match(my, peer) &&
+           !(datafellows & SSH_BUG_FIRSTKEX)) {
+               type = packet_read();
+               debug2("skipping next packet (type %u)", type);
+       }
+
+       kex_prop_free(my);
+       kex_prop_free(peer);
+}
+
+static u_char *
+derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen,
+    BIGNUM *shared_secret)
+{
+       Buffer b;
+       EVP_MD_CTX md;
+       char c = id;
+       u_int have;
+       int mdsz;
+       u_char *digest;
+
+       if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0)
+               fatal("bad kex md size %d", mdsz);
+       digest = xmalloc(roundup(need, mdsz));
+
+       buffer_init(&b);
+       buffer_put_bignum2(&b, shared_secret);
+
+       /* K1 = HASH(K || H || "A" || session_id) */
+       EVP_DigestInit(&md, kex->evp_md);
+       if (!(datafellows & SSH_BUG_DERIVEKEY))
+               EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
+       EVP_DigestUpdate(&md, hash, hashlen);
+       EVP_DigestUpdate(&md, &c, 1);
+       EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len);
+       EVP_DigestFinal(&md, digest, NULL);
+
+       /*
+        * expand key:
+        * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
+        * Key = K1 || K2 || ... || Kn
+        */
+       for (have = mdsz; need > have; have += mdsz) {
+               EVP_DigestInit(&md, kex->evp_md);
+               if (!(datafellows & SSH_BUG_DERIVEKEY))
+                       EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
+               EVP_DigestUpdate(&md, hash, hashlen);
+               EVP_DigestUpdate(&md, digest, have);
+               EVP_DigestFinal(&md, digest + have, NULL);
+       }
+       buffer_free(&b);
+#ifdef DEBUG_KEX
+       fprintf(stderr, "key '%c'== ", c);
+       dump_digest("key", digest, need);
+#endif
+       return digest;
+}
+
+Newkeys *current_keys[MODE_MAX];
+
+#define NKEYS  6
+void
+kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret)
+{
+       u_char *keys[NKEYS];
+       u_int i, mode, ctos;
+
+       for (i = 0; i < NKEYS; i++) {
+               keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen,
+                   shared_secret);
+       }
+
+       debug2("kex_derive_keys");
+       for (mode = 0; mode < MODE_MAX; mode++) {
+               current_keys[mode] = kex->newkeys[mode];
+               kex->newkeys[mode] = NULL;
+               ctos = (!kex->server && mode == MODE_OUT) ||
+                   (kex->server && mode == MODE_IN);
+               current_keys[mode]->enc.iv  = keys[ctos ? 0 : 1];
+               current_keys[mode]->enc.key = keys[ctos ? 2 : 3];
+               current_keys[mode]->mac.key = keys[ctos ? 4 : 5];
+       }
+}
+
+Newkeys *
+kex_get_newkeys(int mode)
+{
+       Newkeys *ret;
+
+       ret = current_keys[mode];
+       current_keys[mode] = NULL;
+       return ret;
+}
+
+void
+derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
+    u_int8_t cookie[8], u_int8_t id[16])
+{
+       const EVP_MD *evp_md = EVP_md5();
+       EVP_MD_CTX md;
+       u_int8_t nbuf[2048], obuf[EVP_MAX_MD_SIZE];
+       int len;
+
+       EVP_DigestInit(&md, evp_md);
+
+       len = BN_num_bytes(host_modulus);
+       if (len < (512 / 8) || (u_int)len > sizeof(nbuf))
+               fatal("%s: bad host modulus (len %d)", __func__, len);
+       BN_bn2bin(host_modulus, nbuf);
+       EVP_DigestUpdate(&md, nbuf, len);
+
+       len = BN_num_bytes(server_modulus);
+       if (len < (512 / 8) || (u_int)len > sizeof(nbuf))
+               fatal("%s: bad server modulus (len %d)", __func__, len);
+       BN_bn2bin(server_modulus, nbuf);
+       EVP_DigestUpdate(&md, nbuf, len);
+
+       EVP_DigestUpdate(&md, cookie, 8);
+
+       EVP_DigestFinal(&md, obuf, NULL);
+       memcpy(id, obuf, 16);
+
+       memset(nbuf, 0, sizeof(nbuf));
+       memset(obuf, 0, sizeof(obuf));
+       memset(&md, 0, sizeof(md));
+}
+
+#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
+void
+dump_digest(char *msg, u_char *digest, int len)
+{
+       int i;
+
+       fprintf(stderr, "%s\n", msg);
+       for (i = 0; i < len; i++) {
+               fprintf(stderr, "%02x", digest[i]);
+               if (i%32 == 31)
+                       fprintf(stderr, "\n");
+               else if (i%8 == 7)
+                       fprintf(stderr, " ");
+       }
+       fprintf(stderr, "\n");
+}
+#endif
diff --git a/.pc/gssapi.patch/kex.h b/.pc/gssapi.patch/kex.h
new file mode 100644 (file)
index 0000000..7373d3c
--- /dev/null
@@ -0,0 +1,185 @@
+/* $OpenBSD: kex.h,v 1.52 2010/09/22 05:01:29 djm Exp $ */
+
+/*
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef KEX_H
+#define KEX_H
+
+#include <signal.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ec.h>
+#endif
+
+#define KEX_COOKIE_LEN 16
+
+#define        KEX_DH1                 "diffie-hellman-group1-sha1"
+#define        KEX_DH14                "diffie-hellman-group14-sha1"
+#define        KEX_DHGEX_SHA1          "diffie-hellman-group-exchange-sha1"
+#define        KEX_DHGEX_SHA256        "diffie-hellman-group-exchange-sha256"
+#define        KEX_RESUME              "resume@appgate.com"
+/* The following represents the family of ECDH methods */
+#define        KEX_ECDH_SHA2_STEM      "ecdh-sha2-"
+
+#define COMP_NONE      0
+#define COMP_ZLIB      1
+#define COMP_DELAYED   2
+
+enum kex_init_proposals {
+       PROPOSAL_KEX_ALGS,
+       PROPOSAL_SERVER_HOST_KEY_ALGS,
+       PROPOSAL_ENC_ALGS_CTOS,
+       PROPOSAL_ENC_ALGS_STOC,
+       PROPOSAL_MAC_ALGS_CTOS,
+       PROPOSAL_MAC_ALGS_STOC,
+       PROPOSAL_COMP_ALGS_CTOS,
+       PROPOSAL_COMP_ALGS_STOC,
+       PROPOSAL_LANG_CTOS,
+       PROPOSAL_LANG_STOC,
+       PROPOSAL_MAX
+};
+
+enum kex_modes {
+       MODE_IN,
+       MODE_OUT,
+       MODE_MAX
+};
+
+enum kex_exchange {
+       KEX_DH_GRP1_SHA1,
+       KEX_DH_GRP14_SHA1,
+       KEX_DH_GEX_SHA1,
+       KEX_DH_GEX_SHA256,
+       KEX_ECDH_SHA2,
+       KEX_MAX
+};
+
+#define KEX_INIT_SENT  0x0001
+
+typedef struct Kex Kex;
+typedef struct Mac Mac;
+typedef struct Comp Comp;
+typedef struct Enc Enc;
+typedef struct Newkeys Newkeys;
+
+struct Enc {
+       char    *name;
+       Cipher  *cipher;
+       int     enabled;
+       u_int   key_len;
+       u_int   block_size;
+       u_char  *key;
+       u_char  *iv;
+};
+struct Mac {
+       char    *name;
+       int     enabled;
+       u_int   mac_len;
+       u_char  *key;
+       u_int   key_len;
+       int     type;
+       const EVP_MD    *evp_md;
+       HMAC_CTX        evp_ctx;
+       struct umac_ctx *umac_ctx;
+};
+struct Comp {
+       int     type;
+       int     enabled;
+       char    *name;
+};
+struct Newkeys {
+       Enc     enc;
+       Mac     mac;
+       Comp    comp;
+};
+struct Kex {
+       u_char  *session_id;
+       u_int   session_id_len;
+       Newkeys *newkeys[MODE_MAX];
+       u_int   we_need;
+       int     server;
+       char    *name;
+       int     hostkey_type;
+       int     kex_type;
+       int     roaming;
+       Buffer  my;
+       Buffer  peer;
+       sig_atomic_t done;
+       int     flags;
+       const EVP_MD *evp_md;
+       char    *client_version_string;
+       char    *server_version_string;
+       int     (*verify_host_key)(Key *);
+       Key     *(*load_host_public_key)(int);
+       Key     *(*load_host_private_key)(int);
+       int     (*host_key_index)(Key *);
+       void    (*kex[KEX_MAX])(Kex *);
+};
+
+int     kex_names_valid(const char *);
+
+Kex    *kex_setup(char *[PROPOSAL_MAX]);
+void    kex_finish(Kex *);
+
+void    kex_send_kexinit(Kex *);
+void    kex_input_kexinit(int, u_int32_t, void *);
+void    kex_derive_keys(Kex *, u_char *, u_int, BIGNUM *);
+
+Newkeys *kex_get_newkeys(int);
+
+void    kexdh_client(Kex *);
+void    kexdh_server(Kex *);
+void    kexgex_client(Kex *);
+void    kexgex_server(Kex *);
+void    kexecdh_client(Kex *);
+void    kexecdh_server(Kex *);
+
+void
+kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
+    BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
+void
+kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *,
+    int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *,
+    BIGNUM *, BIGNUM *, u_char **, u_int *);
+#ifdef OPENSSL_HAS_ECC
+void
+kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int,
+    char *, int, u_char *, int, const EC_POINT *, const EC_POINT *,
+    const BIGNUM *, u_char **, u_int *);
+int    kex_ecdh_name_to_nid(const char *);
+const EVP_MD *kex_ecdh_name_to_evpmd(const char *);
+#else
+# define kex_ecdh_name_to_nid(x) (-1)
+# define kex_ecdh_name_to_evpmd(x) (NULL)
+#endif
+
+void
+derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
+
+#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
+void   dump_digest(char *, u_char *, int);
+#endif
+
+#endif
diff --git a/.pc/gssapi.patch/kexgssc.c b/.pc/gssapi.patch/kexgssc.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/.pc/gssapi.patch/kexgsss.c b/.pc/gssapi.patch/kexgsss.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/.pc/gssapi.patch/key.c b/.pc/gssapi.patch/key.c
new file mode 100644 (file)
index 0000000..498cf5a
--- /dev/null
@@ -0,0 +1,2273 @@
+/* $OpenBSD: key.c,v 1.97 2011/05/17 07:13:31 djm Exp $ */
+/*
+ * read_bignum():
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ *
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <openssl/evp.h>
+#include <openbsd-compat/openssl-compat.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "rsa.h"
+#include "uuencode.h"
+#include "buffer.h"
+#include "log.h"
+#include "misc.h"
+#include "ssh2.h"
+
+static struct KeyCert *
+cert_new(void)
+{
+       struct KeyCert *cert;
+
+       cert = xcalloc(1, sizeof(*cert));
+       buffer_init(&cert->certblob);
+       buffer_init(&cert->critical);
+       buffer_init(&cert->extensions);
+       cert->key_id = NULL;
+       cert->principals = NULL;
+       cert->signature_key = NULL;
+       return cert;
+}
+
+Key *
+key_new(int type)
+{
+       Key *k;
+       RSA *rsa;
+       DSA *dsa;
+       k = xcalloc(1, sizeof(*k));
+       k->type = type;
+       k->ecdsa = NULL;
+       k->ecdsa_nid = -1;
+       k->dsa = NULL;
+       k->rsa = NULL;
+       k->cert = NULL;
+       switch (k->type) {
+       case KEY_RSA1:
+       case KEY_RSA:
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               if ((rsa = RSA_new()) == NULL)
+                       fatal("key_new: RSA_new failed");
+               if ((rsa->n = BN_new()) == NULL)
+                       fatal("key_new: BN_new failed");
+               if ((rsa->e = BN_new()) == NULL)
+                       fatal("key_new: BN_new failed");
+               k->rsa = rsa;
+               break;
+       case KEY_DSA:
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               if ((dsa = DSA_new()) == NULL)
+                       fatal("key_new: DSA_new failed");
+               if ((dsa->p = BN_new()) == NULL)
+                       fatal("key_new: BN_new failed");
+               if ((dsa->q = BN_new()) == NULL)
+                       fatal("key_new: BN_new failed");
+               if ((dsa->g = BN_new()) == NULL)
+                       fatal("key_new: BN_new failed");
+               if ((dsa->pub_key = BN_new()) == NULL)
+                       fatal("key_new: BN_new failed");
+               k->dsa = dsa;
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+       case KEY_ECDSA_CERT:
+               /* Cannot do anything until we know the group */
+               break;
+#endif
+       case KEY_UNSPEC:
+               break;
+       default:
+               fatal("key_new: bad key type %d", k->type);
+               break;
+       }
+
+       if (key_is_cert(k))
+               k->cert = cert_new();
+
+       return k;
+}
+
+void
+key_add_private(Key *k)
+{
+       switch (k->type) {
+       case KEY_RSA1:
+       case KEY_RSA:
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               if ((k->rsa->d = BN_new()) == NULL)
+                       fatal("key_new_private: BN_new failed");
+               if ((k->rsa->iqmp = BN_new()) == NULL)
+                       fatal("key_new_private: BN_new failed");
+               if ((k->rsa->q = BN_new()) == NULL)
+                       fatal("key_new_private: BN_new failed");
+               if ((k->rsa->p = BN_new()) == NULL)
+                       fatal("key_new_private: BN_new failed");
+               if ((k->rsa->dmq1 = BN_new()) == NULL)
+                       fatal("key_new_private: BN_new failed");
+               if ((k->rsa->dmp1 = BN_new()) == NULL)
+                       fatal("key_new_private: BN_new failed");
+               break;
+       case KEY_DSA:
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               if ((k->dsa->priv_key = BN_new()) == NULL)
+                       fatal("key_new_private: BN_new failed");
+               break;
+       case KEY_ECDSA:
+       case KEY_ECDSA_CERT:
+               /* Cannot do anything until we know the group */
+               break;
+       case KEY_UNSPEC:
+               break;
+       default:
+               break;
+       }
+}
+
+Key *
+key_new_private(int type)
+{
+       Key *k = key_new(type);
+
+       key_add_private(k);
+       return k;
+}
+
+static void
+cert_free(struct KeyCert *cert)
+{
+       u_int i;
+
+       buffer_free(&cert->certblob);
+       buffer_free(&cert->critical);
+       buffer_free(&cert->extensions);
+       if (cert->key_id != NULL)
+               xfree(cert->key_id);
+       for (i = 0; i < cert->nprincipals; i++)
+               xfree(cert->principals[i]);
+       if (cert->principals != NULL)
+               xfree(cert->principals);
+       if (cert->signature_key != NULL)
+               key_free(cert->signature_key);
+}
+
+void
+key_free(Key *k)
+{
+       if (k == NULL)
+               fatal("key_free: key is NULL");
+       switch (k->type) {
+       case KEY_RSA1:
+       case KEY_RSA:
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               if (k->rsa != NULL)
+                       RSA_free(k->rsa);
+               k->rsa = NULL;
+               break;
+       case KEY_DSA:
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               if (k->dsa != NULL)
+                       DSA_free(k->dsa);
+               k->dsa = NULL;
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+       case KEY_ECDSA_CERT:
+               if (k->ecdsa != NULL)
+                       EC_KEY_free(k->ecdsa);
+               k->ecdsa = NULL;
+               break;
+#endif
+       case KEY_UNSPEC:
+               break;
+       default:
+               fatal("key_free: bad key type %d", k->type);
+               break;
+       }
+       if (key_is_cert(k)) {
+               if (k->cert != NULL)
+                       cert_free(k->cert);
+               k->cert = NULL;
+       }
+
+       xfree(k);
+}
+
+static int
+cert_compare(struct KeyCert *a, struct KeyCert *b)
+{
+       if (a == NULL && b == NULL)
+               return 1;
+       if (a == NULL || b == NULL)
+               return 0;
+       if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
+               return 0;
+       if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
+           buffer_len(&a->certblob)) != 0)
+               return 0;
+       return 1;
+}
+
+/*
+ * Compare public portions of key only, allowing comparisons between
+ * certificates and plain keys too.
+ */
+int
+key_equal_public(const Key *a, const Key *b)
+{
+#ifdef OPENSSL_HAS_ECC
+       BN_CTX *bnctx;
+#endif
+
+       if (a == NULL || b == NULL ||
+           key_type_plain(a->type) != key_type_plain(b->type))
+               return 0;
+
+       switch (a->type) {
+       case KEY_RSA1:
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+       case KEY_RSA:
+               return a->rsa != NULL && b->rsa != NULL &&
+                   BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
+                   BN_cmp(a->rsa->n, b->rsa->n) == 0;
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+       case KEY_DSA:
+               return a->dsa != NULL && b->dsa != NULL &&
+                   BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
+                   BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
+                   BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
+                   BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA_CERT:
+       case KEY_ECDSA:
+               if (a->ecdsa == NULL || b->ecdsa == NULL ||
+                   EC_KEY_get0_public_key(a->ecdsa) == NULL ||
+                   EC_KEY_get0_public_key(b->ecdsa) == NULL)
+                       return 0;
+               if ((bnctx = BN_CTX_new()) == NULL)
+                       fatal("%s: BN_CTX_new failed", __func__);
+               if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
+                   EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
+                   EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
+                   EC_KEY_get0_public_key(a->ecdsa),
+                   EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
+                       BN_CTX_free(bnctx);
+                       return 0;
+               }
+               BN_CTX_free(bnctx);
+               return 1;
+#endif /* OPENSSL_HAS_ECC */
+       default:
+               fatal("key_equal: bad key type %d", a->type);
+       }
+       /* NOTREACHED */
+}
+
+int
+key_equal(const Key *a, const Key *b)
+{
+       if (a == NULL || b == NULL || a->type != b->type)
+               return 0;
+       if (key_is_cert(a)) {
+               if (!cert_compare(a->cert, b->cert))
+                       return 0;
+       }
+       return key_equal_public(a, b);
+}
+
+u_char*
+key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
+{
+       const EVP_MD *md = NULL;
+       EVP_MD_CTX ctx;
+       u_char *blob = NULL;
+       u_char *retval = NULL;
+       u_int len = 0;
+       int nlen, elen, otype;
+
+       *dgst_raw_length = 0;
+
+       switch (dgst_type) {
+       case SSH_FP_MD5:
+               md = EVP_md5();
+               break;
+       case SSH_FP_SHA1:
+               md = EVP_sha1();
+               break;
+       default:
+               fatal("key_fingerprint_raw: bad digest type %d",
+                   dgst_type);
+       }
+       switch (k->type) {
+       case KEY_RSA1:
+               nlen = BN_num_bytes(k->rsa->n);
+               elen = BN_num_bytes(k->rsa->e);
+               len = nlen + elen;
+               blob = xmalloc(len);
+               BN_bn2bin(k->rsa->n, blob);
+               BN_bn2bin(k->rsa->e, blob + nlen);
+               break;
+       case KEY_DSA:
+       case KEY_ECDSA:
+       case KEY_RSA:
+               key_to_blob(k, &blob, &len);
+               break;
+       case KEY_DSA_CERT_V00:
+       case KEY_RSA_CERT_V00:
+       case KEY_DSA_CERT:
+       case KEY_ECDSA_CERT:
+       case KEY_RSA_CERT:
+               /* We want a fingerprint of the _key_ not of the cert */
+               otype = k->type;
+               k->type = key_type_plain(k->type);
+               key_to_blob(k, &blob, &len);
+               k->type = otype;
+               break;
+       case KEY_UNSPEC:
+               return retval;
+       default:
+               fatal("key_fingerprint_raw: bad key type %d", k->type);
+               break;
+       }
+       if (blob != NULL) {
+               retval = xmalloc(EVP_MAX_MD_SIZE);
+               EVP_DigestInit(&ctx, md);
+               EVP_DigestUpdate(&ctx, blob, len);
+               EVP_DigestFinal(&ctx, retval, dgst_raw_length);
+               memset(blob, 0, len);
+               xfree(blob);
+       } else {
+               fatal("key_fingerprint_raw: blob is null");
+       }
+       return retval;
+}
+
+static char *
+key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
+{
+       char *retval;
+       u_int i;
+
+       retval = xcalloc(1, dgst_raw_len * 3 + 1);
+       for (i = 0; i < dgst_raw_len; i++) {
+               char hex[4];
+               snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
+               strlcat(retval, hex, dgst_raw_len * 3 + 1);
+       }
+
+       /* Remove the trailing ':' character */
+       retval[(dgst_raw_len * 3) - 1] = '\0';
+       return retval;
+}
+
+static char *
+key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
+{
+       char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
+       char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
+           'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
+       u_int i, j = 0, rounds, seed = 1;
+       char *retval;
+
+       rounds = (dgst_raw_len / 2) + 1;
+       retval = xcalloc((rounds * 6), sizeof(char));
+       retval[j++] = 'x';
+       for (i = 0; i < rounds; i++) {
+               u_int idx0, idx1, idx2, idx3, idx4;
+               if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
+                       idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
+                           seed) % 6;
+                       idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
+                       idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
+                           (seed / 6)) % 6;
+                       retval[j++] = vowels[idx0];
+                       retval[j++] = consonants[idx1];
+                       retval[j++] = vowels[idx2];
+                       if ((i + 1) < rounds) {
+                               idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
+                               idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
+                               retval[j++] = consonants[idx3];
+                               retval[j++] = '-';
+                               retval[j++] = consonants[idx4];
+                               seed = ((seed * 5) +
+                                   ((((u_int)(dgst_raw[2 * i])) * 7) +
+                                   ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
+                       }
+               } else {
+                       idx0 = seed % 6;
+                       idx1 = 16;
+                       idx2 = seed / 6;
+                       retval[j++] = vowels[idx0];
+                       retval[j++] = consonants[idx1];
+                       retval[j++] = vowels[idx2];
+               }
+       }
+       retval[j++] = 'x';
+       retval[j++] = '\0';
+       return retval;
+}
+
+/*
+ * Draw an ASCII-Art representing the fingerprint so human brain can
+ * profit from its built-in pattern recognition ability.
+ * This technique is called "random art" and can be found in some
+ * scientific publications like this original paper:
+ *
+ * "Hash Visualization: a New Technique to improve Real-World Security",
+ * Perrig A. and Song D., 1999, International Workshop on Cryptographic
+ * Techniques and E-Commerce (CrypTEC '99)
+ * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
+ *
+ * The subject came up in a talk by Dan Kaminsky, too.
+ *
+ * If you see the picture is different, the key is different.
+ * If the picture looks the same, you still know nothing.
+ *
+ * The algorithm used here is a worm crawling over a discrete plane,
+ * leaving a trace (augmenting the field) everywhere it goes.
+ * Movement is taken from dgst_raw 2bit-wise.  Bumping into walls
+ * makes the respective movement vector be ignored for this turn.
+ * Graphs are not unambiguous, because circles in graphs can be
+ * walked in either direction.
+ */
+
+/*
+ * Field sizes for the random art.  Have to be odd, so the starting point
+ * can be in the exact middle of the picture, and FLDBASE should be >=8 .
+ * Else pictures would be too dense, and drawing the frame would
+ * fail, too, because the key type would not fit in anymore.
+ */
+#define        FLDBASE         8
+#define        FLDSIZE_Y       (FLDBASE + 1)
+#define        FLDSIZE_X       (FLDBASE * 2 + 1)
+static char *
+key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
+{
+       /*
+        * Chars to be used after each other every time the worm
+        * intersects with itself.  Matter of taste.
+        */
+       char    *augmentation_string = " .o+=*BOX@%&#/^SE";
+       char    *retval, *p;
+       u_char   field[FLDSIZE_X][FLDSIZE_Y];
+       u_int    i, b;
+       int      x, y;
+       size_t   len = strlen(augmentation_string) - 1;
+
+       retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
+
+       /* initialize field */
+       memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
+       x = FLDSIZE_X / 2;
+       y = FLDSIZE_Y / 2;
+
+       /* process raw key */
+       for (i = 0; i < dgst_raw_len; i++) {
+               int input;
+               /* each byte conveys four 2-bit move commands */
+               input = dgst_raw[i];
+               for (b = 0; b < 4; b++) {
+                       /* evaluate 2 bit, rest is shifted later */
+                       x += (input & 0x1) ? 1 : -1;
+                       y += (input & 0x2) ? 1 : -1;
+
+                       /* assure we are still in bounds */
+                       x = MAX(x, 0);
+                       y = MAX(y, 0);
+                       x = MIN(x, FLDSIZE_X - 1);
+                       y = MIN(y, FLDSIZE_Y - 1);
+
+                       /* augment the field */
+                       if (field[x][y] < len - 2)
+                               field[x][y]++;
+                       input = input >> 2;
+               }
+       }
+
+       /* mark starting point and end point*/
+       field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
+       field[x][y] = len;
+
+       /* fill in retval */
+       snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
+       p = strchr(retval, '\0');
+
+       /* output upper border */
+       for (i = p - retval - 1; i < FLDSIZE_X; i++)
+               *p++ = '-';
+       *p++ = '+';
+       *p++ = '\n';
+
+       /* output content */
+       for (y = 0; y < FLDSIZE_Y; y++) {
+               *p++ = '|';
+               for (x = 0; x < FLDSIZE_X; x++)
+                       *p++ = augmentation_string[MIN(field[x][y], len)];
+               *p++ = '|';
+               *p++ = '\n';
+       }
+
+       /* output lower border */
+       *p++ = '+';
+       for (i = 0; i < FLDSIZE_X; i++)
+               *p++ = '-';
+       *p++ = '+';
+
+       return retval;
+}
+
+char *
+key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
+{
+       char *retval = NULL;
+       u_char *dgst_raw;
+       u_int dgst_raw_len;
+
+       dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
+       if (!dgst_raw)
+               fatal("key_fingerprint: null from key_fingerprint_raw()");
+       switch (dgst_rep) {
+       case SSH_FP_HEX:
+               retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
+               break;
+       case SSH_FP_BUBBLEBABBLE:
+               retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
+               break;
+       case SSH_FP_RANDOMART:
+               retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
+               break;
+       default:
+               fatal("key_fingerprint: bad digest representation %d",
+                   dgst_rep);
+               break;
+       }
+       memset(dgst_raw, 0, dgst_raw_len);
+       xfree(dgst_raw);
+       return retval;
+}
+
+/*
+ * Reads a multiple-precision integer in decimal from the buffer, and advances
+ * the pointer.  The integer must already be initialized.  This function is
+ * permitted to modify the buffer.  This leaves *cpp to point just beyond the
+ * last processed (and maybe modified) character.  Note that this may modify
+ * the buffer containing the number.
+ */
+static int
+read_bignum(char **cpp, BIGNUM * value)
+{
+       char *cp = *cpp;
+       int old;
+
+       /* Skip any leading whitespace. */
+       for (; *cp == ' ' || *cp == '\t'; cp++)
+               ;
+
+       /* Check that it begins with a decimal digit. */
+       if (*cp < '0' || *cp > '9')
+               return 0;
+
+       /* Save starting position. */
+       *cpp = cp;
+
+       /* Move forward until all decimal digits skipped. */
+       for (; *cp >= '0' && *cp <= '9'; cp++)
+               ;
+
+       /* Save the old terminating character, and replace it by \0. */
+       old = *cp;
+       *cp = 0;
+
+       /* Parse the number. */
+       if (BN_dec2bn(&value, *cpp) == 0)
+               return 0;
+
+       /* Restore old terminating character. */
+       *cp = old;
+
+       /* Move beyond the number and return success. */
+       *cpp = cp;
+       return 1;
+}
+
+static int
+write_bignum(FILE *f, BIGNUM *num)
+{
+       char *buf = BN_bn2dec(num);
+       if (buf == NULL) {
+               error("write_bignum: BN_bn2dec() failed");
+               return 0;
+       }
+       fprintf(f, " %s", buf);
+       OPENSSL_free(buf);
+       return 1;
+}
+
+/* returns 1 ok, -1 error */
+int
+key_read(Key *ret, char **cpp)
+{
+       Key *k;
+       int success = -1;
+       char *cp, *space;
+       int len, n, type;
+       u_int bits;
+       u_char *blob;
+#ifdef OPENSSL_HAS_ECC
+       int curve_nid = -1;
+#endif
+
+       cp = *cpp;
+
+       switch (ret->type) {
+       case KEY_RSA1:
+               /* Get number of bits. */
+               if (*cp < '0' || *cp > '9')
+                       return -1;      /* Bad bit count... */
+               for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
+                       bits = 10 * bits + *cp - '0';
+               if (bits == 0)
+                       return -1;
+               *cpp = cp;
+               /* Get public exponent, public modulus. */
+               if (!read_bignum(cpp, ret->rsa->e))
+                       return -1;
+               if (!read_bignum(cpp, ret->rsa->n))
+                       return -1;
+               /* validate the claimed number of bits */
+               if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
+                       verbose("key_read: claimed key size %d does not match "
+                          "actual %d", bits, BN_num_bits(ret->rsa->n));
+                       return -1;
+               }
+               success = 1;
+               break;
+       case KEY_UNSPEC:
+       case KEY_RSA:
+       case KEY_DSA:
+       case KEY_ECDSA:
+       case KEY_DSA_CERT_V00:
+       case KEY_RSA_CERT_V00:
+       case KEY_DSA_CERT:
+       case KEY_ECDSA_CERT:
+       case KEY_RSA_CERT:
+               space = strchr(cp, ' ');
+               if (space == NULL) {
+                       debug3("key_read: missing whitespace");
+                       return -1;
+               }
+               *space = '\0';
+               type = key_type_from_name(cp);
+#ifdef OPENSSL_HAS_ECC
+               if (key_type_plain(type) == KEY_ECDSA &&
+                   (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
+                       debug("key_read: invalid curve");
+                       return -1;
+               }
+#endif
+               *space = ' ';
+               if (type == KEY_UNSPEC) {
+                       debug3("key_read: missing keytype");
+                       return -1;
+               }
+               cp = space+1;
+               if (*cp == '\0') {
+                       debug3("key_read: short string");
+                       return -1;
+               }
+               if (ret->type == KEY_UNSPEC) {
+                       ret->type = type;
+               } else if (ret->type != type) {
+                       /* is a key, but different type */
+                       debug3("key_read: type mismatch");
+                       return -1;
+               }
+               len = 2*strlen(cp);
+               blob = xmalloc(len);
+               n = uudecode(cp, blob, len);
+               if (n < 0) {
+                       error("key_read: uudecode %s failed", cp);
+                       xfree(blob);
+                       return -1;
+               }
+               k = key_from_blob(blob, (u_int)n);
+               xfree(blob);
+               if (k == NULL) {
+                       error("key_read: key_from_blob %s failed", cp);
+                       return -1;
+               }
+               if (k->type != type) {
+                       error("key_read: type mismatch: encoding error");
+                       key_free(k);
+                       return -1;
+               }
+#ifdef OPENSSL_HAS_ECC
+               if (key_type_plain(type) == KEY_ECDSA &&
+                   curve_nid != k->ecdsa_nid) {
+                       error("key_read: type mismatch: EC curve mismatch");
+                       key_free(k);
+                       return -1;
+               }
+#endif
+/*XXXX*/
+               if (key_is_cert(ret)) {
+                       if (!key_is_cert(k)) {
+                               error("key_read: loaded key is not a cert");
+                               key_free(k);
+                               return -1;
+                       }
+                       if (ret->cert != NULL)
+                               cert_free(ret->cert);
+                       ret->cert = k->cert;
+                       k->cert = NULL;
+               }
+               if (key_type_plain(ret->type) == KEY_RSA) {
+                       if (ret->rsa != NULL)
+                               RSA_free(ret->rsa);
+                       ret->rsa = k->rsa;
+                       k->rsa = NULL;
+#ifdef DEBUG_PK
+                       RSA_print_fp(stderr, ret->rsa, 8);
+#endif
+               }
+               if (key_type_plain(ret->type) == KEY_DSA) {
+                       if (ret->dsa != NULL)
+                               DSA_free(ret->dsa);
+                       ret->dsa = k->dsa;
+                       k->dsa = NULL;
+#ifdef DEBUG_PK
+                       DSA_print_fp(stderr, ret->dsa, 8);
+#endif
+               }
+#ifdef OPENSSL_HAS_ECC
+               if (key_type_plain(ret->type) == KEY_ECDSA) {
+                       if (ret->ecdsa != NULL)
+                               EC_KEY_free(ret->ecdsa);
+                       ret->ecdsa = k->ecdsa;
+                       ret->ecdsa_nid = k->ecdsa_nid;
+                       k->ecdsa = NULL;
+                       k->ecdsa_nid = -1;
+#ifdef DEBUG_PK
+                       key_dump_ec_key(ret->ecdsa);
+#endif
+               }
+#endif
+               success = 1;
+/*XXXX*/
+               key_free(k);
+               if (success != 1)
+                       break;
+               /* advance cp: skip whitespace and data */
+               while (*cp == ' ' || *cp == '\t')
+                       cp++;
+               while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+                       cp++;
+               *cpp = cp;
+               break;
+       default:
+               fatal("key_read: bad key type: %d", ret->type);
+               break;
+       }
+       return success;
+}
+
+int
+key_write(const Key *key, FILE *f)
+{
+       int n, success = 0;
+       u_int len, bits = 0;
+       u_char *blob;
+       char *uu;
+
+       if (key_is_cert(key)) {
+               if (key->cert == NULL) {
+                       error("%s: no cert data", __func__);
+                       return 0;
+               }
+               if (buffer_len(&key->cert->certblob) == 0) {
+                       error("%s: no signed certificate blob", __func__);
+                       return 0;
+               }
+       }
+
+       switch (key->type) {
+       case KEY_RSA1:
+               if (key->rsa == NULL)
+                       return 0;
+               /* size of modulus 'n' */
+               bits = BN_num_bits(key->rsa->n);
+               fprintf(f, "%u", bits);
+               if (write_bignum(f, key->rsa->e) &&
+                   write_bignum(f, key->rsa->n))
+                       return 1;
+               error("key_write: failed for RSA key");
+               return 0;
+       case KEY_DSA:
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               if (key->dsa == NULL)
+                       return 0;
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+       case KEY_ECDSA_CERT:
+               if (key->ecdsa == NULL)
+                       return 0;
+               break;
+#endif
+       case KEY_RSA:
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               if (key->rsa == NULL)
+                       return 0;
+               break;
+       default:
+               return 0;
+       }
+
+       key_to_blob(key, &blob, &len);
+       uu = xmalloc(2*len);
+       n = uuencode(blob, len, uu, 2*len);
+       if (n > 0) {
+               fprintf(f, "%s %s", key_ssh_name(key), uu);
+               success = 1;
+       }
+       xfree(blob);
+       xfree(uu);
+
+       return success;
+}
+
+const char *
+key_type(const Key *k)
+{
+       switch (k->type) {
+       case KEY_RSA1:
+               return "RSA1";
+       case KEY_RSA:
+               return "RSA";
+       case KEY_DSA:
+               return "DSA";
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+               return "ECDSA";
+#endif
+       case KEY_RSA_CERT_V00:
+               return "RSA-CERT-V00";
+       case KEY_DSA_CERT_V00:
+               return "DSA-CERT-V00";
+       case KEY_RSA_CERT:
+               return "RSA-CERT";
+       case KEY_DSA_CERT:
+               return "DSA-CERT";
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA_CERT:
+               return "ECDSA-CERT";
+#endif
+       }
+       return "unknown";
+}
+
+const char *
+key_cert_type(const Key *k)
+{
+       switch (k->cert->type) {
+       case SSH2_CERT_TYPE_USER:
+               return "user";
+       case SSH2_CERT_TYPE_HOST:
+               return "host";
+       default:
+               return "unknown";
+       }
+}
+
+static const char *
+key_ssh_name_from_type_nid(int type, int nid)
+{
+       switch (type) {
+       case KEY_RSA:
+               return "ssh-rsa";
+       case KEY_DSA:
+               return "ssh-dss";
+       case KEY_RSA_CERT_V00:
+               return "ssh-rsa-cert-v00@openssh.com";
+       case KEY_DSA_CERT_V00:
+               return "ssh-dss-cert-v00@openssh.com";
+       case KEY_RSA_CERT:
+               return "ssh-rsa-cert-v01@openssh.com";
+       case KEY_DSA_CERT:
+               return "ssh-dss-cert-v01@openssh.com";
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+               switch (nid) {
+               case NID_X9_62_prime256v1:
+                       return "ecdsa-sha2-nistp256";
+               case NID_secp384r1:
+                       return "ecdsa-sha2-nistp384";
+               case NID_secp521r1:
+                       return "ecdsa-sha2-nistp521";
+               default:
+                       break;
+               }
+               break;
+       case KEY_ECDSA_CERT:
+               switch (nid) {
+               case NID_X9_62_prime256v1:
+                       return "ecdsa-sha2-nistp256-cert-v01@openssh.com";
+               case NID_secp384r1:
+                       return "ecdsa-sha2-nistp384-cert-v01@openssh.com";
+               case NID_secp521r1:
+                       return "ecdsa-sha2-nistp521-cert-v01@openssh.com";
+               default:
+                       break;
+               }
+               break;
+#endif /* OPENSSL_HAS_ECC */
+       }
+       return "ssh-unknown";
+}
+
+const char *
+key_ssh_name(const Key *k)
+{
+       return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
+}
+
+const char *
+key_ssh_name_plain(const Key *k)
+{
+       return key_ssh_name_from_type_nid(key_type_plain(k->type),
+           k->ecdsa_nid);
+}
+
+u_int
+key_size(const Key *k)
+{
+       switch (k->type) {
+       case KEY_RSA1:
+       case KEY_RSA:
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               return BN_num_bits(k->rsa->n);
+       case KEY_DSA:
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               return BN_num_bits(k->dsa->p);
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+       case KEY_ECDSA_CERT:
+               return key_curve_nid_to_bits(k->ecdsa_nid);
+#endif
+       }
+       return 0;
+}
+
+static RSA *
+rsa_generate_private_key(u_int bits)
+{
+       RSA *private = RSA_new();
+       BIGNUM *f4 = BN_new();
+
+       if (private == NULL)
+               fatal("%s: RSA_new failed", __func__);
+       if (f4 == NULL)
+               fatal("%s: BN_new failed", __func__);
+       if (!BN_set_word(f4, RSA_F4))
+               fatal("%s: BN_new failed", __func__);
+       if (!RSA_generate_key_ex(private, bits, f4, NULL))
+               fatal("%s: key generation failed.", __func__);
+       BN_free(f4);
+       return private;
+}
+
+static DSA*
+dsa_generate_private_key(u_int bits)
+{
+       DSA *private = DSA_new();
+
+       if (private == NULL)
+               fatal("%s: DSA_new failed", __func__);
+       if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
+           NULL, NULL))
+               fatal("%s: DSA_generate_parameters failed", __func__);
+       if (!DSA_generate_key(private))
+               fatal("%s: DSA_generate_key failed.", __func__);
+       return private;
+}
+
+int
+key_ecdsa_bits_to_nid(int bits)
+{
+       switch (bits) {
+#ifdef OPENSSL_HAS_ECC
+       case 256:
+               return NID_X9_62_prime256v1;
+       case 384:
+               return NID_secp384r1;
+       case 521:
+               return NID_secp521r1;
+#endif
+       default:
+               return -1;
+       }
+}
+
+#ifdef OPENSSL_HAS_ECC
+int
+key_ecdsa_key_to_nid(EC_KEY *k)
+{
+       EC_GROUP *eg;
+       int nids[] = {
+               NID_X9_62_prime256v1,
+               NID_secp384r1,
+               NID_secp521r1,
+               -1
+       };
+       int nid;
+       u_int i;
+       BN_CTX *bnctx;
+       const EC_GROUP *g = EC_KEY_get0_group(k);
+
+       /*
+        * The group may be stored in a ASN.1 encoded private key in one of two
+        * ways: as a "named group", which is reconstituted by ASN.1 object ID
+        * or explicit group parameters encoded into the key blob. Only the
+        * "named group" case sets the group NID for us, but we can figure
+        * it out for the other case by comparing against all the groups that
+        * are supported.
+        */
+       if ((nid = EC_GROUP_get_curve_name(g)) > 0)
+               return nid;
+       if ((bnctx = BN_CTX_new()) == NULL)
+               fatal("%s: BN_CTX_new() failed", __func__);
+       for (i = 0; nids[i] != -1; i++) {
+               if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
+                       fatal("%s: EC_GROUP_new_by_curve_name failed",
+                           __func__);
+               if (EC_GROUP_cmp(g, eg, bnctx) == 0)
+                       break;
+               EC_GROUP_free(eg);
+       }
+       BN_CTX_free(bnctx);
+       debug3("%s: nid = %d", __func__, nids[i]);
+       if (nids[i] != -1) {
+               /* Use the group with the NID attached */
+               EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
+               if (EC_KEY_set_group(k, eg) != 1)
+                       fatal("%s: EC_KEY_set_group", __func__);
+       }
+       return nids[i];
+}
+
+static EC_KEY*
+ecdsa_generate_private_key(u_int bits, int *nid)
+{
+       EC_KEY *private;
+
+       if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
+               fatal("%s: invalid key length", __func__);
+       if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
+               fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
+       if (EC_KEY_generate_key(private) != 1)
+               fatal("%s: EC_KEY_generate_key failed", __func__);
+       EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
+       return private;
+}
+#endif /* OPENSSL_HAS_ECC */
+
+Key *
+key_generate(int type, u_int bits)
+{
+       Key *k = key_new(KEY_UNSPEC);
+       switch (type) {
+       case KEY_DSA:
+               k->dsa = dsa_generate_private_key(bits);
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+               k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
+               break;
+#endif
+       case KEY_RSA:
+       case KEY_RSA1:
+               k->rsa = rsa_generate_private_key(bits);
+               break;
+       case KEY_RSA_CERT_V00:
+       case KEY_DSA_CERT_V00:
+       case KEY_RSA_CERT:
+       case KEY_DSA_CERT:
+               fatal("key_generate: cert keys cannot be generated directly");
+       default:
+               fatal("key_generate: unknown type %d", type);
+       }
+       k->type = type;
+       return k;
+}
+
+void
+key_cert_copy(const Key *from_key, struct Key *to_key)
+{
+       u_int i;
+       const struct KeyCert *from;
+       struct KeyCert *to;
+
+       if (to_key->cert != NULL) {
+               cert_free(to_key->cert);
+               to_key->cert = NULL;
+       }
+
+       if ((from = from_key->cert) == NULL)
+               return;
+
+       to = to_key->cert = cert_new();
+
+       buffer_append(&to->certblob, buffer_ptr(&from->certblob),
+           buffer_len(&from->certblob));
+
+       buffer_append(&to->critical,
+           buffer_ptr(&from->critical), buffer_len(&from->critical));
+       buffer_append(&to->extensions,
+           buffer_ptr(&from->extensions), buffer_len(&from->extensions));
+
+       to->serial = from->serial;
+       to->type = from->type;
+       to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
+       to->valid_after = from->valid_after;
+       to->valid_before = from->valid_before;
+       to->signature_key = from->signature_key == NULL ?
+           NULL : key_from_private(from->signature_key);
+
+       to->nprincipals = from->nprincipals;
+       if (to->nprincipals > CERT_MAX_PRINCIPALS)
+               fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
+                   __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
+       if (to->nprincipals > 0) {
+               to->principals = xcalloc(from->nprincipals,
+                   sizeof(*to->principals));
+               for (i = 0; i < to->nprincipals; i++)
+                       to->principals[i] = xstrdup(from->principals[i]);
+       }
+}
+
+Key *
+key_from_private(const Key *k)
+{
+       Key *n = NULL;
+       switch (k->type) {
+       case KEY_DSA:
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               n = key_new(k->type);
+               if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
+                   (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
+                   (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
+                   (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
+                       fatal("key_from_private: BN_copy failed");
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+       case KEY_ECDSA_CERT:
+               n = key_new(k->type);
+               n->ecdsa_nid = k->ecdsa_nid;
+               if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
+                       fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
+               if (EC_KEY_set_public_key(n->ecdsa,
+                   EC_KEY_get0_public_key(k->ecdsa)) != 1)
+                       fatal("%s: EC_KEY_set_public_key failed", __func__);
+               break;
+#endif
+       case KEY_RSA:
+       case KEY_RSA1:
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               n = key_new(k->type);
+               if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
+                   (BN_copy(n->rsa->e, k->rsa->e) == NULL))
+                       fatal("key_from_private: BN_copy failed");
+               break;
+       default:
+               fatal("key_from_private: unknown type %d", k->type);
+               break;
+       }
+       if (key_is_cert(k))
+               key_cert_copy(k, n);
+       return n;
+}
+
+int
+key_type_from_name(char *name)
+{
+       if (strcmp(name, "rsa1") == 0) {
+               return KEY_RSA1;
+       } else if (strcmp(name, "rsa") == 0) {
+               return KEY_RSA;
+       } else if (strcmp(name, "dsa") == 0) {
+               return KEY_DSA;
+       } else if (strcmp(name, "ssh-rsa") == 0) {
+               return KEY_RSA;
+       } else if (strcmp(name, "ssh-dss") == 0) {
+               return KEY_DSA;
+#ifdef OPENSSL_HAS_ECC
+       } else if (strcmp(name, "ecdsa") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp521") == 0) {
+               return KEY_ECDSA;
+#endif
+       } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
+               return KEY_RSA_CERT_V00;
+       } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
+               return KEY_DSA_CERT_V00;
+       } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) {
+               return KEY_RSA_CERT;
+       } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
+               return KEY_DSA_CERT;
+#ifdef OPENSSL_HAS_ECC
+       } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
+               return KEY_ECDSA_CERT;
+#endif
+       }
+
+       debug2("key_type_from_name: unknown key type '%s'", name);
+       return KEY_UNSPEC;
+}
+
+int
+key_ecdsa_nid_from_name(const char *name)
+{
+#ifdef OPENSSL_HAS_ECC
+       if (strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0)
+               return NID_X9_62_prime256v1;
+       if (strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0)
+               return NID_secp384r1;
+       if (strcmp(name, "ecdsa-sha2-nistp521") == 0 ||
+           strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0)
+               return NID_secp521r1;
+#endif /* OPENSSL_HAS_ECC */
+
+       debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
+       return -1;
+}
+
+int
+key_names_valid2(const char *names)
+{
+       char *s, *cp, *p;
+
+       if (names == NULL || strcmp(names, "") == 0)
+               return 0;
+       s = cp = xstrdup(names);
+       for ((p = strsep(&cp, ",")); p && *p != '\0';
+           (p = strsep(&cp, ","))) {
+               switch (key_type_from_name(p)) {
+               case KEY_RSA1:
+               case KEY_UNSPEC:
+                       xfree(s);
+                       return 0;
+               }
+       }
+       debug3("key names ok: [%s]", names);
+       xfree(s);
+       return 1;
+}
+
+static int
+cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
+{
+       u_char *principals, *critical, *exts, *sig_key, *sig;
+       u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
+       Buffer tmp;
+       char *principal;
+       int ret = -1;
+       int v00 = key->type == KEY_DSA_CERT_V00 ||
+           key->type == KEY_RSA_CERT_V00;
+
+       buffer_init(&tmp);
+
+       /* Copy the entire key blob for verification and later serialisation */
+       buffer_append(&key->cert->certblob, blob, blen);
+
+       elen = 0; /* Not touched for v00 certs */
+       principals = exts = critical = sig_key = sig = NULL;
+       if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
+           buffer_get_int_ret(&key->cert->type, b) != 0 ||
+           (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
+           (principals = buffer_get_string_ret(b, &plen)) == NULL ||
+           buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
+           buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
+           (critical = buffer_get_string_ret(b, &clen)) == NULL ||
+           (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
+           (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
+           buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
+           (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
+               error("%s: parse error", __func__);
+               goto out;
+       }
+
+       if (kidlen != strlen(key->cert->key_id)) {
+               error("%s: key ID contains \\0 character", __func__);
+               goto out;
+       }
+
+       /* Signature is left in the buffer so we can calculate this length */
+       signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
+
+       if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
+               error("%s: parse error", __func__);
+               goto out;
+       }
+
+       if (key->cert->type != SSH2_CERT_TYPE_USER &&
+           key->cert->type != SSH2_CERT_TYPE_HOST) {
+               error("Unknown certificate type %u", key->cert->type);
+               goto out;
+       }
+
+       buffer_append(&tmp, principals, plen);
+       while (buffer_len(&tmp) > 0) {
+               if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
+                       error("%s: Too many principals", __func__);
+                       goto out;
+               }
+               if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
+                       error("%s: Principals data invalid", __func__);
+                       goto out;
+               }
+               key->cert->principals = xrealloc(key->cert->principals,
+                   key->cert->nprincipals + 1, sizeof(*key->cert->principals));
+               key->cert->principals[key->cert->nprincipals++] = principal;
+       }
+
+       buffer_clear(&tmp);
+
+       buffer_append(&key->cert->critical, critical, clen);
+       buffer_append(&tmp, critical, clen);
+       /* validate structure */
+       while (buffer_len(&tmp) != 0) {
+               if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
+                   buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
+                       error("%s: critical option data invalid", __func__);
+                       goto out;
+               }
+       }
+       buffer_clear(&tmp);
+
+       buffer_append(&key->cert->extensions, exts, elen);
+       buffer_append(&tmp, exts, elen);
+       /* validate structure */
+       while (buffer_len(&tmp) != 0) {
+               if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
+                   buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
+                       error("%s: extension data invalid", __func__);
+                       goto out;
+               }
+       }
+       buffer_clear(&tmp);
+
+       if ((key->cert->signature_key = key_from_blob(sig_key,
+           sklen)) == NULL) {
+               error("%s: Signature key invalid", __func__);
+               goto out;
+       }
+       if (key->cert->signature_key->type != KEY_RSA &&
+           key->cert->signature_key->type != KEY_DSA &&
+           key->cert->signature_key->type != KEY_ECDSA) {
+               error("%s: Invalid signature key type %s (%d)", __func__,
+                   key_type(key->cert->signature_key),
+                   key->cert->signature_key->type);
+               goto out;
+       }
+
+       switch (key_verify(key->cert->signature_key, sig, slen, 
+           buffer_ptr(&key->cert->certblob), signed_len)) {
+       case 1:
+               ret = 0;
+               break; /* Good signature */
+       case 0:
+               error("%s: Invalid signature on certificate", __func__);
+               goto out;
+       case -1:
+               error("%s: Certificate signature verification failed",
+                   __func__);
+               goto out;
+       }
+
+ out:
+       buffer_free(&tmp);
+       if (principals != NULL)
+               xfree(principals);
+       if (critical != NULL)
+               xfree(critical);
+       if (exts != NULL)
+               xfree(exts);
+       if (sig_key != NULL)
+               xfree(sig_key);
+       if (sig != NULL)
+               xfree(sig);
+       return ret;
+}
+
+Key *
+key_from_blob(const u_char *blob, u_int blen)
+{
+       Buffer b;
+       int rlen, type;
+       char *ktype = NULL, *curve = NULL;
+       Key *key = NULL;
+#ifdef OPENSSL_HAS_ECC
+       EC_POINT *q = NULL;
+       int nid = -1;
+#endif
+
+#ifdef DEBUG_PK
+       dump_base64(stderr, blob, blen);
+#endif
+       buffer_init(&b);
+       buffer_append(&b, blob, blen);
+       if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
+               error("key_from_blob: can't read key type");
+               goto out;
+       }
+
+       type = key_type_from_name(ktype);
+#ifdef OPENSSL_HAS_ECC
+       if (key_type_plain(type) == KEY_ECDSA)
+               nid = key_ecdsa_nid_from_name(ktype);
+#endif
+
+       switch (type) {
+       case KEY_RSA_CERT:
+               (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
+               /* FALLTHROUGH */
+       case KEY_RSA:
+       case KEY_RSA_CERT_V00:
+               key = key_new(type);
+               if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
+                   buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
+                       error("key_from_blob: can't read rsa key");
+ badkey:
+                       key_free(key);
+                       key = NULL;
+                       goto out;
+               }
+#ifdef DEBUG_PK
+               RSA_print_fp(stderr, key->rsa, 8);
+#endif
+               break;
+       case KEY_DSA_CERT:
+               (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
+               /* FALLTHROUGH */
+       case KEY_DSA:
+       case KEY_DSA_CERT_V00:
+               key = key_new(type);
+               if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
+                   buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
+                   buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
+                   buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
+                       error("key_from_blob: can't read dsa key");
+                       goto badkey;
+               }
+#ifdef DEBUG_PK
+               DSA_print_fp(stderr, key->dsa, 8);
+#endif
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA_CERT:
+               (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
+               /* FALLTHROUGH */
+       case KEY_ECDSA:
+               key = key_new(type);
+               key->ecdsa_nid = nid;
+               if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {
+                       error("key_from_blob: can't read ecdsa curve");
+                       goto badkey;
+               }
+               if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {
+                       error("key_from_blob: ecdsa curve doesn't match type");
+                       goto badkey;
+               }
+               if (key->ecdsa != NULL)
+                       EC_KEY_free(key->ecdsa);
+               if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
+                   == NULL)
+                       fatal("key_from_blob: EC_KEY_new_by_curve_name failed");
+               if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)
+                       fatal("key_from_blob: EC_POINT_new failed");
+               if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),
+                   q) == -1) {
+                       error("key_from_blob: can't read ecdsa key point");
+                       goto badkey;
+               }
+               if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
+                   q) != 0)
+                       goto badkey;
+               if (EC_KEY_set_public_key(key->ecdsa, q) != 1)
+                       fatal("key_from_blob: EC_KEY_set_public_key failed");
+#ifdef DEBUG_PK
+               key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
+#endif
+               break;
+#endif /* OPENSSL_HAS_ECC */
+       case KEY_UNSPEC:
+               key = key_new(type);
+               break;
+       default:
+               error("key_from_blob: cannot handle type %s", ktype);
+               goto out;
+       }
+       if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
+               error("key_from_blob: can't parse cert data");
+               goto badkey;
+       }
+       rlen = buffer_len(&b);
+       if (key != NULL && rlen != 0)
+               error("key_from_blob: remaining bytes in key blob %d", rlen);
+ out:
+       if (ktype != NULL)
+               xfree(ktype);
+       if (curve != NULL)
+               xfree(curve);
+#ifdef OPENSSL_HAS_ECC
+       if (q != NULL)
+               EC_POINT_free(q);
+#endif
+       buffer_free(&b);
+       return key;
+}
+
+int
+key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
+{
+       Buffer b;
+       int len;
+
+       if (key == NULL) {
+               error("key_to_blob: key == NULL");
+               return 0;
+       }
+       buffer_init(&b);
+       switch (key->type) {
+       case KEY_DSA_CERT_V00:
+       case KEY_RSA_CERT_V00:
+       case KEY_DSA_CERT:
+       case KEY_ECDSA_CERT:
+       case KEY_RSA_CERT:
+               /* Use the existing blob */
+               buffer_append(&b, buffer_ptr(&key->cert->certblob),
+                   buffer_len(&key->cert->certblob));
+               break;
+       case KEY_DSA:
+               buffer_put_cstring(&b, key_ssh_name(key));
+               buffer_put_bignum2(&b, key->dsa->p);
+               buffer_put_bignum2(&b, key->dsa->q);
+               buffer_put_bignum2(&b, key->dsa->g);
+               buffer_put_bignum2(&b, key->dsa->pub_key);
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+               buffer_put_cstring(&b, key_ssh_name(key));
+               buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
+               buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
+                   EC_KEY_get0_public_key(key->ecdsa));
+               break;
+#endif
+       case KEY_RSA:
+               buffer_put_cstring(&b, key_ssh_name(key));
+               buffer_put_bignum2(&b, key->rsa->e);
+               buffer_put_bignum2(&b, key->rsa->n);
+               break;
+       default:
+               error("key_to_blob: unsupported key type %d", key->type);
+               buffer_free(&b);
+               return 0;
+       }
+       len = buffer_len(&b);
+       if (lenp != NULL)
+               *lenp = len;
+       if (blobp != NULL) {
+               *blobp = xmalloc(len);
+               memcpy(*blobp, buffer_ptr(&b), len);
+       }
+       memset(buffer_ptr(&b), 0, len);
+       buffer_free(&b);
+       return len;
+}
+
+int
+key_sign(
+    const Key *key,
+    u_char **sigp, u_int *lenp,
+    const u_char *data, u_int datalen)
+{
+       switch (key->type) {
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+       case KEY_DSA:
+               return ssh_dss_sign(key, sigp, lenp, data, datalen);
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA_CERT:
+       case KEY_ECDSA:
+               return ssh_ecdsa_sign(key, sigp, lenp, data, datalen);
+#endif
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+       case KEY_RSA:
+               return ssh_rsa_sign(key, sigp, lenp, data, datalen);
+       default:
+               error("key_sign: invalid key type %d", key->type);
+               return -1;
+       }
+}
+
+/*
+ * key_verify returns 1 for a correct signature, 0 for an incorrect signature
+ * and -1 on error.
+ */
+int
+key_verify(
+    const Key *key,
+    const u_char *signature, u_int signaturelen,
+    const u_char *data, u_int datalen)
+{
+       if (signaturelen == 0)
+               return -1;
+
+       switch (key->type) {
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+       case KEY_DSA:
+               return ssh_dss_verify(key, signature, signaturelen, data, datalen);
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA_CERT:
+       case KEY_ECDSA:
+               return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);
+#endif
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+       case KEY_RSA:
+               return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
+       default:
+               error("key_verify: invalid key type %d", key->type);
+               return -1;
+       }
+}
+
+/* Converts a private to a public key */
+Key *
+key_demote(const Key *k)
+{
+       Key *pk;
+
+       pk = xcalloc(1, sizeof(*pk));
+       pk->type = k->type;
+       pk->flags = k->flags;
+       pk->ecdsa_nid = k->ecdsa_nid;
+       pk->dsa = NULL;
+       pk->ecdsa = NULL;
+       pk->rsa = NULL;
+
+       switch (k->type) {
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               key_cert_copy(k, pk);
+               /* FALLTHROUGH */
+       case KEY_RSA1:
+       case KEY_RSA:
+               if ((pk->rsa = RSA_new()) == NULL)
+                       fatal("key_demote: RSA_new failed");
+               if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
+                       fatal("key_demote: BN_dup failed");
+               if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
+                       fatal("key_demote: BN_dup failed");
+               break;
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               key_cert_copy(k, pk);
+               /* FALLTHROUGH */
+       case KEY_DSA:
+               if ((pk->dsa = DSA_new()) == NULL)
+                       fatal("key_demote: DSA_new failed");
+               if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
+                       fatal("key_demote: BN_dup failed");
+               if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
+                       fatal("key_demote: BN_dup failed");
+               if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
+                       fatal("key_demote: BN_dup failed");
+               if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
+                       fatal("key_demote: BN_dup failed");
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA_CERT:
+               key_cert_copy(k, pk);
+               /* FALLTHROUGH */
+       case KEY_ECDSA:
+               if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)
+                       fatal("key_demote: EC_KEY_new_by_curve_name failed");
+               if (EC_KEY_set_public_key(pk->ecdsa,
+                   EC_KEY_get0_public_key(k->ecdsa)) != 1)
+                       fatal("key_demote: EC_KEY_set_public_key failed");
+               break;
+#endif
+       default:
+               fatal("key_free: bad key type %d", k->type);
+               break;
+       }
+
+       return (pk);
+}
+
+int
+key_is_cert(const Key *k)
+{
+       if (k == NULL)
+               return 0;
+       switch (k->type) {
+       case KEY_RSA_CERT_V00:
+       case KEY_DSA_CERT_V00:
+       case KEY_RSA_CERT:
+       case KEY_DSA_CERT:
+       case KEY_ECDSA_CERT:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/* Return the cert-less equivalent to a certified key type */
+int
+key_type_plain(int type)
+{
+       switch (type) {
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               return KEY_RSA;
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               return KEY_DSA;
+       case KEY_ECDSA_CERT:
+               return KEY_ECDSA;
+       default:
+               return type;
+       }
+}
+
+/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
+int
+key_to_certified(Key *k, int legacy)
+{
+       switch (k->type) {
+       case KEY_RSA:
+               k->cert = cert_new();
+               k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
+               return 0;
+       case KEY_DSA:
+               k->cert = cert_new();
+               k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
+               return 0;
+       case KEY_ECDSA:
+               if (legacy)
+                       fatal("%s: legacy ECDSA certificates are not supported",
+                           __func__);
+               k->cert = cert_new();
+               k->type = KEY_ECDSA_CERT;
+               return 0;
+       default:
+               error("%s: key has incorrect type %s", __func__, key_type(k));
+               return -1;
+       }
+}
+
+/* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
+int
+key_drop_cert(Key *k)
+{
+       switch (k->type) {
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               cert_free(k->cert);
+               k->type = KEY_RSA;
+               return 0;
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               cert_free(k->cert);
+               k->type = KEY_DSA;
+               return 0;
+       case KEY_ECDSA_CERT:
+               cert_free(k->cert);
+               k->type = KEY_ECDSA;
+               return 0;
+       default:
+               error("%s: key has incorrect type %s", __func__, key_type(k));
+               return -1;
+       }
+}
+
+/*
+ * Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating
+ * the signed certblob
+ */
+int
+key_certify(Key *k, Key *ca)
+{
+       Buffer principals;
+       u_char *ca_blob, *sig_blob, nonce[32];
+       u_int i, ca_len, sig_len;
+
+       if (k->cert == NULL) {
+               error("%s: key lacks cert info", __func__);
+               return -1;
+       }
+
+       if (!key_is_cert(k)) {
+               error("%s: certificate has unknown type %d", __func__,
+                   k->cert->type);
+               return -1;
+       }
+
+       if (ca->type != KEY_RSA && ca->type != KEY_DSA &&
+           ca->type != KEY_ECDSA) {
+               error("%s: CA key has unsupported type %s", __func__,
+                   key_type(ca));
+               return -1;
+       }
+
+       key_to_blob(ca, &ca_blob, &ca_len);
+
+       buffer_clear(&k->cert->certblob);
+       buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
+
+       /* -v01 certs put nonce first */
+       arc4random_buf(&nonce, sizeof(nonce));
+       if (!key_cert_is_legacy(k))
+               buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
+
+       switch (k->type) {
+       case KEY_DSA_CERT_V00:
+       case KEY_DSA_CERT:
+               buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
+               buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
+               buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
+               buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA_CERT:
+               buffer_put_cstring(&k->cert->certblob,
+                   key_curve_nid_to_name(k->ecdsa_nid));
+               buffer_put_ecpoint(&k->cert->certblob,
+                   EC_KEY_get0_group(k->ecdsa),
+                   EC_KEY_get0_public_key(k->ecdsa));
+               break;
+#endif
+       case KEY_RSA_CERT_V00:
+       case KEY_RSA_CERT:
+               buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
+               buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
+               break;
+       default:
+               error("%s: key has incorrect type %s", __func__, key_type(k));
+               buffer_clear(&k->cert->certblob);
+               xfree(ca_blob);
+               return -1;
+       }
+
+       /* -v01 certs have a serial number next */
+       if (!key_cert_is_legacy(k))
+               buffer_put_int64(&k->cert->certblob, k->cert->serial);
+
+       buffer_put_int(&k->cert->certblob, k->cert->type);
+       buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
+
+       buffer_init(&principals);
+       for (i = 0; i < k->cert->nprincipals; i++)
+               buffer_put_cstring(&principals, k->cert->principals[i]);
+       buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
+           buffer_len(&principals));
+       buffer_free(&principals);
+
+       buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
+       buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
+       buffer_put_string(&k->cert->certblob,
+           buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
+
+       /* -v01 certs have non-critical options here */
+       if (!key_cert_is_legacy(k)) {
+               buffer_put_string(&k->cert->certblob,
+                   buffer_ptr(&k->cert->extensions),
+                   buffer_len(&k->cert->extensions));
+       }
+
+       /* -v00 certs put the nonce at the end */
+       if (key_cert_is_legacy(k))
+               buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
+
+       buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
+       buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
+       xfree(ca_blob);
+
+       /* Sign the whole mess */
+       if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
+           buffer_len(&k->cert->certblob)) != 0) {
+               error("%s: signature operation failed", __func__);
+               buffer_clear(&k->cert->certblob);
+               return -1;
+       }
+       /* Append signature and we are done */
+       buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
+       xfree(sig_blob);
+
+       return 0;
+}
+
+int
+key_cert_check_authority(const Key *k, int want_host, int require_principal,
+    const char *name, const char **reason)
+{
+       u_int i, principal_matches;
+       time_t now = time(NULL);
+
+       if (want_host) {
+               if (k->cert->type != SSH2_CERT_TYPE_HOST) {
+                       *reason = "Certificate invalid: not a host certificate";
+                       return -1;
+               }
+       } else {
+               if (k->cert->type != SSH2_CERT_TYPE_USER) {
+                       *reason = "Certificate invalid: not a user certificate";
+                       return -1;
+               }
+       }
+       if (now < 0) {
+               error("%s: system clock lies before epoch", __func__);
+               *reason = "Certificate invalid: not yet valid";
+               return -1;
+       }
+       if ((u_int64_t)now < k->cert->valid_after) {
+               *reason = "Certificate invalid: not yet valid";
+               return -1;
+       }
+       if ((u_int64_t)now >= k->cert->valid_before) {
+               *reason = "Certificate invalid: expired";
+               return -1;
+       }
+       if (k->cert->nprincipals == 0) {
+               if (require_principal) {
+                       *reason = "Certificate lacks principal list";
+                       return -1;
+               }
+       } else if (name != NULL) {
+               principal_matches = 0;
+               for (i = 0; i < k->cert->nprincipals; i++) {
+                       if (strcmp(name, k->cert->principals[i]) == 0) {
+                               principal_matches = 1;
+                               break;
+                       }
+               }
+               if (!principal_matches) {
+                       *reason = "Certificate invalid: name is not a listed "
+                           "principal";
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int
+key_cert_is_legacy(Key *k)
+{
+       switch (k->type) {
+       case KEY_DSA_CERT_V00:
+       case KEY_RSA_CERT_V00:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/* XXX: these are really begging for a table-driven approach */
+int
+key_curve_name_to_nid(const char *name)
+{
+#ifdef OPENSSL_HAS_ECC
+       if (strcmp(name, "nistp256") == 0)
+               return NID_X9_62_prime256v1;
+       else if (strcmp(name, "nistp384") == 0)
+               return NID_secp384r1;
+       else if (strcmp(name, "nistp521") == 0)
+               return NID_secp521r1;
+#endif
+
+       debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
+       return -1;
+}
+
+u_int
+key_curve_nid_to_bits(int nid)
+{
+       switch (nid) {
+#ifdef OPENSSL_HAS_ECC
+       case NID_X9_62_prime256v1:
+               return 256;
+       case NID_secp384r1:
+               return 384;
+       case NID_secp521r1:
+               return 521;
+#endif
+       default:
+               error("%s: unsupported EC curve nid %d", __func__, nid);
+               return 0;
+       }
+}
+
+const char *
+key_curve_nid_to_name(int nid)
+{
+#ifdef OPENSSL_HAS_ECC
+       if (nid == NID_X9_62_prime256v1)
+               return "nistp256";
+       else if (nid == NID_secp384r1)
+               return "nistp384";
+       else if (nid == NID_secp521r1)
+               return "nistp521";
+#endif
+       error("%s: unsupported EC curve nid %d", __func__, nid);
+       return NULL;
+}
+
+#ifdef OPENSSL_HAS_ECC
+const EVP_MD *
+key_ec_nid_to_evpmd(int nid)
+{
+       int kbits = key_curve_nid_to_bits(nid);
+
+       if (kbits == 0)
+               fatal("%s: invalid nid %d", __func__, nid);
+       /* RFC5656 section 6.2.1 */
+       if (kbits <= 256)
+               return EVP_sha256();
+       else if (kbits <= 384)
+               return EVP_sha384();
+       else
+               return EVP_sha512();
+}
+
+int
+key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
+{
+       BN_CTX *bnctx;
+       EC_POINT *nq = NULL;
+       BIGNUM *order, *x, *y, *tmp;
+       int ret = -1;
+
+       if ((bnctx = BN_CTX_new()) == NULL)
+               fatal("%s: BN_CTX_new failed", __func__);
+       BN_CTX_start(bnctx);
+
+       /*
+        * We shouldn't ever hit this case because bignum_get_ecpoint()
+        * refuses to load GF2m points.
+        */
+       if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
+           NID_X9_62_prime_field) {
+               error("%s: group is not a prime field", __func__);
+               goto out;
+       }
+
+       /* Q != infinity */
+       if (EC_POINT_is_at_infinity(group, public)) {
+               error("%s: received degenerate public key (infinity)",
+                   __func__);
+               goto out;
+       }
+
+       if ((x = BN_CTX_get(bnctx)) == NULL ||
+           (y = BN_CTX_get(bnctx)) == NULL ||
+           (order = BN_CTX_get(bnctx)) == NULL ||
+           (tmp = BN_CTX_get(bnctx)) == NULL)
+               fatal("%s: BN_CTX_get failed", __func__);
+
+       /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
+       if (EC_GROUP_get_order(group, order, bnctx) != 1)
+               fatal("%s: EC_GROUP_get_order failed", __func__);
+       if (EC_POINT_get_affine_coordinates_GFp(group, public,
+           x, y, bnctx) != 1)
+               fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
+       if (BN_num_bits(x) <= BN_num_bits(order) / 2) {
+               error("%s: public key x coordinate too small: "
+                   "bits(x) = %d, bits(order)/2 = %d", __func__,
+                   BN_num_bits(x), BN_num_bits(order) / 2);
+               goto out;
+       }
+       if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
+               error("%s: public key y coordinate too small: "
+                   "bits(y) = %d, bits(order)/2 = %d", __func__,
+                   BN_num_bits(x), BN_num_bits(order) / 2);
+               goto out;
+       }
+
+       /* nQ == infinity (n == order of subgroup) */
+       if ((nq = EC_POINT_new(group)) == NULL)
+               fatal("%s: BN_CTX_tmp failed", __func__);
+       if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)
+               fatal("%s: EC_GROUP_mul failed", __func__);
+       if (EC_POINT_is_at_infinity(group, nq) != 1) {
+               error("%s: received degenerate public key (nQ != infinity)",
+                   __func__);
+               goto out;
+       }
+
+       /* x < order - 1, y < order - 1 */
+       if (!BN_sub(tmp, order, BN_value_one()))
+               fatal("%s: BN_sub failed", __func__);
+       if (BN_cmp(x, tmp) >= 0) {
+               error("%s: public key x coordinate >= group order - 1",
+                   __func__);
+               goto out;
+       }
+       if (BN_cmp(y, tmp) >= 0) {
+               error("%s: public key y coordinate >= group order - 1",
+                   __func__);
+               goto out;
+       }
+       ret = 0;
+ out:
+       BN_CTX_free(bnctx);
+       EC_POINT_free(nq);
+       return ret;
+}
+
+int
+key_ec_validate_private(const EC_KEY *key)
+{
+       BN_CTX *bnctx;
+       BIGNUM *order, *tmp;
+       int ret = -1;
+
+       if ((bnctx = BN_CTX_new()) == NULL)
+               fatal("%s: BN_CTX_new failed", __func__);
+       BN_CTX_start(bnctx);
+
+       if ((order = BN_CTX_get(bnctx)) == NULL ||
+           (tmp = BN_CTX_get(bnctx)) == NULL)
+               fatal("%s: BN_CTX_get failed", __func__);
+
+       /* log2(private) > log2(order)/2 */
+       if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
+               fatal("%s: EC_GROUP_get_order failed", __func__);
+       if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
+           BN_num_bits(order) / 2) {
+               error("%s: private key too small: "
+                   "bits(y) = %d, bits(order)/2 = %d", __func__,
+                   BN_num_bits(EC_KEY_get0_private_key(key)),
+                   BN_num_bits(order) / 2);
+               goto out;
+       }
+
+       /* private < order - 1 */
+       if (!BN_sub(tmp, order, BN_value_one()))
+               fatal("%s: BN_sub failed", __func__);
+       if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {
+               error("%s: private key >= group order - 1", __func__);
+               goto out;
+       }
+       ret = 0;
+ out:
+       BN_CTX_free(bnctx);
+       return ret;
+}
+
+#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK)
+void
+key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
+{
+       BIGNUM *x, *y;
+       BN_CTX *bnctx;
+
+       if (point == NULL) {
+               fputs("point=(NULL)\n", stderr);
+               return;
+       }
+       if ((bnctx = BN_CTX_new()) == NULL)
+               fatal("%s: BN_CTX_new failed", __func__);
+       BN_CTX_start(bnctx);
+       if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)
+               fatal("%s: BN_CTX_get failed", __func__);
+       if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
+           NID_X9_62_prime_field)
+               fatal("%s: group is not a prime field", __func__);
+       if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)
+               fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
+       fputs("x=", stderr);
+       BN_print_fp(stderr, x);
+       fputs("\ny=", stderr);
+       BN_print_fp(stderr, y);
+       fputs("\n", stderr);
+       BN_CTX_free(bnctx);
+}
+
+void
+key_dump_ec_key(const EC_KEY *key)
+{
+       const BIGNUM *exponent;
+
+       key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key));
+       fputs("exponent=", stderr);
+       if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
+               fputs("(NULL)", stderr);
+       else
+               BN_print_fp(stderr, EC_KEY_get0_private_key(key));
+       fputs("\n", stderr);
+}
+#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */
+#endif /* OPENSSL_HAS_ECC */
diff --git a/.pc/gssapi.patch/key.h b/.pc/gssapi.patch/key.h
new file mode 100644 (file)
index 0000000..ec5ac5e
--- /dev/null
@@ -0,0 +1,151 @@
+/* $OpenBSD: key.h,v 1.33 2010/10/28 11:22:09 djm Exp $ */
+
+/*
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef KEY_H
+#define KEY_H
+
+#include "buffer.h"
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#ifdef OPENSSL_HAS_ECC
+#include <openssl/ec.h>
+#endif
+
+typedef struct Key Key;
+enum types {
+       KEY_RSA1,
+       KEY_RSA,
+       KEY_DSA,
+       KEY_ECDSA,
+       KEY_RSA_CERT,
+       KEY_DSA_CERT,
+       KEY_ECDSA_CERT,
+       KEY_RSA_CERT_V00,
+       KEY_DSA_CERT_V00,
+       KEY_UNSPEC
+};
+enum fp_type {
+       SSH_FP_SHA1,
+       SSH_FP_MD5
+};
+enum fp_rep {
+       SSH_FP_HEX,
+       SSH_FP_BUBBLEBABBLE,
+       SSH_FP_RANDOMART
+};
+
+/* key is stored in external hardware */
+#define KEY_FLAG_EXT           0x0001
+
+#define CERT_MAX_PRINCIPALS    256
+struct KeyCert {
+       Buffer           certblob; /* Kept around for use on wire */
+       u_int            type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
+       u_int64_t        serial;
+       char            *key_id;
+       u_int            nprincipals;
+       char            **principals;
+       u_int64_t        valid_after, valid_before;
+       Buffer           critical;
+       Buffer           extensions;
+       Key             *signature_key;
+};
+
+struct Key {
+       int      type;
+       int      flags;
+       RSA     *rsa;
+       DSA     *dsa;
+       int      ecdsa_nid;     /* NID of curve */
+#ifdef OPENSSL_HAS_ECC
+       EC_KEY  *ecdsa;
+#else
+       void    *ecdsa;
+#endif
+       struct KeyCert *cert;
+};
+
+Key            *key_new(int);
+void            key_add_private(Key *);
+Key            *key_new_private(int);
+void            key_free(Key *);
+Key            *key_demote(const Key *);
+int             key_equal_public(const Key *, const Key *);
+int             key_equal(const Key *, const Key *);
+char           *key_fingerprint(Key *, enum fp_type, enum fp_rep);
+u_char         *key_fingerprint_raw(Key *, enum fp_type, u_int *);
+const char     *key_type(const Key *);
+const char     *key_cert_type(const Key *);
+int             key_write(const Key *, FILE *);
+int             key_read(Key *, char **);
+u_int           key_size(const Key *);
+
+Key    *key_generate(int, u_int);
+Key    *key_from_private(const Key *);
+int     key_type_from_name(char *);
+int     key_is_cert(const Key *);
+int     key_type_plain(int);
+int     key_to_certified(Key *, int);
+int     key_drop_cert(Key *);
+int     key_certify(Key *, Key *);
+void    key_cert_copy(const Key *, struct Key *);
+int     key_cert_check_authority(const Key *, int, int, const char *,
+           const char **);
+int     key_cert_is_legacy(Key *);
+
+int             key_ecdsa_nid_from_name(const char *);
+int             key_curve_name_to_nid(const char *);
+const char *    key_curve_nid_to_name(int);
+u_int           key_curve_nid_to_bits(int);
+int             key_ecdsa_bits_to_nid(int);
+#ifdef OPENSSL_HAS_ECC
+int             key_ecdsa_key_to_nid(EC_KEY *);
+const EVP_MD *  key_ec_nid_to_evpmd(int nid);
+int             key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
+int             key_ec_validate_private(const EC_KEY *);
+#endif
+
+Key            *key_from_blob(const u_char *, u_int);
+int             key_to_blob(const Key *, u_char **, u_int *);
+const char     *key_ssh_name(const Key *);
+const char     *key_ssh_name_plain(const Key *);
+int             key_names_valid2(const char *);
+
+int     key_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
+int     key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
+
+int     ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
+int     ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
+int     ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
+int     ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
+int     ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
+int     ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
+
+#if defined(OPENSSL_HAS_ECC) && (defined(DEBUG_KEXECDH) || defined(DEBUG_PK))
+void   key_dump_ec_point(const EC_GROUP *, const EC_POINT *);
+void   key_dump_ec_key(const EC_KEY *);
+#endif
+
+#endif
diff --git a/.pc/gssapi.patch/monitor.c b/.pc/gssapi.patch/monitor.c
new file mode 100644 (file)
index 0000000..a166fed
--- /dev/null
@@ -0,0 +1,2308 @@
+/* $OpenBSD: monitor.c,v 1.115 2011/06/23 23:35:42 djm Exp $ */
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright 2002 Markus Friedl <markus@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include "openbsd-compat/sys-tree.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+# endif
+#endif
+
+#ifdef SKEY
+#include <skey.h>
+#endif
+
+#include <openssl/dh.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "atomicio.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "key.h"
+#include "buffer.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "cipher.h"
+#include "kex.h"
+#include "dh.h"
+#ifdef TARGET_OS_MAC   /* XXX Broken krb5 headers on Mac */
+#undef TARGET_OS_MAC
+#include "zlib.h"
+#define TARGET_OS_MAC 1
+#else
+#include "zlib.h"
+#endif
+#include "packet.h"
+#include "auth-options.h"
+#include "sshpty.h"
+#include "channels.h"
+#include "session.h"
+#include "sshlogin.h"
+#include "canohost.h"
+#include "log.h"
+#include "servconf.h"
+#include "monitor.h"
+#include "monitor_mm.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "monitor_fdpass.h"
+#include "misc.h"
+#include "compat.h"
+#include "ssh2.h"
+#include "jpake.h"
+#include "roaming.h"
+
+#ifdef GSSAPI
+static Gssctxt *gsscontext = NULL;
+#endif
+
+/* Imports */
+extern ServerOptions options;
+extern u_int utmp_len;
+extern Newkeys *current_keys[];
+extern z_stream incoming_stream;
+extern z_stream outgoing_stream;
+extern u_char session_id[];
+extern Buffer auth_debug;
+extern int auth_debug_init;
+extern Buffer loginmsg;
+
+/* State exported from the child */
+
+struct {
+       z_stream incoming;
+       z_stream outgoing;
+       u_char *keyin;
+       u_int keyinlen;
+       u_char *keyout;
+       u_int keyoutlen;
+       u_char *ivin;
+       u_int ivinlen;
+       u_char *ivout;
+       u_int ivoutlen;
+       u_char *ssh1key;
+       u_int ssh1keylen;
+       int ssh1cipher;
+       int ssh1protoflags;
+       u_char *input;
+       u_int ilen;
+       u_char *output;
+       u_int olen;
+       u_int64_t sent_bytes;
+       u_int64_t recv_bytes;
+} child_state;
+
+/* Functions on the monitor that answer unprivileged requests */
+
+int mm_answer_moduli(int, Buffer *);
+int mm_answer_sign(int, Buffer *);
+int mm_answer_pwnamallow(int, Buffer *);
+int mm_answer_auth2_read_banner(int, Buffer *);
+int mm_answer_authserv(int, Buffer *);
+int mm_answer_authpassword(int, Buffer *);
+int mm_answer_bsdauthquery(int, Buffer *);
+int mm_answer_bsdauthrespond(int, Buffer *);
+int mm_answer_skeyquery(int, Buffer *);
+int mm_answer_skeyrespond(int, Buffer *);
+int mm_answer_keyallowed(int, Buffer *);
+int mm_answer_keyverify(int, Buffer *);
+int mm_answer_pty(int, Buffer *);
+int mm_answer_pty_cleanup(int, Buffer *);
+int mm_answer_term(int, Buffer *);
+int mm_answer_rsa_keyallowed(int, Buffer *);
+int mm_answer_rsa_challenge(int, Buffer *);
+int mm_answer_rsa_response(int, Buffer *);
+int mm_answer_sesskey(int, Buffer *);
+int mm_answer_sessid(int, Buffer *);
+int mm_answer_jpake_get_pwdata(int, Buffer *);
+int mm_answer_jpake_step1(int, Buffer *);
+int mm_answer_jpake_step2(int, Buffer *);
+int mm_answer_jpake_key_confirm(int, Buffer *);
+int mm_answer_jpake_check_confirm(int, Buffer *);
+
+#ifdef USE_PAM
+int mm_answer_pam_start(int, Buffer *);
+int mm_answer_pam_account(int, Buffer *);
+int mm_answer_pam_init_ctx(int, Buffer *);
+int mm_answer_pam_query(int, Buffer *);
+int mm_answer_pam_respond(int, Buffer *);
+int mm_answer_pam_free_ctx(int, Buffer *);
+#endif
+
+#ifdef GSSAPI
+int mm_answer_gss_setup_ctx(int, Buffer *);
+int mm_answer_gss_accept_ctx(int, Buffer *);
+int mm_answer_gss_userok(int, Buffer *);
+int mm_answer_gss_checkmic(int, Buffer *);
+#endif
+
+#ifdef SSH_AUDIT_EVENTS
+int mm_answer_audit_event(int, Buffer *);
+int mm_answer_audit_command(int, Buffer *);
+#endif
+
+static int monitor_read_log(struct monitor *);
+
+static Authctxt *authctxt;
+static BIGNUM *ssh1_challenge = NULL;  /* used for ssh1 rsa auth */
+
+/* local state for key verify */
+static u_char *key_blob = NULL;
+static u_int key_bloblen = 0;
+static int key_blobtype = MM_NOKEY;
+static char *hostbased_cuser = NULL;
+static char *hostbased_chost = NULL;
+static char *auth_method = "unknown";
+static u_int session_id2_len = 0;
+static u_char *session_id2 = NULL;
+static pid_t monitor_child_pid;
+
+struct mon_table {
+       enum monitor_reqtype type;
+       int flags;
+       int (*f)(int, Buffer *);
+};
+
+#define MON_ISAUTH     0x0004  /* Required for Authentication */
+#define MON_AUTHDECIDE 0x0008  /* Decides Authentication */
+#define MON_ONCE       0x0010  /* Disable after calling */
+#define MON_ALOG       0x0020  /* Log auth attempt without authenticating */
+
+#define MON_AUTH       (MON_ISAUTH|MON_AUTHDECIDE)
+
+#define MON_PERMIT     0x1000  /* Request is permitted */
+
+struct mon_table mon_dispatch_proto20[] = {
+    {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
+    {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
+    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+    {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+    {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
+    {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+#ifdef USE_PAM
+    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
+    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
+    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
+    {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
+    {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
+#endif
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+#endif
+#ifdef BSD_AUTH
+    {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
+    {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
+#endif
+#ifdef SKEY
+    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
+    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
+#endif
+    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
+    {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+#endif
+#ifdef JPAKE
+    {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
+    {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1},
+    {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2},
+    {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm},
+    {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_postauth20[] = {
+    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
+    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
+    {MONITOR_REQ_PTY, 0, mm_answer_pty},
+    {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
+    {MONITOR_REQ_TERM, 0, mm_answer_term},
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_proto15[] = {
+    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+    {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
+    {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
+    {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+    {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed},
+    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed},
+    {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
+    {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
+#ifdef BSD_AUTH
+    {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
+    {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
+#endif
+#ifdef SKEY
+    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
+    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
+#endif
+#ifdef USE_PAM
+    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
+    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
+    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
+    {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
+    {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
+#endif
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_postauth15[] = {
+    {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
+    {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
+    {MONITOR_REQ_TERM, 0, mm_answer_term},
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table *mon_dispatch;
+
+/* Specifies if a certain message is allowed at the moment */
+
+static void
+monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
+{
+       while (ent->f != NULL) {
+               if (ent->type == type) {
+                       ent->flags &= ~MON_PERMIT;
+                       ent->flags |= permit ? MON_PERMIT : 0;
+                       return;
+               }
+               ent++;
+       }
+}
+
+static void
+monitor_permit_authentications(int permit)
+{
+       struct mon_table *ent = mon_dispatch;
+
+       while (ent->f != NULL) {
+               if (ent->flags & MON_AUTH) {
+                       ent->flags &= ~MON_PERMIT;
+                       ent->flags |= permit ? MON_PERMIT : 0;
+               }
+               ent++;
+       }
+}
+
+void
+monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
+{
+       struct mon_table *ent;
+       int authenticated = 0;
+
+       debug3("preauth child monitor started");
+
+       close(pmonitor->m_recvfd);
+       close(pmonitor->m_log_sendfd);
+       pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
+
+       authctxt = _authctxt;
+       memset(authctxt, 0, sizeof(*authctxt));
+
+       authctxt->loginmsg = &loginmsg;
+
+       if (compat20) {
+               mon_dispatch = mon_dispatch_proto20;
+
+               /* Permit requests for moduli and signatures */
+               monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+       } else {
+               mon_dispatch = mon_dispatch_proto15;
+
+               monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
+       }
+
+       /* The first few requests do not require asynchronous access */
+       while (!authenticated) {
+               auth_method = "unknown";
+               authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
+               if (authenticated) {
+                       if (!(ent->flags & MON_AUTHDECIDE))
+                               fatal("%s: unexpected authentication from %d",
+                                   __func__, ent->type);
+                       if (authctxt->pw->pw_uid == 0 &&
+                           !auth_root_allowed(auth_method))
+                               authenticated = 0;
+#ifdef USE_PAM
+                       /* PAM needs to perform account checks after auth */
+                       if (options.use_pam && authenticated) {
+                               Buffer m;
+
+                               buffer_init(&m);
+                               mm_request_receive_expect(pmonitor->m_sendfd,
+                                   MONITOR_REQ_PAM_ACCOUNT, &m);
+                               authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
+                               buffer_free(&m);
+                       }
+#endif
+               }
+
+               if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
+                       auth_log(authctxt, authenticated, auth_method,
+                           compat20 ? " ssh2" : "");
+                       if (!authenticated)
+                               authctxt->failures++;
+               }
+#ifdef JPAKE
+               /* Cleanup JPAKE context after authentication */
+               if (ent->flags & MON_AUTHDECIDE) {
+                       if (authctxt->jpake_ctx != NULL) {
+                               jpake_free(authctxt->jpake_ctx);
+                               authctxt->jpake_ctx = NULL;
+                       }
+               }
+#endif
+       }
+
+       /* Drain any buffered messages from the child */
+       while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
+               ;
+
+       if (!authctxt->valid)
+               fatal("%s: authenticated invalid user", __func__);
+       if (strcmp(auth_method, "unknown") == 0)
+               fatal("%s: authentication method name unknown", __func__);
+
+       debug("%s: %s has been authenticated by privileged process",
+           __func__, authctxt->user);
+
+       mm_get_keystate(pmonitor);
+
+       close(pmonitor->m_sendfd);
+       close(pmonitor->m_log_recvfd);
+       pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
+}
+
+static void
+monitor_set_child_handler(pid_t pid)
+{
+       monitor_child_pid = pid;
+}
+
+static void
+monitor_child_handler(int sig)
+{
+       kill(monitor_child_pid, sig);
+}
+
+void
+monitor_child_postauth(struct monitor *pmonitor)
+{
+       close(pmonitor->m_recvfd);
+       pmonitor->m_recvfd = -1;
+
+       monitor_set_child_handler(pmonitor->m_pid);
+       signal(SIGHUP, &monitor_child_handler);
+       signal(SIGTERM, &monitor_child_handler);
+       signal(SIGINT, &monitor_child_handler);
+
+       if (compat20) {
+               mon_dispatch = mon_dispatch_postauth20;
+
+               /* Permit requests for moduli and signatures */
+               monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+       } else {
+               mon_dispatch = mon_dispatch_postauth15;
+               monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+       }
+       if (!no_pty_flag) {
+               monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
+       }
+
+       for (;;)
+               monitor_read(pmonitor, mon_dispatch, NULL);
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
+}
+
+void
+monitor_sync(struct monitor *pmonitor)
+{
+       if (options.compression) {
+               /* The member allocation is not visible, so sync it */
+               mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback);
+       }
+}
+
+static int
+monitor_read_log(struct monitor *pmonitor)
+{
+       Buffer logmsg;
+       u_int len, level;
+       char *msg;
+
+       buffer_init(&logmsg);
+
+       /* Read length */
+       buffer_append_space(&logmsg, 4);
+       if (atomicio(read, pmonitor->m_log_recvfd,
+           buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
+               if (errno == EPIPE) {
+                       debug("%s: child log fd closed", __func__);
+                       close(pmonitor->m_log_recvfd);
+                       pmonitor->m_log_recvfd = -1;
+                       return -1;
+               }
+               fatal("%s: log fd read: %s", __func__, strerror(errno));
+       }
+       len = buffer_get_int(&logmsg);
+       if (len <= 4 || len > 8192)
+               fatal("%s: invalid log message length %u", __func__, len);
+
+       /* Read severity, message */
+       buffer_clear(&logmsg);
+       buffer_append_space(&logmsg, len);
+       if (atomicio(read, pmonitor->m_log_recvfd,
+           buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg))
+               fatal("%s: log fd read: %s", __func__, strerror(errno));
+
+       /* Log it */
+       level = buffer_get_int(&logmsg);
+       msg = buffer_get_string(&logmsg, NULL);
+       if (log_level_name(level) == NULL)
+               fatal("%s: invalid log level %u (corrupted message?)",
+                   __func__, level);
+       do_log2(level, "%s [preauth]", msg);
+
+       buffer_free(&logmsg);
+       xfree(msg);
+
+       return 0;
+}
+
+int
+monitor_read(struct monitor *pmonitor, struct mon_table *ent,
+    struct mon_table **pent)
+{
+       Buffer m;
+       int ret;
+       u_char type;
+       struct pollfd pfd[2];
+
+       for (;;) {
+               bzero(&pfd, sizeof(pfd));
+               pfd[0].fd = pmonitor->m_sendfd;
+               pfd[0].events = POLLIN;
+               pfd[1].fd = pmonitor->m_log_recvfd;
+               pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN;
+               if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) {
+                       if (errno == EINTR || errno == EAGAIN)
+                               continue;
+                       fatal("%s: poll: %s", __func__, strerror(errno));
+               }
+               if (pfd[1].revents) {
+                       /*
+                        * Drain all log messages before processing next
+                        * monitor request.
+                        */
+                       monitor_read_log(pmonitor);
+                       continue;
+               }
+               if (pfd[0].revents)
+                       break;  /* Continues below */
+       }
+
+       buffer_init(&m);
+
+       mm_request_receive(pmonitor->m_sendfd, &m);
+       type = buffer_get_char(&m);
+
+       debug3("%s: checking request %d", __func__, type);
+
+       while (ent->f != NULL) {
+               if (ent->type == type)
+                       break;
+               ent++;
+       }
+
+       if (ent->f != NULL) {
+               if (!(ent->flags & MON_PERMIT))
+                       fatal("%s: unpermitted request %d", __func__,
+                           type);
+               ret = (*ent->f)(pmonitor->m_sendfd, &m);
+               buffer_free(&m);
+
+               /* The child may use this request only once, disable it */
+               if (ent->flags & MON_ONCE) {
+                       debug2("%s: %d used once, disabling now", __func__,
+                           type);
+                       ent->flags &= ~MON_PERMIT;
+               }
+
+               if (pent != NULL)
+                       *pent = ent;
+
+               return ret;
+       }
+
+       fatal("%s: unsupported request: %d", __func__, type);
+
+       /* NOTREACHED */
+       return (-1);
+}
+
+/* allowed key state */
+static int
+monitor_allowed_key(u_char *blob, u_int bloblen)
+{
+       /* make sure key is allowed */
+       if (key_blob == NULL || key_bloblen != bloblen ||
+           timingsafe_bcmp(key_blob, blob, key_bloblen))
+               return (0);
+       return (1);
+}
+
+static void
+monitor_reset_key_state(void)
+{
+       /* reset state */
+       if (key_blob != NULL)
+               xfree(key_blob);
+       if (hostbased_cuser != NULL)
+               xfree(hostbased_cuser);
+       if (hostbased_chost != NULL)
+               xfree(hostbased_chost);
+       key_blob = NULL;
+       key_bloblen = 0;
+       key_blobtype = MM_NOKEY;
+       hostbased_cuser = NULL;
+       hostbased_chost = NULL;
+}
+
+int
+mm_answer_moduli(int sock, Buffer *m)
+{
+       DH *dh;
+       int min, want, max;
+
+       min = buffer_get_int(m);
+       want = buffer_get_int(m);
+       max = buffer_get_int(m);
+
+       debug3("%s: got parameters: %d %d %d",
+           __func__, min, want, max);
+       /* We need to check here, too, in case the child got corrupted */
+       if (max < min || want < min || max < want)
+               fatal("%s: bad parameters: %d %d %d",
+                   __func__, min, want, max);
+
+       buffer_clear(m);
+
+       dh = choose_dh(min, want, max);
+       if (dh == NULL) {
+               buffer_put_char(m, 0);
+               return (0);
+       } else {
+               /* Send first bignum */
+               buffer_put_char(m, 1);
+               buffer_put_bignum2(m, dh->p);
+               buffer_put_bignum2(m, dh->g);
+
+               DH_free(dh);
+       }
+       mm_request_send(sock, MONITOR_ANS_MODULI, m);
+       return (0);
+}
+
+int
+mm_answer_sign(int sock, Buffer *m)
+{
+       Key *key;
+       u_char *p;
+       u_char *signature;
+       u_int siglen, datlen;
+       int keyid;
+
+       debug3("%s", __func__);
+
+       keyid = buffer_get_int(m);
+       p = buffer_get_string(m, &datlen);
+
+       /*
+        * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
+        * SHA384 (48 bytes) and SHA512 (64 bytes).
+        */
+       if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64)
+               fatal("%s: data length incorrect: %u", __func__, datlen);
+
+       /* save session id, it will be passed on the first call */
+       if (session_id2_len == 0) {
+               session_id2_len = datlen;
+               session_id2 = xmalloc(session_id2_len);
+               memcpy(session_id2, p, session_id2_len);
+       }
+
+       if ((key = get_hostkey_by_index(keyid)) == NULL)
+               fatal("%s: no hostkey from index %d", __func__, keyid);
+       if (key_sign(key, &signature, &siglen, p, datlen) < 0)
+               fatal("%s: key_sign failed", __func__);
+
+       debug3("%s: signature %p(%u)", __func__, signature, siglen);
+
+       buffer_clear(m);
+       buffer_put_string(m, signature, siglen);
+
+       xfree(p);
+       xfree(signature);
+
+       mm_request_send(sock, MONITOR_ANS_SIGN, m);
+
+       /* Turn on permissions for getpwnam */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+
+       return (0);
+}
+
+/* Retrieves the password entry and also checks if the user is permitted */
+
+int
+mm_answer_pwnamallow(int sock, Buffer *m)
+{
+       char *username;
+       struct passwd *pwent;
+       int allowed = 0;
+       u_int i;
+
+       debug3("%s", __func__);
+
+       if (authctxt->attempt++ != 0)
+               fatal("%s: multiple attempts for getpwnam", __func__);
+
+       username = buffer_get_string(m, NULL);
+
+       pwent = getpwnamallow(username);
+
+       authctxt->user = xstrdup(username);
+       setproctitle("%s [priv]", pwent ? username : "unknown");
+       xfree(username);
+
+       buffer_clear(m);
+
+       if (pwent == NULL) {
+               buffer_put_char(m, 0);
+               authctxt->pw = fakepw();
+               goto out;
+       }
+
+       allowed = 1;
+       authctxt->pw = pwent;
+       authctxt->valid = 1;
+
+       buffer_put_char(m, 1);
+       buffer_put_string(m, pwent, sizeof(struct passwd));
+       buffer_put_cstring(m, pwent->pw_name);
+       buffer_put_cstring(m, "*");
+       buffer_put_cstring(m, pwent->pw_gecos);
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+       buffer_put_cstring(m, pwent->pw_class);
+#endif
+       buffer_put_cstring(m, pwent->pw_dir);
+       buffer_put_cstring(m, pwent->pw_shell);
+
+ out:
+       buffer_put_string(m, &options, sizeof(options));
+
+#define M_CP_STROPT(x) do { \
+               if (options.x != NULL) \
+                       buffer_put_cstring(m, options.x); \
+       } while (0)
+#define M_CP_STRARRAYOPT(x, nx) do { \
+               for (i = 0; i < options.nx; i++) \
+                       buffer_put_cstring(m, options.x[i]); \
+       } while (0)
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+       
+       debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
+       mm_request_send(sock, MONITOR_ANS_PWNAM, m);
+
+       /* For SSHv1 allow authentication now */
+       if (!compat20)
+               monitor_permit_authentications(1);
+       else {
+               /* Allow service/style information on the auth context */
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
+       }
+#ifdef USE_PAM
+       if (options.use_pam)
+               monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
+#endif
+
+       return (0);
+}
+
+int mm_answer_auth2_read_banner(int sock, Buffer *m)
+{
+       char *banner;
+
+       buffer_clear(m);
+       banner = auth2_read_banner();
+       buffer_put_cstring(m, banner != NULL ? banner : "");
+       mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
+
+       if (banner != NULL)
+               xfree(banner);
+
+       return (0);
+}
+
+int
+mm_answer_authserv(int sock, Buffer *m)
+{
+       monitor_permit_authentications(1);
+
+       authctxt->service = buffer_get_string(m, NULL);
+       authctxt->style = buffer_get_string(m, NULL);
+       debug3("%s: service=%s, style=%s",
+           __func__, authctxt->service, authctxt->style);
+
+       if (strlen(authctxt->style) == 0) {
+               xfree(authctxt->style);
+               authctxt->style = NULL;
+       }
+
+       return (0);
+}
+
+int
+mm_answer_authpassword(int sock, Buffer *m)
+{
+       static int call_count;
+       char *passwd;
+       int authenticated;
+       u_int plen;
+
+       passwd = buffer_get_string(m, &plen);
+       /* Only authenticate if the context is valid */
+       authenticated = options.password_authentication &&
+           auth_password(authctxt, passwd);
+       memset(passwd, 0, strlen(passwd));
+       xfree(passwd);
+
+       buffer_clear(m);
+       buffer_put_int(m, authenticated);
+
+       debug3("%s: sending result %d", __func__, authenticated);
+       mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
+
+       call_count++;
+       if (plen == 0 && call_count == 1)
+               auth_method = "none";
+       else
+               auth_method = "password";
+
+       /* Causes monitor loop to terminate if authenticated */
+       return (authenticated);
+}
+
+#ifdef BSD_AUTH
+int
+mm_answer_bsdauthquery(int sock, Buffer *m)
+{
+       char *name, *infotxt;
+       u_int numprompts;
+       u_int *echo_on;
+       char **prompts;
+       u_int success;
+
+       success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
+           &prompts, &echo_on) < 0 ? 0 : 1;
+
+       buffer_clear(m);
+       buffer_put_int(m, success);
+       if (success)
+               buffer_put_cstring(m, prompts[0]);
+
+       debug3("%s: sending challenge success: %u", __func__, success);
+       mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
+
+       if (success) {
+               xfree(name);
+               xfree(infotxt);
+               xfree(prompts);
+               xfree(echo_on);
+       }
+
+       return (0);
+}
+
+int
+mm_answer_bsdauthrespond(int sock, Buffer *m)
+{
+       char *response;
+       int authok;
+
+       if (authctxt->as == 0)
+               fatal("%s: no bsd auth session", __func__);
+
+       response = buffer_get_string(m, NULL);
+       authok = options.challenge_response_authentication &&
+           auth_userresponse(authctxt->as, response, 0);
+       authctxt->as = NULL;
+       debug3("%s: <%s> = <%d>", __func__, response, authok);
+       xfree(response);
+
+       buffer_clear(m);
+       buffer_put_int(m, authok);
+
+       debug3("%s: sending authenticated: %d", __func__, authok);
+       mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
+
+       auth_method = "bsdauth";
+
+       return (authok != 0);
+}
+#endif
+
+#ifdef SKEY
+int
+mm_answer_skeyquery(int sock, Buffer *m)
+{
+       struct skey skey;
+       char challenge[1024];
+       u_int success;
+
+       success = _compat_skeychallenge(&skey, authctxt->user, challenge,
+           sizeof(challenge)) < 0 ? 0 : 1;
+
+       buffer_clear(m);
+       buffer_put_int(m, success);
+       if (success)
+               buffer_put_cstring(m, challenge);
+
+       debug3("%s: sending challenge success: %u", __func__, success);
+       mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m);
+
+       return (0);
+}
+
+int
+mm_answer_skeyrespond(int sock, Buffer *m)
+{
+       char *response;
+       int authok;
+
+       response = buffer_get_string(m, NULL);
+
+       authok = (options.challenge_response_authentication &&
+           authctxt->valid &&
+           skey_haskey(authctxt->pw->pw_name) == 0 &&
+           skey_passcheck(authctxt->pw->pw_name, response) != -1);
+
+       xfree(response);
+
+       buffer_clear(m);
+       buffer_put_int(m, authok);
+
+       debug3("%s: sending authenticated: %d", __func__, authok);
+       mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m);
+
+       auth_method = "skey";
+
+       return (authok != 0);
+}
+#endif
+
+#ifdef USE_PAM
+int
+mm_answer_pam_start(int sock, Buffer *m)
+{
+       if (!options.use_pam)
+               fatal("UsePAM not set, but ended up in %s anyway", __func__);
+
+       start_pam(authctxt);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1);
+
+       return (0);
+}
+
+int
+mm_answer_pam_account(int sock, Buffer *m)
+{
+       u_int ret;
+
+       if (!options.use_pam)
+               fatal("UsePAM not set, but ended up in %s anyway", __func__);
+
+       ret = do_pam_account();
+
+       buffer_put_int(m, ret);
+       buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
+
+       mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m);
+
+       return (ret);
+}
+
+static void *sshpam_ctxt, *sshpam_authok;
+extern KbdintDevice sshpam_device;
+
+int
+mm_answer_pam_init_ctx(int sock, Buffer *m)
+{
+
+       debug3("%s", __func__);
+       authctxt->user = buffer_get_string(m, NULL);
+       sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
+       sshpam_authok = NULL;
+       buffer_clear(m);
+       if (sshpam_ctxt != NULL) {
+               monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1);
+               buffer_put_int(m, 1);
+       } else {
+               buffer_put_int(m, 0);
+       }
+       mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
+       return (0);
+}
+
+int
+mm_answer_pam_query(int sock, Buffer *m)
+{
+       char *name = NULL, *info = NULL, **prompts = NULL;
+       u_int i, num = 0, *echo_on = 0;
+       int ret;
+
+       debug3("%s", __func__);
+       sshpam_authok = NULL;
+       ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on);
+       if (ret == 0 && num == 0)
+               sshpam_authok = sshpam_ctxt;
+       if (num > 1 || name == NULL || info == NULL)
+               ret = -1;
+       buffer_clear(m);
+       buffer_put_int(m, ret);
+       buffer_put_cstring(m, name);
+       xfree(name);
+       buffer_put_cstring(m, info);
+       xfree(info);
+       buffer_put_int(m, num);
+       for (i = 0; i < num; ++i) {
+               buffer_put_cstring(m, prompts[i]);
+               xfree(prompts[i]);
+               buffer_put_int(m, echo_on[i]);
+       }
+       if (prompts != NULL)
+               xfree(prompts);
+       if (echo_on != NULL)
+               xfree(echo_on);
+       auth_method = "keyboard-interactive/pam";
+       mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
+       return (0);
+}
+
+int
+mm_answer_pam_respond(int sock, Buffer *m)
+{
+       char **resp;
+       u_int i, num;
+       int ret;
+
+       debug3("%s", __func__);
+       sshpam_authok = NULL;
+       num = buffer_get_int(m);
+       if (num > 0) {
+               resp = xcalloc(num, sizeof(char *));
+               for (i = 0; i < num; ++i)
+                       resp[i] = buffer_get_string(m, NULL);
+               ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
+               for (i = 0; i < num; ++i)
+                       xfree(resp[i]);
+               xfree(resp);
+       } else {
+               ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
+       }
+       buffer_clear(m);
+       buffer_put_int(m, ret);
+       mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
+       auth_method = "keyboard-interactive/pam";
+       if (ret == 0)
+               sshpam_authok = sshpam_ctxt;
+       return (0);
+}
+
+int
+mm_answer_pam_free_ctx(int sock, Buffer *m)
+{
+
+       debug3("%s", __func__);
+       (sshpam_device.free_ctx)(sshpam_ctxt);
+       buffer_clear(m);
+       mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
+       auth_method = "keyboard-interactive/pam";
+       return (sshpam_authok == sshpam_ctxt);
+}
+#endif
+
+int
+mm_answer_keyallowed(int sock, Buffer *m)
+{
+       Key *key;
+       char *cuser, *chost;
+       u_char *blob;
+       u_int bloblen;
+       enum mm_keytype type = 0;
+       int allowed = 0;
+
+       debug3("%s entering", __func__);
+
+       type = buffer_get_int(m);
+       cuser = buffer_get_string(m, NULL);
+       chost = buffer_get_string(m, NULL);
+       blob = buffer_get_string(m, &bloblen);
+
+       key = key_from_blob(blob, bloblen);
+
+       if ((compat20 && type == MM_RSAHOSTKEY) ||
+           (!compat20 && type != MM_RSAHOSTKEY))
+               fatal("%s: key type and protocol mismatch", __func__);
+
+       debug3("%s: key_from_blob: %p", __func__, key);
+
+       if (key != NULL && authctxt->valid) {
+               switch (type) {
+               case MM_USERKEY:
+                       allowed = options.pubkey_authentication &&
+                           user_key_allowed(authctxt->pw, key);
+                       auth_method = "publickey";
+                       if (options.pubkey_authentication && allowed != 1)
+                               auth_clear_options();
+                       break;
+               case MM_HOSTKEY:
+                       allowed = options.hostbased_authentication &&
+                           hostbased_key_allowed(authctxt->pw,
+                           cuser, chost, key);
+                       auth_method = "hostbased";
+                       break;
+               case MM_RSAHOSTKEY:
+                       key->type = KEY_RSA1; /* XXX */
+                       allowed = options.rhosts_rsa_authentication &&
+                           auth_rhosts_rsa_key_allowed(authctxt->pw,
+                           cuser, chost, key);
+                       if (options.rhosts_rsa_authentication && allowed != 1)
+                               auth_clear_options();
+                       auth_method = "rsa";
+                       break;
+               default:
+                       fatal("%s: unknown key type %d", __func__, type);
+                       break;
+               }
+       }
+       if (key != NULL)
+               key_free(key);
+
+       /* clear temporarily storage (used by verify) */
+       monitor_reset_key_state();
+
+       if (allowed) {
+               /* Save temporarily for comparison in verify */
+               key_blob = blob;
+               key_bloblen = bloblen;
+               key_blobtype = type;
+               hostbased_cuser = cuser;
+               hostbased_chost = chost;
+       } else {
+               /* Log failed attempt */
+               auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
+               xfree(blob);
+               xfree(cuser);
+               xfree(chost);
+       }
+
+       debug3("%s: key %p is %s",
+           __func__, key, allowed ? "allowed" : "not allowed");
+
+       buffer_clear(m);
+       buffer_put_int(m, allowed);
+       buffer_put_int(m, forced_command != NULL);
+
+       mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
+
+       if (type == MM_RSAHOSTKEY)
+               monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
+
+       return (0);
+}
+
+static int
+monitor_valid_userblob(u_char *data, u_int datalen)
+{
+       Buffer b;
+       char *p;
+       u_int len;
+       int fail = 0;
+
+       buffer_init(&b);
+       buffer_append(&b, data, datalen);
+
+       if (datafellows & SSH_OLD_SESSIONID) {
+               p = buffer_ptr(&b);
+               len = buffer_len(&b);
+               if ((session_id2 == NULL) ||
+                   (len < session_id2_len) ||
+                   (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
+                       fail++;
+               buffer_consume(&b, session_id2_len);
+       } else {
+               p = buffer_get_string(&b, &len);
+               if ((session_id2 == NULL) ||
+                   (len != session_id2_len) ||
+                   (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
+                       fail++;
+               xfree(p);
+       }
+       if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+               fail++;
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(authctxt->user, p) != 0) {
+               logit("wrong user name passed to monitor: expected %s != %.100s",
+                   authctxt->user, p);
+               fail++;
+       }
+       xfree(p);
+       buffer_skip_string(&b);
+       if (datafellows & SSH_BUG_PKAUTH) {
+               if (!buffer_get_char(&b))
+                       fail++;
+       } else {
+               p = buffer_get_string(&b, NULL);
+               if (strcmp("publickey", p) != 0)
+                       fail++;
+               xfree(p);
+               if (!buffer_get_char(&b))
+                       fail++;
+               buffer_skip_string(&b);
+       }
+       buffer_skip_string(&b);
+       if (buffer_len(&b) != 0)
+               fail++;
+       buffer_free(&b);
+       return (fail == 0);
+}
+
+static int
+monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
+    char *chost)
+{
+       Buffer b;
+       char *p;
+       u_int len;
+       int fail = 0;
+
+       buffer_init(&b);
+       buffer_append(&b, data, datalen);
+
+       p = buffer_get_string(&b, &len);
+       if ((session_id2 == NULL) ||
+           (len != session_id2_len) ||
+           (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
+               fail++;
+       xfree(p);
+
+       if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+               fail++;
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(authctxt->user, p) != 0) {
+               logit("wrong user name passed to monitor: expected %s != %.100s",
+                   authctxt->user, p);
+               fail++;
+       }
+       xfree(p);
+       buffer_skip_string(&b); /* service */
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(p, "hostbased") != 0)
+               fail++;
+       xfree(p);
+       buffer_skip_string(&b); /* pkalg */
+       buffer_skip_string(&b); /* pkblob */
+
+       /* verify client host, strip trailing dot if necessary */
+       p = buffer_get_string(&b, NULL);
+       if (((len = strlen(p)) > 0) && p[len - 1] == '.')
+               p[len - 1] = '\0';
+       if (strcmp(p, chost) != 0)
+               fail++;
+       xfree(p);
+
+       /* verify client user */
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(p, cuser) != 0)
+               fail++;
+       xfree(p);
+
+       if (buffer_len(&b) != 0)
+               fail++;
+       buffer_free(&b);
+       return (fail == 0);
+}
+
+int
+mm_answer_keyverify(int sock, Buffer *m)
+{
+       Key *key;
+       u_char *signature, *data, *blob;
+       u_int signaturelen, datalen, bloblen;
+       int verified = 0;
+       int valid_data = 0;
+
+       blob = buffer_get_string(m, &bloblen);
+       signature = buffer_get_string(m, &signaturelen);
+       data = buffer_get_string(m, &datalen);
+
+       if (hostbased_cuser == NULL || hostbased_chost == NULL ||
+         !monitor_allowed_key(blob, bloblen))
+               fatal("%s: bad key, not previously allowed", __func__);
+
+       key = key_from_blob(blob, bloblen);
+       if (key == NULL)
+               fatal("%s: bad public key blob", __func__);
+
+       switch (key_blobtype) {
+       case MM_USERKEY:
+               valid_data = monitor_valid_userblob(data, datalen);
+               break;
+       case MM_HOSTKEY:
+               valid_data = monitor_valid_hostbasedblob(data, datalen,
+                   hostbased_cuser, hostbased_chost);
+               break;
+       default:
+               valid_data = 0;
+               break;
+       }
+       if (!valid_data)
+               fatal("%s: bad signature data blob", __func__);
+
+       verified = key_verify(key, signature, signaturelen, data, datalen);
+       debug3("%s: key %p signature %s",
+           __func__, key, (verified == 1) ? "verified" : "unverified");
+
+       key_free(key);
+       xfree(blob);
+       xfree(signature);
+       xfree(data);
+
+       auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
+
+       monitor_reset_key_state();
+
+       buffer_clear(m);
+       buffer_put_int(m, verified);
+       mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
+
+       return (verified == 1);
+}
+
+static void
+mm_record_login(Session *s, struct passwd *pw)
+{
+       socklen_t fromlen;
+       struct sockaddr_storage from;
+
+       /*
+        * Get IP address of client. If the connection is not a socket, let
+        * the address be 0.0.0.0.
+        */
+       memset(&from, 0, sizeof(from));
+       fromlen = sizeof(from);
+       if (packet_connection_is_on_socket()) {
+               if (getpeername(packet_get_connection_in(),
+                   (struct sockaddr *)&from, &fromlen) < 0) {
+                       debug("getpeername: %.100s", strerror(errno));
+                       cleanup_exit(255);
+               }
+       }
+       /* Record that there was a login on that tty from the remote host. */
+       record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
+           get_remote_name_or_ip(utmp_len, options.use_dns),
+           (struct sockaddr *)&from, fromlen);
+}
+
+static void
+mm_session_close(Session *s)
+{
+       debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
+       if (s->ttyfd != -1) {
+               debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
+               session_pty_cleanup2(s);
+       }
+       session_unused(s->self);
+}
+
+int
+mm_answer_pty(int sock, Buffer *m)
+{
+       extern struct monitor *pmonitor;
+       Session *s;
+       int res, fd0;
+
+       debug3("%s entering", __func__);
+
+       buffer_clear(m);
+       s = session_new();
+       if (s == NULL)
+               goto error;
+       s->authctxt = authctxt;
+       s->pw = authctxt->pw;
+       s->pid = pmonitor->m_pid;
+       res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
+       if (res == 0)
+               goto error;
+       pty_setowner(authctxt->pw, s->tty);
+
+       buffer_put_int(m, 1);
+       buffer_put_cstring(m, s->tty);
+
+       /* We need to trick ttyslot */
+       if (dup2(s->ttyfd, 0) == -1)
+               fatal("%s: dup2", __func__);
+
+       mm_record_login(s, authctxt->pw);
+
+       /* Now we can close the file descriptor again */
+       close(0);
+
+       /* send messages generated by record_login */
+       buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
+       buffer_clear(&loginmsg);
+
+       mm_request_send(sock, MONITOR_ANS_PTY, m);
+
+       if (mm_send_fd(sock, s->ptyfd) == -1 ||
+           mm_send_fd(sock, s->ttyfd) == -1)
+               fatal("%s: send fds failed", __func__);
+
+       /* make sure nothing uses fd 0 */
+       if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
+               fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
+       if (fd0 != 0)
+               error("%s: fd0 %d != 0", __func__, fd0);
+
+       /* slave is not needed */
+       close(s->ttyfd);
+       s->ttyfd = s->ptyfd;
+       /* no need to dup() because nobody closes ptyfd */
+       s->ptymaster = s->ptyfd;
+
+       debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd);
+
+       return (0);
+
+ error:
+       if (s != NULL)
+               mm_session_close(s);
+       buffer_put_int(m, 0);
+       mm_request_send(sock, MONITOR_ANS_PTY, m);
+       return (0);
+}
+
+int
+mm_answer_pty_cleanup(int sock, Buffer *m)
+{
+       Session *s;
+       char *tty;
+
+       debug3("%s entering", __func__);
+
+       tty = buffer_get_string(m, NULL);
+       if ((s = session_by_tty(tty)) != NULL)
+               mm_session_close(s);
+       buffer_clear(m);
+       xfree(tty);
+       return (0);
+}
+
+int
+mm_answer_sesskey(int sock, Buffer *m)
+{
+       BIGNUM *p;
+       int rsafail;
+
+       /* Turn off permissions */
+       monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0);
+
+       if ((p = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       buffer_get_bignum2(m, p);
+
+       rsafail = ssh1_session_key(p);
+
+       buffer_clear(m);
+       buffer_put_int(m, rsafail);
+       buffer_put_bignum2(m, p);
+
+       BN_clear_free(p);
+
+       mm_request_send(sock, MONITOR_ANS_SESSKEY, m);
+
+       /* Turn on permissions for sessid passing */
+       monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
+
+       return (0);
+}
+
+int
+mm_answer_sessid(int sock, Buffer *m)
+{
+       int i;
+
+       debug3("%s entering", __func__);
+
+       if (buffer_len(m) != 16)
+               fatal("%s: bad ssh1 session id", __func__);
+       for (i = 0; i < 16; i++)
+               session_id[i] = buffer_get_char(m);
+
+       /* Turn on permissions for getpwnam */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+
+       return (0);
+}
+
+int
+mm_answer_rsa_keyallowed(int sock, Buffer *m)
+{
+       BIGNUM *client_n;
+       Key *key = NULL;
+       u_char *blob = NULL;
+       u_int blen = 0;
+       int allowed = 0;
+
+       debug3("%s entering", __func__);
+
+       auth_method = "rsa";
+       if (options.rsa_authentication && authctxt->valid) {
+               if ((client_n = BN_new()) == NULL)
+                       fatal("%s: BN_new", __func__);
+               buffer_get_bignum2(m, client_n);
+               allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
+               BN_clear_free(client_n);
+       }
+       buffer_clear(m);
+       buffer_put_int(m, allowed);
+       buffer_put_int(m, forced_command != NULL);
+
+       /* clear temporarily storage (used by generate challenge) */
+       monitor_reset_key_state();
+
+       if (allowed && key != NULL) {
+               key->type = KEY_RSA;    /* cheat for key_to_blob */
+               if (key_to_blob(key, &blob, &blen) == 0)
+                       fatal("%s: key_to_blob failed", __func__);
+               buffer_put_string(m, blob, blen);
+
+               /* Save temporarily for comparison in verify */
+               key_blob = blob;
+               key_bloblen = blen;
+               key_blobtype = MM_RSAUSERKEY;
+       }
+       if (key != NULL)
+               key_free(key);
+
+       mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
+       monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
+       return (0);
+}
+
+int
+mm_answer_rsa_challenge(int sock, Buffer *m)
+{
+       Key *key = NULL;
+       u_char *blob;
+       u_int blen;
+
+       debug3("%s entering", __func__);
+
+       if (!authctxt->valid)
+               fatal("%s: authctxt not valid", __func__);
+       blob = buffer_get_string(m, &blen);
+       if (!monitor_allowed_key(blob, blen))
+               fatal("%s: bad key, not previously allowed", __func__);
+       if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
+               fatal("%s: key type mismatch", __func__);
+       if ((key = key_from_blob(blob, blen)) == NULL)
+               fatal("%s: received bad key", __func__);
+       if (key->type != KEY_RSA)
+               fatal("%s: received bad key type %d", __func__, key->type);
+       key->type = KEY_RSA1;
+       if (ssh1_challenge)
+               BN_clear_free(ssh1_challenge);
+       ssh1_challenge = auth_rsa_generate_challenge(key);
+
+       buffer_clear(m);
+       buffer_put_bignum2(m, ssh1_challenge);
+
+       debug3("%s sending reply", __func__);
+       mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
+
+       xfree(blob);
+       key_free(key);
+       return (0);
+}
+
+int
+mm_answer_rsa_response(int sock, Buffer *m)
+{
+       Key *key = NULL;
+       u_char *blob, *response;
+       u_int blen, len;
+       int success;
+
+       debug3("%s entering", __func__);
+
+       if (!authctxt->valid)
+               fatal("%s: authctxt not valid", __func__);
+       if (ssh1_challenge == NULL)
+               fatal("%s: no ssh1_challenge", __func__);
+
+       blob = buffer_get_string(m, &blen);
+       if (!monitor_allowed_key(blob, blen))
+               fatal("%s: bad key, not previously allowed", __func__);
+       if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
+               fatal("%s: key type mismatch: %d", __func__, key_blobtype);
+       if ((key = key_from_blob(blob, blen)) == NULL)
+               fatal("%s: received bad key", __func__);
+       response = buffer_get_string(m, &len);
+       if (len != 16)
+               fatal("%s: received bad response to challenge", __func__);
+       success = auth_rsa_verify_response(key, ssh1_challenge, response);
+
+       xfree(blob);
+       key_free(key);
+       xfree(response);
+
+       auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
+
+       /* reset state */
+       BN_clear_free(ssh1_challenge);
+       ssh1_challenge = NULL;
+       monitor_reset_key_state();
+
+       buffer_clear(m);
+       buffer_put_int(m, success);
+       mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m);
+
+       return (success);
+}
+
+int
+mm_answer_term(int sock, Buffer *req)
+{
+       extern struct monitor *pmonitor;
+       int res, status;
+
+       debug3("%s: tearing down sessions", __func__);
+
+       /* The child is terminating */
+       session_destroy_all(&mm_session_close);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               sshpam_cleanup();
+#endif
+
+       while (waitpid(pmonitor->m_pid, &status, 0) == -1)
+               if (errno != EINTR)
+                       exit(1);
+
+       res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
+
+       /* Terminate process */
+       exit(res);
+}
+
+#ifdef SSH_AUDIT_EVENTS
+/* Report that an audit event occurred */
+int
+mm_answer_audit_event(int socket, Buffer *m)
+{
+       ssh_audit_event_t event;
+
+       debug3("%s entering", __func__);
+
+       event = buffer_get_int(m);
+       switch(event) {
+       case SSH_AUTH_FAIL_PUBKEY:
+       case SSH_AUTH_FAIL_HOSTBASED:
+       case SSH_AUTH_FAIL_GSSAPI:
+       case SSH_LOGIN_EXCEED_MAXTRIES:
+       case SSH_LOGIN_ROOT_DENIED:
+       case SSH_CONNECTION_CLOSE:
+       case SSH_INVALID_USER:
+               audit_event(event);
+               break;
+       default:
+               fatal("Audit event type %d not permitted", event);
+       }
+
+       return (0);
+}
+
+int
+mm_answer_audit_command(int socket, Buffer *m)
+{
+       u_int len;
+       char *cmd;
+
+       debug3("%s entering", __func__);
+       cmd = buffer_get_string(m, &len);
+       /* sanity check command, if so how? */
+       audit_run_command(cmd);
+       xfree(cmd);
+       return (0);
+}
+#endif /* SSH_AUDIT_EVENTS */
+
+void
+monitor_apply_keystate(struct monitor *pmonitor)
+{
+       if (compat20) {
+               set_newkeys(MODE_IN);
+               set_newkeys(MODE_OUT);
+       } else {
+               packet_set_protocol_flags(child_state.ssh1protoflags);
+               packet_set_encryption_key(child_state.ssh1key,
+                   child_state.ssh1keylen, child_state.ssh1cipher);
+               xfree(child_state.ssh1key);
+       }
+
+       /* for rc4 and other stateful ciphers */
+       packet_set_keycontext(MODE_OUT, child_state.keyout);
+       xfree(child_state.keyout);
+       packet_set_keycontext(MODE_IN, child_state.keyin);
+       xfree(child_state.keyin);
+
+       if (!compat20) {
+               packet_set_iv(MODE_OUT, child_state.ivout);
+               xfree(child_state.ivout);
+               packet_set_iv(MODE_IN, child_state.ivin);
+               xfree(child_state.ivin);
+       }
+
+       memcpy(&incoming_stream, &child_state.incoming,
+           sizeof(incoming_stream));
+       memcpy(&outgoing_stream, &child_state.outgoing,
+           sizeof(outgoing_stream));
+
+       /* Update with new address */
+       if (options.compression)
+               mm_init_compression(pmonitor->m_zlib);
+
+       /* Network I/O buffers */
+       /* XXX inefficient for large buffers, need: buffer_init_from_string */
+       buffer_clear(packet_get_input());
+       buffer_append(packet_get_input(), child_state.input, child_state.ilen);
+       memset(child_state.input, 0, child_state.ilen);
+       xfree(child_state.input);
+
+       buffer_clear(packet_get_output());
+       buffer_append(packet_get_output(), child_state.output,
+                     child_state.olen);
+       memset(child_state.output, 0, child_state.olen);
+       xfree(child_state.output);
+
+       /* Roaming */
+       if (compat20)
+               roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes);
+}
+
+static Kex *
+mm_get_kex(Buffer *m)
+{
+       Kex *kex;
+       void *blob;
+       u_int bloblen;
+
+       kex = xcalloc(1, sizeof(*kex));
+       kex->session_id = buffer_get_string(m, &kex->session_id_len);
+       if (session_id2 == NULL ||
+           kex->session_id_len != session_id2_len ||
+           timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0)
+               fatal("mm_get_get: internal error: bad session id");
+       kex->we_need = buffer_get_int(m);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+       kex->server = 1;
+       kex->hostkey_type = buffer_get_int(m);
+       kex->kex_type = buffer_get_int(m);
+       blob = buffer_get_string(m, &bloblen);
+       buffer_init(&kex->my);
+       buffer_append(&kex->my, blob, bloblen);
+       xfree(blob);
+       blob = buffer_get_string(m, &bloblen);
+       buffer_init(&kex->peer);
+       buffer_append(&kex->peer, blob, bloblen);
+       xfree(blob);
+       kex->done = 1;
+       kex->flags = buffer_get_int(m);
+       kex->client_version_string = buffer_get_string(m, NULL);
+       kex->server_version_string = buffer_get_string(m, NULL);
+       kex->load_host_public_key=&get_hostkey_public_by_type;
+       kex->load_host_private_key=&get_hostkey_private_by_type;
+       kex->host_key_index=&get_hostkey_index;
+
+       return (kex);
+}
+
+/* This function requries careful sanity checking */
+
+void
+mm_get_keystate(struct monitor *pmonitor)
+{
+       Buffer m;
+       u_char *blob, *p;
+       u_int bloblen, plen;
+       u_int32_t seqnr, packets;
+       u_int64_t blocks, bytes;
+
+       debug3("%s: Waiting for new keys", __func__);
+
+       buffer_init(&m);
+       mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
+       if (!compat20) {
+               child_state.ssh1protoflags = buffer_get_int(&m);
+               child_state.ssh1cipher = buffer_get_int(&m);
+               child_state.ssh1key = buffer_get_string(&m,
+                   &child_state.ssh1keylen);
+               child_state.ivout = buffer_get_string(&m,
+                   &child_state.ivoutlen);
+               child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
+               goto skip;
+       } else {
+               /* Get the Kex for rekeying */
+               *pmonitor->m_pkex = mm_get_kex(&m);
+       }
+
+       blob = buffer_get_string(&m, &bloblen);
+       current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
+       xfree(blob);
+
+       debug3("%s: Waiting for second key", __func__);
+       blob = buffer_get_string(&m, &bloblen);
+       current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
+       xfree(blob);
+
+       /* Now get sequence numbers for the packets */
+       seqnr = buffer_get_int(&m);
+       blocks = buffer_get_int64(&m);
+       packets = buffer_get_int(&m);
+       bytes = buffer_get_int64(&m);
+       packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes);
+       seqnr = buffer_get_int(&m);
+       blocks = buffer_get_int64(&m);
+       packets = buffer_get_int(&m);
+       bytes = buffer_get_int64(&m);
+       packet_set_state(MODE_IN, seqnr, blocks, packets, bytes);
+
+ skip:
+       /* Get the key context */
+       child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
+       child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);
+
+       debug3("%s: Getting compression state", __func__);
+       /* Get compression state */
+       p = buffer_get_string(&m, &plen);
+       if (plen != sizeof(child_state.outgoing))
+               fatal("%s: bad request size", __func__);
+       memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
+       xfree(p);
+
+       p = buffer_get_string(&m, &plen);
+       if (plen != sizeof(child_state.incoming))
+               fatal("%s: bad request size", __func__);
+       memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
+       xfree(p);
+
+       /* Network I/O buffers */
+       debug3("%s: Getting Network I/O buffers", __func__);
+       child_state.input = buffer_get_string(&m, &child_state.ilen);
+       child_state.output = buffer_get_string(&m, &child_state.olen);
+
+       /* Roaming */
+       if (compat20) {
+               child_state.sent_bytes = buffer_get_int64(&m);
+               child_state.recv_bytes = buffer_get_int64(&m);
+       }
+
+       buffer_free(&m);
+}
+
+
+/* Allocation functions for zlib */
+void *
+mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
+{
+       size_t len = (size_t) size * ncount;
+       void *address;
+
+       if (len == 0 || ncount > SIZE_T_MAX / size)
+               fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);
+
+       address = mm_malloc(mm, len);
+
+       return (address);
+}
+
+void
+mm_zfree(struct mm_master *mm, void *address)
+{
+       mm_free(mm, address);
+}
+
+void
+mm_init_compression(struct mm_master *mm)
+{
+       outgoing_stream.zalloc = (alloc_func)mm_zalloc;
+       outgoing_stream.zfree = (free_func)mm_zfree;
+       outgoing_stream.opaque = mm;
+
+       incoming_stream.zalloc = (alloc_func)mm_zalloc;
+       incoming_stream.zfree = (free_func)mm_zfree;
+       incoming_stream.opaque = mm;
+}
+
+/* XXX */
+
+#define FD_CLOSEONEXEC(x) do { \
+       if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \
+               fatal("fcntl(%d, F_SETFD)", x); \
+} while (0)
+
+static void
+monitor_openfds(struct monitor *mon, int do_logfds)
+{
+       int pair[2];
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
+               fatal("%s: socketpair: %s", __func__, strerror(errno));
+       FD_CLOSEONEXEC(pair[0]);
+       FD_CLOSEONEXEC(pair[1]);
+       mon->m_recvfd = pair[0];
+       mon->m_sendfd = pair[1];
+
+       if (do_logfds) {
+               if (pipe(pair) == -1)
+                       fatal("%s: pipe: %s", __func__, strerror(errno));
+               FD_CLOSEONEXEC(pair[0]);
+               FD_CLOSEONEXEC(pair[1]);
+               mon->m_log_recvfd = pair[0];
+               mon->m_log_sendfd = pair[1];
+       } else
+               mon->m_log_recvfd = mon->m_log_sendfd = -1;
+}
+
+#define MM_MEMSIZE     65536
+
+struct monitor *
+monitor_init(void)
+{
+       struct monitor *mon;
+
+       mon = xcalloc(1, sizeof(*mon));
+
+       monitor_openfds(mon, 1);
+
+       /* Used to share zlib space across processes */
+       if (options.compression) {
+               mon->m_zback = mm_create(NULL, MM_MEMSIZE);
+               mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
+
+               /* Compression needs to share state across borders */
+               mm_init_compression(mon->m_zlib);
+       }
+
+       return mon;
+}
+
+void
+monitor_reinit(struct monitor *mon)
+{
+       monitor_openfds(mon, 0);
+}
+
+#ifdef GSSAPI
+int
+mm_answer_gss_setup_ctx(int sock, Buffer *m)
+{
+       gss_OID_desc goid;
+       OM_uint32 major;
+       u_int len;
+
+       goid.elements = buffer_get_string(m, &len);
+       goid.length = len;
+
+       major = ssh_gssapi_server_ctx(&gsscontext, &goid);
+
+       xfree(goid.elements);
+
+       buffer_clear(m);
+       buffer_put_int(m, major);
+
+       mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
+
+       /* Now we have a context, enable the step */
+       monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
+
+       return (0);
+}
+
+int
+mm_answer_gss_accept_ctx(int sock, Buffer *m)
+{
+       gss_buffer_desc in;
+       gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       OM_uint32 flags = 0; /* GSI needs this */
+       u_int len;
+
+       in.value = buffer_get_string(m, &len);
+       in.length = len;
+       major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
+       xfree(in.value);
+
+       buffer_clear(m);
+       buffer_put_int(m, major);
+       buffer_put_string(m, out.value, out.length);
+       buffer_put_int(m, flags);
+       mm_request_send(sock, MONITOR_ANS_GSSSTEP, m);
+
+       gss_release_buffer(&minor, &out);
+
+       if (major == GSS_S_COMPLETE) {
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
+       }
+       return (0);
+}
+
+int
+mm_answer_gss_checkmic(int sock, Buffer *m)
+{
+       gss_buffer_desc gssbuf, mic;
+       OM_uint32 ret;
+       u_int len;
+
+       gssbuf.value = buffer_get_string(m, &len);
+       gssbuf.length = len;
+       mic.value = buffer_get_string(m, &len);
+       mic.length = len;
+
+       ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
+
+       xfree(gssbuf.value);
+       xfree(mic.value);
+
+       buffer_clear(m);
+       buffer_put_int(m, ret);
+
+       mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m);
+
+       if (!GSS_ERROR(ret))
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
+
+       return (0);
+}
+
+int
+mm_answer_gss_userok(int sock, Buffer *m)
+{
+       int authenticated;
+
+       authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+
+       buffer_clear(m);
+       buffer_put_int(m, authenticated);
+
+       debug3("%s: sending result %d", __func__, authenticated);
+       mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
+
+       auth_method = "gssapi-with-mic";
+
+       /* Monitor loop will terminate if authenticated */
+       return (authenticated);
+}
+#endif /* GSSAPI */
+
+#ifdef JPAKE
+int
+mm_answer_jpake_step1(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx;
+       u_char *x3_proof, *x4_proof;
+       u_int x3_proof_len, x4_proof_len;
+
+       if (!options.zero_knowledge_password_authentication)
+               fatal("zero_knowledge_password_authentication disabled");
+
+       if (authctxt->jpake_ctx != NULL)
+               fatal("%s: authctxt->jpake_ctx already set (%p)",
+                   __func__, authctxt->jpake_ctx);
+       authctxt->jpake_ctx = pctx = jpake_new();
+
+       jpake_step1(pctx->grp,
+           &pctx->server_id, &pctx->server_id_len,
+           &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
+           &x3_proof, &x3_proof_len,
+           &x4_proof, &x4_proof_len);
+
+       JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__));
+
+       buffer_clear(m);
+
+       buffer_put_string(m, pctx->server_id, pctx->server_id_len);
+       buffer_put_bignum2(m, pctx->g_x3);
+       buffer_put_bignum2(m, pctx->g_x4);
+       buffer_put_string(m, x3_proof, x3_proof_len);
+       buffer_put_string(m, x4_proof, x4_proof_len);
+
+       debug3("%s: sending step1", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m);
+
+       bzero(x3_proof, x3_proof_len);
+       bzero(x4_proof, x4_proof_len);
+       xfree(x3_proof);
+       xfree(x4_proof);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1);
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_get_pwdata(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+       char *hash_scheme, *salt;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt);
+
+       buffer_clear(m);
+       /* pctx->s is sensitive, not returned to slave */
+       buffer_put_cstring(m, hash_scheme);
+       buffer_put_cstring(m, salt);
+
+       debug3("%s: sending pwdata", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m);
+
+       bzero(hash_scheme, strlen(hash_scheme));
+       bzero(salt, strlen(salt));
+       xfree(hash_scheme);
+       xfree(salt);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_step2(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+       u_char *x1_proof, *x2_proof, *x4_s_proof;
+       u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       if ((pctx->g_x1 = BN_new()) == NULL ||
+           (pctx->g_x2 = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+       buffer_get_bignum2(m, pctx->g_x1);
+       buffer_get_bignum2(m, pctx->g_x2);
+       pctx->client_id = buffer_get_string(m, &pctx->client_id_len);
+       x1_proof = buffer_get_string(m, &x1_proof_len);
+       x2_proof = buffer_get_string(m, &x2_proof_len);
+
+       jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
+           pctx->g_x1, pctx->g_x2, pctx->x4,
+           pctx->client_id, pctx->client_id_len,
+           pctx->server_id, pctx->server_id_len,
+           x1_proof, x1_proof_len,
+           x2_proof, x2_proof_len,
+           &pctx->b,
+           &x4_s_proof, &x4_s_proof_len);
+
+       JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__));
+
+       bzero(x1_proof, x1_proof_len);
+       bzero(x2_proof, x2_proof_len);
+       xfree(x1_proof);
+       xfree(x2_proof);
+
+       buffer_clear(m);
+
+       buffer_put_bignum2(m, pctx->b);
+       buffer_put_string(m, x4_s_proof, x4_s_proof_len);
+
+       debug3("%s: sending step2", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m);
+
+       bzero(x4_s_proof, x4_s_proof_len);
+       xfree(x4_s_proof);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_key_confirm(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+       u_char *x2_s_proof;
+       u_int x2_s_proof_len;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       if ((pctx->a = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+       buffer_get_bignum2(m, pctx->a);
+       x2_s_proof = buffer_get_string(m, &x2_s_proof_len);
+
+       jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
+           pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
+           pctx->server_id, pctx->server_id_len,
+           pctx->client_id, pctx->client_id_len,
+           session_id2, session_id2_len,
+           x2_s_proof, x2_s_proof_len,
+           &pctx->k,
+           &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len);
+
+       JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__));
+
+       bzero(x2_s_proof, x2_s_proof_len);
+       buffer_clear(m);
+
+       /* pctx->k is sensitive, not sent */
+       buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
+
+       debug3("%s: sending confirmation hash", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_check_confirm(int sock, Buffer *m)
+{
+       int authenticated = 0;
+       u_char *peer_confirm_hash;
+       u_int peer_confirm_hash_len;
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len);
+
+       authenticated = jpake_check_confirm(pctx->k,
+           pctx->client_id, pctx->client_id_len,
+           session_id2, session_id2_len,
+           peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid;
+
+       JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__));
+
+       bzero(peer_confirm_hash, peer_confirm_hash_len);
+       xfree(peer_confirm_hash);
+
+       buffer_clear(m);
+       buffer_put_int(m, authenticated);
+
+       debug3("%s: sending result %d", __func__, authenticated);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1);
+
+       auth_method = "jpake-01@openssh.com";
+       return authenticated;
+}
+
+#endif /* JPAKE */
diff --git a/.pc/gssapi.patch/monitor.h b/.pc/gssapi.patch/monitor.h
new file mode 100644 (file)
index 0000000..5e7d552
--- /dev/null
@@ -0,0 +1,99 @@
+/* $OpenBSD: monitor.h,v 1.16 2011/06/17 21:44:31 djm Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MONITOR_H_
+#define _MONITOR_H_
+
+enum monitor_reqtype {
+       MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
+       MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
+       MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
+       MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
+       MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
+       MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
+       MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
+       MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
+       MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
+       MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
+       MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
+       MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
+       MONITOR_REQ_KEYEXPORT,
+       MONITOR_REQ_PTY, MONITOR_ANS_PTY,
+       MONITOR_REQ_PTYCLEANUP,
+       MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY,
+       MONITOR_REQ_SESSID,
+       MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED,
+       MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE,
+       MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
+       MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP,
+       MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
+       MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
+       MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
+       MONITOR_REQ_PAM_START,
+       MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
+       MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
+       MONITOR_REQ_PAM_QUERY, MONITOR_ANS_PAM_QUERY,
+       MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND,
+       MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX,
+       MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND,
+       MONITOR_REQ_TERM,
+       MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
+       MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
+       MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2,
+       MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM,
+       MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM,
+};
+
+struct mm_master;
+struct monitor {
+       int                      m_recvfd;
+       int                      m_sendfd;
+       int                      m_log_recvfd;
+       int                      m_log_sendfd;
+       struct mm_master        *m_zback;
+       struct mm_master        *m_zlib;
+       struct Kex              **m_pkex;
+       pid_t                    m_pid;
+};
+
+struct monitor *monitor_init(void);
+void monitor_reinit(struct monitor *);
+void monitor_sync(struct monitor *);
+
+struct Authctxt;
+void monitor_child_preauth(struct Authctxt *, struct monitor *);
+void monitor_child_postauth(struct monitor *);
+
+struct mon_table;
+int monitor_read(struct monitor*, struct mon_table *, struct mon_table **);
+
+/* Prototypes for request sending and receiving */
+void mm_request_send(int, enum monitor_reqtype, Buffer *);
+void mm_request_receive(int, Buffer *);
+void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *);
+
+#endif /* _MONITOR_H_ */
diff --git a/.pc/gssapi.patch/monitor_wrap.c b/.pc/gssapi.patch/monitor_wrap.c
new file mode 100644 (file)
index 0000000..1f60658
--- /dev/null
@@ -0,0 +1,1452 @@
+/* $OpenBSD: monitor_wrap.c,v 1.73 2011/06/17 21:44:31 djm Exp $ */
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright 2002 Markus Friedl <markus@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "dh.h"
+#include "buffer.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "auth-options.h"
+#include "packet.h"
+#include "mac.h"
+#include "log.h"
+#ifdef TARGET_OS_MAC    /* XXX Broken krb5 headers on Mac */
+#undef TARGET_OS_MAC
+#include "zlib.h"
+#define TARGET_OS_MAC 1
+#else
+#include "zlib.h"
+#endif
+#include "monitor.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "atomicio.h"
+#include "monitor_fdpass.h"
+#include "misc.h"
+#include "schnorr.h"
+#include "jpake.h"
+#include "uuencode.h"
+
+#include "channels.h"
+#include "session.h"
+#include "servconf.h"
+#include "roaming.h"
+
+/* Imports */
+extern int compat20;
+extern z_stream incoming_stream;
+extern z_stream outgoing_stream;
+extern struct monitor *pmonitor;
+extern Buffer loginmsg;
+extern ServerOptions options;
+
+void
+mm_log_handler(LogLevel level, const char *msg, void *ctx)
+{
+       Buffer log_msg;
+       struct monitor *mon = (struct monitor *)ctx;
+
+       if (mon->m_log_sendfd == -1)
+               fatal("%s: no log channel", __func__);
+
+       buffer_init(&log_msg);
+       /*
+        * Placeholder for packet length. Will be filled in with the actual
+        * packet length once the packet has been constucted. This saves
+        * fragile math.
+        */
+       buffer_put_int(&log_msg, 0);
+
+       buffer_put_int(&log_msg, level);
+       buffer_put_cstring(&log_msg, msg);
+       put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
+       if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
+           buffer_len(&log_msg)) != buffer_len(&log_msg))
+               fatal("%s: write: %s", __func__, strerror(errno));
+       buffer_free(&log_msg);
+}
+
+int
+mm_is_monitor(void)
+{
+       /*
+        * m_pid is only set in the privileged part, and
+        * points to the unprivileged child.
+        */
+       return (pmonitor && pmonitor->m_pid > 0);
+}
+
+void
+mm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
+{
+       u_int mlen = buffer_len(m);
+       u_char buf[5];
+
+       debug3("%s entering: type %d", __func__, type);
+
+       put_u32(buf, mlen + 1);
+       buf[4] = (u_char) type;         /* 1st byte of payload is mesg-type */
+       if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
+               fatal("%s: write: %s", __func__, strerror(errno));
+       if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
+               fatal("%s: write: %s", __func__, strerror(errno));
+}
+
+void
+mm_request_receive(int sock, Buffer *m)
+{
+       u_char buf[4];
+       u_int msg_len;
+
+       debug3("%s entering", __func__);
+
+       if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
+               if (errno == EPIPE)
+                       cleanup_exit(255);
+               fatal("%s: read: %s", __func__, strerror(errno));
+       }
+       msg_len = get_u32(buf);
+       if (msg_len > 256 * 1024)
+               fatal("%s: read: bad msg_len %d", __func__, msg_len);
+       buffer_clear(m);
+       buffer_append_space(m, msg_len);
+       if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
+               fatal("%s: read: %s", __func__, strerror(errno));
+}
+
+void
+mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
+{
+       u_char rtype;
+
+       debug3("%s entering: type %d", __func__, type);
+
+       mm_request_receive(sock, m);
+       rtype = buffer_get_char(m);
+       if (rtype != type)
+               fatal("%s: read: rtype %d != type %d", __func__,
+                   rtype, type);
+}
+
+DH *
+mm_choose_dh(int min, int nbits, int max)
+{
+       BIGNUM *p, *g;
+       int success = 0;
+       Buffer m;
+
+       buffer_init(&m);
+       buffer_put_int(&m, min);
+       buffer_put_int(&m, nbits);
+       buffer_put_int(&m, max);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
+
+       success = buffer_get_char(&m);
+       if (success == 0)
+               fatal("%s: MONITOR_ANS_MODULI failed", __func__);
+
+       if ((p = BN_new()) == NULL)
+               fatal("%s: BN_new failed", __func__);
+       if ((g = BN_new()) == NULL)
+               fatal("%s: BN_new failed", __func__);
+       buffer_get_bignum2(&m, p);
+       buffer_get_bignum2(&m, g);
+
+       debug3("%s: remaining %d", __func__, buffer_len(&m));
+       buffer_free(&m);
+
+       return (dh_new_group(g, p));
+}
+
+int
+mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
+{
+       Kex *kex = *pmonitor->m_pkex;
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_int(&m, kex->host_key_index(key));
+       buffer_put_string(&m, data, datalen);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
+       *sigp  = buffer_get_string(&m, lenp);
+       buffer_free(&m);
+
+       return (0);
+}
+
+struct passwd *
+mm_getpwnamallow(const char *username)
+{
+       Buffer m;
+       struct passwd *pw;
+       u_int len, i;
+       ServerOptions *newopts;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, username);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
+
+       if (buffer_get_char(&m) == 0) {
+               pw = NULL;
+               goto out;
+       }
+       pw = buffer_get_string(&m, &len);
+       if (len != sizeof(struct passwd))
+               fatal("%s: struct passwd size mismatch", __func__);
+       pw->pw_name = buffer_get_string(&m, NULL);
+       pw->pw_passwd = buffer_get_string(&m, NULL);
+       pw->pw_gecos = buffer_get_string(&m, NULL);
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+       pw->pw_class = buffer_get_string(&m, NULL);
+#endif
+       pw->pw_dir = buffer_get_string(&m, NULL);
+       pw->pw_shell = buffer_get_string(&m, NULL);
+
+out:
+       /* copy options block as a Match directive may have changed some */
+       newopts = buffer_get_string(&m, &len);
+       if (len != sizeof(*newopts))
+               fatal("%s: option block size mismatch", __func__);
+
+#define M_CP_STROPT(x) do { \
+               if (newopts->x != NULL) \
+                       newopts->x = buffer_get_string(&m, NULL); \
+       } while (0)
+#define M_CP_STRARRAYOPT(x, nx) do { \
+               for (i = 0; i < newopts->nx; i++) \
+                       newopts->x[i] = buffer_get_string(&m, NULL); \
+       } while (0)
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+
+       copy_set_server_options(&options, newopts, 1);
+       xfree(newopts);
+
+       buffer_free(&m);
+
+       return (pw);
+}
+
+char *
+mm_auth2_read_banner(void)
+{
+       Buffer m;
+       char *banner;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
+       buffer_clear(&m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_AUTH2_READ_BANNER, &m);
+       banner = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       /* treat empty banner as missing banner */
+       if (strlen(banner) == 0) {
+               xfree(banner);
+               banner = NULL;
+       }
+       return (banner);
+}
+
+/* Inform the privileged process about service and style */
+
+void
+mm_inform_authserv(char *service, char *style)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, service);
+       buffer_put_cstring(&m, style ? style : "");
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
+
+       buffer_free(&m);
+}
+
+/* Do the password authentication */
+int
+mm_auth_password(Authctxt *authctxt, char *password)
+{
+       Buffer m;
+       int authenticated = 0;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, password);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
+
+       authenticated = buffer_get_int(&m);
+
+       buffer_free(&m);
+
+       debug3("%s: user %sauthenticated",
+           __func__, authenticated ? "" : "not ");
+       return (authenticated);
+}
+
+int
+mm_user_key_allowed(struct passwd *pw, Key *key)
+{
+       return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
+}
+
+int
+mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
+    Key *key)
+{
+       return (mm_key_allowed(MM_HOSTKEY, user, host, key));
+}
+
+int
+mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
+    char *host, Key *key)
+{
+       int ret;
+
+       key->type = KEY_RSA; /* XXX hack for key_to_blob */
+       ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
+       key->type = KEY_RSA1;
+       return (ret);
+}
+
+int
+mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
+{
+       Buffer m;
+       u_char *blob;
+       u_int len;
+       int allowed = 0, have_forced = 0;
+
+       debug3("%s entering", __func__);
+
+       /* Convert the key to a blob and the pass it over */
+       if (!key_to_blob(key, &blob, &len))
+               return (0);
+
+       buffer_init(&m);
+       buffer_put_int(&m, type);
+       buffer_put_cstring(&m, user ? user : "");
+       buffer_put_cstring(&m, host ? host : "");
+       buffer_put_string(&m, blob, len);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
+
+       allowed = buffer_get_int(&m);
+
+       /* fake forced command */
+       auth_clear_options();
+       have_forced = buffer_get_int(&m);
+       forced_command = have_forced ? xstrdup("true") : NULL;
+
+       buffer_free(&m);
+
+       return (allowed);
+}
+
+/*
+ * This key verify needs to send the key type along, because the
+ * privileged parent makes the decision if the key is allowed
+ * for authentication.
+ */
+
+int
+mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+{
+       Buffer m;
+       u_char *blob;
+       u_int len;
+       int verified = 0;
+
+       debug3("%s entering", __func__);
+
+       /* Convert the key to a blob and the pass it over */
+       if (!key_to_blob(key, &blob, &len))
+               return (0);
+
+       buffer_init(&m);
+       buffer_put_string(&m, blob, len);
+       buffer_put_string(&m, sig, siglen);
+       buffer_put_string(&m, data, datalen);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
+
+       verified = buffer_get_int(&m);
+
+       buffer_free(&m);
+
+       return (verified);
+}
+
+/* Export key state after authentication */
+Newkeys *
+mm_newkeys_from_blob(u_char *blob, int blen)
+{
+       Buffer b;
+       u_int len;
+       Newkeys *newkey = NULL;
+       Enc *enc;
+       Mac *mac;
+       Comp *comp;
+
+       debug3("%s: %p(%d)", __func__, blob, blen);
+#ifdef DEBUG_PK
+       dump_base64(stderr, blob, blen);
+#endif
+       buffer_init(&b);
+       buffer_append(&b, blob, blen);
+
+       newkey = xmalloc(sizeof(*newkey));
+       enc = &newkey->enc;
+       mac = &newkey->mac;
+       comp = &newkey->comp;
+
+       /* Enc structure */
+       enc->name = buffer_get_string(&b, NULL);
+       buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
+       enc->enabled = buffer_get_int(&b);
+       enc->block_size = buffer_get_int(&b);
+       enc->key = buffer_get_string(&b, &enc->key_len);
+       enc->iv = buffer_get_string(&b, &len);
+       if (len != enc->block_size)
+               fatal("%s: bad ivlen: expected %u != %u", __func__,
+                   enc->block_size, len);
+
+       if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
+               fatal("%s: bad cipher name %s or pointer %p", __func__,
+                   enc->name, enc->cipher);
+
+       /* Mac structure */
+       mac->name = buffer_get_string(&b, NULL);
+       if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
+               fatal("%s: can not setup mac %s", __func__, mac->name);
+       mac->enabled = buffer_get_int(&b);
+       mac->key = buffer_get_string(&b, &len);
+       if (len > mac->key_len)
+               fatal("%s: bad mac key length: %u > %d", __func__, len,
+                   mac->key_len);
+       mac->key_len = len;
+
+       /* Comp structure */
+       comp->type = buffer_get_int(&b);
+       comp->enabled = buffer_get_int(&b);
+       comp->name = buffer_get_string(&b, NULL);
+
+       len = buffer_len(&b);
+       if (len != 0)
+               error("newkeys_from_blob: remaining bytes in blob %u", len);
+       buffer_free(&b);
+       return (newkey);
+}
+
+int
+mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
+{
+       Buffer b;
+       int len;
+       Enc *enc;
+       Mac *mac;
+       Comp *comp;
+       Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode);
+
+       debug3("%s: converting %p", __func__, newkey);
+
+       if (newkey == NULL) {
+               error("%s: newkey == NULL", __func__);
+               return 0;
+       }
+       enc = &newkey->enc;
+       mac = &newkey->mac;
+       comp = &newkey->comp;
+
+       buffer_init(&b);
+       /* Enc structure */
+       buffer_put_cstring(&b, enc->name);
+       /* The cipher struct is constant and shared, you export pointer */
+       buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
+       buffer_put_int(&b, enc->enabled);
+       buffer_put_int(&b, enc->block_size);
+       buffer_put_string(&b, enc->key, enc->key_len);
+       packet_get_keyiv(mode, enc->iv, enc->block_size);
+       buffer_put_string(&b, enc->iv, enc->block_size);
+
+       /* Mac structure */
+       buffer_put_cstring(&b, mac->name);
+       buffer_put_int(&b, mac->enabled);
+       buffer_put_string(&b, mac->key, mac->key_len);
+
+       /* Comp structure */
+       buffer_put_int(&b, comp->type);
+       buffer_put_int(&b, comp->enabled);
+       buffer_put_cstring(&b, comp->name);
+
+       len = buffer_len(&b);
+       if (lenp != NULL)
+               *lenp = len;
+       if (blobp != NULL) {
+               *blobp = xmalloc(len);
+               memcpy(*blobp, buffer_ptr(&b), len);
+       }
+       memset(buffer_ptr(&b), 0, len);
+       buffer_free(&b);
+       return len;
+}
+
+static void
+mm_send_kex(Buffer *m, Kex *kex)
+{
+       buffer_put_string(m, kex->session_id, kex->session_id_len);
+       buffer_put_int(m, kex->we_need);
+       buffer_put_int(m, kex->hostkey_type);
+       buffer_put_int(m, kex->kex_type);
+       buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
+       buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
+       buffer_put_int(m, kex->flags);
+       buffer_put_cstring(m, kex->client_version_string);
+       buffer_put_cstring(m, kex->server_version_string);
+}
+
+void
+mm_send_keystate(struct monitor *monitor)
+{
+       Buffer m, *input, *output;
+       u_char *blob, *p;
+       u_int bloblen, plen;
+       u_int32_t seqnr, packets;
+       u_int64_t blocks, bytes;
+
+       buffer_init(&m);
+
+       if (!compat20) {
+               u_char iv[24];
+               u_char *key;
+               u_int ivlen, keylen;
+
+               buffer_put_int(&m, packet_get_protocol_flags());
+
+               buffer_put_int(&m, packet_get_ssh1_cipher());
+
+               debug3("%s: Sending ssh1 KEY+IV", __func__);
+               keylen = packet_get_encryption_key(NULL);
+               key = xmalloc(keylen+1);        /* add 1 if keylen == 0 */
+               keylen = packet_get_encryption_key(key);
+               buffer_put_string(&m, key, keylen);
+               memset(key, 0, keylen);
+               xfree(key);
+
+               ivlen = packet_get_keyiv_len(MODE_OUT);
+               packet_get_keyiv(MODE_OUT, iv, ivlen);
+               buffer_put_string(&m, iv, ivlen);
+               ivlen = packet_get_keyiv_len(MODE_OUT);
+               packet_get_keyiv(MODE_IN, iv, ivlen);
+               buffer_put_string(&m, iv, ivlen);
+               goto skip;
+       } else {
+               /* Kex for rekeying */
+               mm_send_kex(&m, *monitor->m_pkex);
+       }
+
+       debug3("%s: Sending new keys: %p %p",
+           __func__, packet_get_newkeys(MODE_OUT),
+           packet_get_newkeys(MODE_IN));
+
+       /* Keys from Kex */
+       if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
+               fatal("%s: conversion of newkeys failed", __func__);
+
+       buffer_put_string(&m, blob, bloblen);
+       xfree(blob);
+
+       if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
+               fatal("%s: conversion of newkeys failed", __func__);
+
+       buffer_put_string(&m, blob, bloblen);
+       xfree(blob);
+
+       packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
+       buffer_put_int(&m, seqnr);
+       buffer_put_int64(&m, blocks);
+       buffer_put_int(&m, packets);
+       buffer_put_int64(&m, bytes);
+       packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
+       buffer_put_int(&m, seqnr);
+       buffer_put_int64(&m, blocks);
+       buffer_put_int(&m, packets);
+       buffer_put_int64(&m, bytes);
+
+       debug3("%s: New keys have been sent", __func__);
+ skip:
+       /* More key context */
+       plen = packet_get_keycontext(MODE_OUT, NULL);
+       p = xmalloc(plen+1);
+       packet_get_keycontext(MODE_OUT, p);
+       buffer_put_string(&m, p, plen);
+       xfree(p);
+
+       plen = packet_get_keycontext(MODE_IN, NULL);
+       p = xmalloc(plen+1);
+       packet_get_keycontext(MODE_IN, p);
+       buffer_put_string(&m, p, plen);
+       xfree(p);
+
+       /* Compression state */
+       debug3("%s: Sending compression state", __func__);
+       buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
+       buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
+
+       /* Network I/O buffers */
+       input = (Buffer *)packet_get_input();
+       output = (Buffer *)packet_get_output();
+       buffer_put_string(&m, buffer_ptr(input), buffer_len(input));
+       buffer_put_string(&m, buffer_ptr(output), buffer_len(output));
+
+       /* Roaming */
+       if (compat20) {
+               buffer_put_int64(&m, get_sent_bytes());
+               buffer_put_int64(&m, get_recv_bytes());
+       }
+
+       mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
+       debug3("%s: Finished sending state", __func__);
+
+       buffer_free(&m);
+}
+
+int
+mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
+{
+       Buffer m;
+       char *p, *msg;
+       int success = 0, tmp1 = -1, tmp2 = -1;
+
+       /* Kludge: ensure there are fds free to receive the pty/tty */
+       if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
+           (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
+               error("%s: cannot allocate fds for pty", __func__);
+               if (tmp1 > 0)
+                       close(tmp1);
+               if (tmp2 > 0)
+                       close(tmp2);
+               return 0;
+       }
+       close(tmp1);
+       close(tmp2);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
+
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: pty alloc failed", __func__);
+               buffer_free(&m);
+               return (0);
+       }
+       p = buffer_get_string(&m, NULL);
+       msg = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       strlcpy(namebuf, p, namebuflen); /* Possible truncation */
+       xfree(p);
+
+       buffer_append(&loginmsg, msg, strlen(msg));
+       xfree(msg);
+
+       if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
+           (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
+               fatal("%s: receive fds failed", __func__);
+
+       /* Success */
+       return (1);
+}
+
+void
+mm_session_pty_cleanup2(Session *s)
+{
+       Buffer m;
+
+       if (s->ttyfd == -1)
+               return;
+       buffer_init(&m);
+       buffer_put_cstring(&m, s->tty);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
+       buffer_free(&m);
+
+       /* closed dup'ed master */
+       if (s->ptymaster != -1 && close(s->ptymaster) < 0)
+               error("close(s->ptymaster/%d): %s",
+                   s->ptymaster, strerror(errno));
+
+       /* unlink pty from session */
+       s->ttyfd = -1;
+}
+
+#ifdef USE_PAM
+void
+mm_start_pam(Authctxt *authctxt)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+       if (!options.use_pam)
+               fatal("UsePAM=no, but ended up in %s anyway", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
+
+       buffer_free(&m);
+}
+
+u_int
+mm_do_pam_account(void)
+{
+       Buffer m;
+       u_int ret;
+       char *msg;
+
+       debug3("%s entering", __func__);
+       if (!options.use_pam)
+               fatal("UsePAM=no, but ended up in %s anyway", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_PAM_ACCOUNT, &m);
+       ret = buffer_get_int(&m);
+       msg = buffer_get_string(&m, NULL);
+       buffer_append(&loginmsg, msg, strlen(msg));
+       xfree(msg);
+
+       buffer_free(&m);
+
+       debug3("%s returning %d", __func__, ret);
+
+       return (ret);
+}
+
+void *
+mm_sshpam_init_ctx(Authctxt *authctxt)
+{
+       Buffer m;
+       int success;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       buffer_put_cstring(&m, authctxt->user);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: pam_init_ctx failed", __func__);
+               buffer_free(&m);
+               return (NULL);
+       }
+       buffer_free(&m);
+       return (authctxt);
+}
+
+int
+mm_sshpam_query(void *ctx, char **name, char **info,
+    u_int *num, char ***prompts, u_int **echo_on)
+{
+       Buffer m;
+       u_int i;
+       int ret;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
+       ret = buffer_get_int(&m);
+       debug3("%s: pam_query returned %d", __func__, ret);
+       *name = buffer_get_string(&m, NULL);
+       *info = buffer_get_string(&m, NULL);
+       *num = buffer_get_int(&m);
+       if (*num > PAM_MAX_NUM_MSG)
+               fatal("%s: recieved %u PAM messages, expected <= %u",
+                   __func__, *num, PAM_MAX_NUM_MSG);
+       *prompts = xcalloc((*num + 1), sizeof(char *));
+       *echo_on = xcalloc((*num + 1), sizeof(u_int));
+       for (i = 0; i < *num; ++i) {
+               (*prompts)[i] = buffer_get_string(&m, NULL);
+               (*echo_on)[i] = buffer_get_int(&m);
+       }
+       buffer_free(&m);
+       return (ret);
+}
+
+int
+mm_sshpam_respond(void *ctx, u_int num, char **resp)
+{
+       Buffer m;
+       u_int i;
+       int ret;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       buffer_put_int(&m, num);
+       for (i = 0; i < num; ++i)
+               buffer_put_cstring(&m, resp[i]);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
+       ret = buffer_get_int(&m);
+       debug3("%s: pam_respond returned %d", __func__, ret);
+       buffer_free(&m);
+       return (ret);
+}
+
+void
+mm_sshpam_free_ctx(void *ctxtp)
+{
+       Buffer m;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
+       buffer_free(&m);
+}
+#endif /* USE_PAM */
+
+/* Request process termination */
+
+void
+mm_terminate(void)
+{
+       Buffer m;
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
+       buffer_free(&m);
+}
+
+int
+mm_ssh1_session_key(BIGNUM *num)
+{
+       int rsafail;
+       Buffer m;
+
+       buffer_init(&m);
+       buffer_put_bignum2(&m, num);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
+
+       rsafail = buffer_get_int(&m);
+       buffer_get_bignum2(&m, num);
+
+       buffer_free(&m);
+
+       return (rsafail);
+}
+
+static void
+mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
+    char ***prompts, u_int **echo_on)
+{
+       *name = xstrdup("");
+       *infotxt = xstrdup("");
+       *numprompts = 1;
+       *prompts = xcalloc(*numprompts, sizeof(char *));
+       *echo_on = xcalloc(*numprompts, sizeof(u_int));
+       (*echo_on)[0] = 0;
+}
+
+int
+mm_bsdauth_query(void *ctx, char **name, char **infotxt,
+   u_int *numprompts, char ***prompts, u_int **echo_on)
+{
+       Buffer m;
+       u_int success;
+       char *challenge;
+
+       debug3("%s: entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
+           &m);
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: no challenge", __func__);
+               buffer_free(&m);
+               return (-1);
+       }
+
+       /* Get the challenge, and format the response */
+       challenge  = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
+       (*prompts)[0] = challenge;
+
+       debug3("%s: received challenge: %s", __func__, challenge);
+
+       return (0);
+}
+
+int
+mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
+{
+       Buffer m;
+       int authok;
+
+       debug3("%s: entering", __func__);
+       if (numresponses != 1)
+               return (-1);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, responses[0]);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_BSDAUTHRESPOND, &m);
+
+       authok = buffer_get_int(&m);
+       buffer_free(&m);
+
+       return ((authok == 0) ? -1 : 0);
+}
+
+#ifdef SKEY
+int
+mm_skey_query(void *ctx, char **name, char **infotxt,
+   u_int *numprompts, char ***prompts, u_int **echo_on)
+{
+       Buffer m;
+       u_int success;
+       char *challenge;
+
+       debug3("%s: entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
+           &m);
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: no challenge", __func__);
+               buffer_free(&m);
+               return (-1);
+       }
+
+       /* Get the challenge, and format the response */
+       challenge  = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       debug3("%s: received challenge: %s", __func__, challenge);
+
+       mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
+
+       xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
+       xfree(challenge);
+
+       return (0);
+}
+
+int
+mm_skey_respond(void *ctx, u_int numresponses, char **responses)
+{
+       Buffer m;
+       int authok;
+
+       debug3("%s: entering", __func__);
+       if (numresponses != 1)
+               return (-1);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, responses[0]);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_SKEYRESPOND, &m);
+
+       authok = buffer_get_int(&m);
+       buffer_free(&m);
+
+       return ((authok == 0) ? -1 : 0);
+}
+#endif /* SKEY */
+
+void
+mm_ssh1_session_id(u_char session_id[16])
+{
+       Buffer m;
+       int i;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       for (i = 0; i < 16; i++)
+               buffer_put_char(&m, session_id[i]);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
+       buffer_free(&m);
+}
+
+int
+mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+{
+       Buffer m;
+       Key *key;
+       u_char *blob;
+       u_int blen;
+       int allowed = 0, have_forced = 0;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_bignum2(&m, client_n);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
+
+       allowed = buffer_get_int(&m);
+
+       /* fake forced command */
+       auth_clear_options();
+       have_forced = buffer_get_int(&m);
+       forced_command = have_forced ? xstrdup("true") : NULL;
+
+       if (allowed && rkey != NULL) {
+               blob = buffer_get_string(&m, &blen);
+               if ((key = key_from_blob(blob, blen)) == NULL)
+                       fatal("%s: key_from_blob failed", __func__);
+               *rkey = key;
+               xfree(blob);
+       }
+       buffer_free(&m);
+
+       return (allowed);
+}
+
+BIGNUM *
+mm_auth_rsa_generate_challenge(Key *key)
+{
+       Buffer m;
+       BIGNUM *challenge;
+       u_char *blob;
+       u_int blen;
+
+       debug3("%s entering", __func__);
+
+       if ((challenge = BN_new()) == NULL)
+               fatal("%s: BN_new failed", __func__);
+
+       key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
+       if (key_to_blob(key, &blob, &blen) == 0)
+               fatal("%s: key_to_blob failed", __func__);
+       key->type = KEY_RSA1;
+
+       buffer_init(&m);
+       buffer_put_string(&m, blob, blen);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
+
+       buffer_get_bignum2(&m, challenge);
+       buffer_free(&m);
+
+       return (challenge);
+}
+
+int
+mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
+{
+       Buffer m;
+       u_char *blob;
+       u_int blen;
+       int success = 0;
+
+       debug3("%s entering", __func__);
+
+       key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
+       if (key_to_blob(key, &blob, &blen) == 0)
+               fatal("%s: key_to_blob failed", __func__);
+       key->type = KEY_RSA1;
+
+       buffer_init(&m);
+       buffer_put_string(&m, blob, blen);
+       buffer_put_string(&m, response, 16);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
+
+       success = buffer_get_int(&m);
+       buffer_free(&m);
+
+       return (success);
+}
+
+#ifdef SSH_AUDIT_EVENTS
+void
+mm_audit_event(ssh_audit_event_t event)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_int(&m, event);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
+       buffer_free(&m);
+}
+
+void
+mm_audit_run_command(const char *command)
+{
+       Buffer m;
+
+       debug3("%s entering command %s", __func__, command);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, command);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
+       buffer_free(&m);
+}
+#endif /* SSH_AUDIT_EVENTS */
+
+#ifdef GSSAPI
+OM_uint32
+mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
+{
+       Buffer m;
+       OM_uint32 major;
+
+       /* Client doesn't get to see the context */
+       *ctx = NULL;
+
+       buffer_init(&m);
+       buffer_put_string(&m, goid->elements, goid->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
+
+       major = buffer_get_int(&m);
+
+       buffer_free(&m);
+       return (major);
+}
+
+OM_uint32
+mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
+    gss_buffer_desc *out, OM_uint32 *flags)
+{
+       Buffer m;
+       OM_uint32 major;
+       u_int len;
+
+       buffer_init(&m);
+       buffer_put_string(&m, in->value, in->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
+
+       major = buffer_get_int(&m);
+       out->value = buffer_get_string(&m, &len);
+       out->length = len;
+       if (flags)
+               *flags = buffer_get_int(&m);
+
+       buffer_free(&m);
+
+       return (major);
+}
+
+OM_uint32
+mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+       Buffer m;
+       OM_uint32 major;
+
+       buffer_init(&m);
+       buffer_put_string(&m, gssbuf->value, gssbuf->length);
+       buffer_put_string(&m, gssmic->value, gssmic->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
+           &m);
+
+       major = buffer_get_int(&m);
+       buffer_free(&m);
+       return(major);
+}
+
+int
+mm_ssh_gssapi_userok(char *user)
+{
+       Buffer m;
+       int authenticated = 0;
+
+       buffer_init(&m);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
+                                 &m);
+
+       authenticated = buffer_get_int(&m);
+
+       buffer_free(&m);
+       debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
+       return (authenticated);
+}
+#endif /* GSSAPI */
+
+#ifdef JPAKE
+void
+mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
+    char **hash_scheme, char **salt)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_GET_PWDATA, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_GET_PWDATA, &m);
+
+       *hash_scheme = buffer_get_string(&m, NULL);
+       *salt = buffer_get_string(&m, NULL);
+
+       buffer_free(&m);
+}
+
+void
+mm_jpake_step1(struct modp_group *grp,
+    u_char **id, u_int *id_len,
+    BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
+    u_char **priv1_proof, u_int *priv1_proof_len,
+    u_char **priv2_proof, u_int *priv2_proof_len)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_STEP1, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_STEP1, &m);
+
+       if ((*priv1 = BN_new()) == NULL ||
+           (*priv2 = BN_new()) == NULL ||
+           (*g_priv1 = BN_new()) == NULL ||
+           (*g_priv2 = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       *id = buffer_get_string(&m, id_len);
+       /* priv1 and priv2 are, well, private */
+       buffer_get_bignum2(&m, *g_priv1);
+       buffer_get_bignum2(&m, *g_priv2);
+       *priv1_proof = buffer_get_string(&m, priv1_proof_len);
+       *priv2_proof = buffer_get_string(&m, priv2_proof_len);
+
+       buffer_free(&m);
+}
+
+void
+mm_jpake_step2(struct modp_group *grp, BIGNUM *s,
+    BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
+    const u_char *theirid, u_int theirid_len,
+    const u_char *myid, u_int myid_len,
+    const u_char *theirpub1_proof, u_int theirpub1_proof_len,
+    const u_char *theirpub2_proof, u_int theirpub2_proof_len,
+    BIGNUM **newpub,
+    u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       /* monitor already has all bignums except theirpub1, theirpub2 */
+       buffer_put_bignum2(&m, theirpub1);
+       buffer_put_bignum2(&m, theirpub2);
+       /* monitor already knows our id */
+       buffer_put_string(&m, theirid, theirid_len);
+       buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len);
+       buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len);
+
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_STEP2, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_STEP2, &m);
+
+       if ((*newpub = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       buffer_get_bignum2(&m, *newpub);
+       *newpub_exponent_proof = buffer_get_string(&m,
+           newpub_exponent_proof_len);
+
+       buffer_free(&m);
+}
+
+void
+mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
+    BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
+    BIGNUM *theirpub1, BIGNUM *theirpub2,
+    const u_char *my_id, u_int my_id_len,
+    const u_char *their_id, u_int their_id_len,
+    const u_char *sess_id, u_int sess_id_len,
+    const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
+    BIGNUM **k,
+    u_char **confirm_hash, u_int *confirm_hash_len)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       /* monitor already has all bignums except step2_val */
+       buffer_put_bignum2(&m, step2_val);
+       /* monitor already knows all the ids */
+       buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len);
+
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_KEY_CONFIRM, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_KEY_CONFIRM, &m);
+
+       /* 'k' is sensitive and stays in the monitor */
+       *confirm_hash = buffer_get_string(&m, confirm_hash_len);
+
+       buffer_free(&m);
+}
+
+int
+mm_jpake_check_confirm(const BIGNUM *k,
+    const u_char *peer_id, u_int peer_id_len,
+    const u_char *sess_id, u_int sess_id_len,
+    const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
+{
+       Buffer m;
+       int success = 0;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       /* k is dummy in slave, ignored */
+       /* monitor knows all the ids */
+       buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len);
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m);
+
+       success = buffer_get_int(&m);
+       buffer_free(&m);
+
+       debug3("%s: success = %d", __func__, success);
+       return success;
+}
+#endif /* JPAKE */
diff --git a/.pc/gssapi.patch/monitor_wrap.h b/.pc/gssapi.patch/monitor_wrap.h
new file mode 100644 (file)
index 0000000..0c7f2e3
--- /dev/null
@@ -0,0 +1,131 @@
+/* $OpenBSD: monitor_wrap.h,v 1.23 2011/06/17 21:44:31 djm Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MM_WRAP_H_
+#define _MM_WRAP_H_
+
+extern int use_privsep;
+#define PRIVSEP(x)     (use_privsep ? mm_##x : x)
+
+enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY};
+
+struct monitor;
+struct mm_master;
+struct Authctxt;
+
+void mm_log_handler(LogLevel, const char *, void *);
+int mm_is_monitor(void);
+DH *mm_choose_dh(int, int, int);
+int mm_key_sign(Key *, u_char **, u_int *, 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_key_allowed(enum mm_keytype, char *, char *, Key *);
+int mm_user_key_allowed(struct passwd *, Key *);
+int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
+int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
+int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
+int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
+int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
+BIGNUM *mm_auth_rsa_generate_challenge(Key *);
+
+#ifdef GSSAPI
+OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
+OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
+   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
+int mm_ssh_gssapi_userok(char *user);
+OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+#endif
+
+#ifdef USE_PAM
+void mm_start_pam(struct Authctxt *);
+u_int mm_do_pam_account(void);
+void *mm_sshpam_init_ctx(struct Authctxt *);
+int mm_sshpam_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_sshpam_respond(void *, u_int, char **);
+void mm_sshpam_free_ctx(void *);
+#endif
+
+#ifdef SSH_AUDIT_EVENTS
+#include "audit.h"
+void mm_audit_event(ssh_audit_event_t);
+void mm_audit_run_command(const char *);
+#endif
+
+struct Session;
+void mm_terminate(void);
+int mm_pty_allocate(int *, int *, char *, size_t);
+void mm_session_pty_cleanup2(struct Session *);
+
+/* SSHv1 interfaces */
+void mm_ssh1_session_id(u_char *);
+int mm_ssh1_session_key(BIGNUM *);
+
+/* Key export functions */
+struct Newkeys *mm_newkeys_from_blob(u_char *, int);
+int mm_newkeys_to_blob(int, u_char **, u_int *);
+
+void monitor_apply_keystate(struct monitor *);
+void mm_get_keystate(struct monitor *);
+void mm_send_keystate(struct monitor*);
+
+/* bsdauth */
+int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_bsdauth_respond(void *, u_int, char **);
+
+/* skey */
+int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_skey_respond(void *, u_int, char **);
+
+/* jpake */
+struct modp_group;
+void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **);
+void mm_jpake_step1(struct modp_group *, u_char **, u_int *,
+    BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **,
+    u_char **, u_int *, u_char **, u_int *);
+void mm_jpake_step2(struct modp_group *, BIGNUM *,
+    BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
+    const u_char *, u_int, const u_char *, u_int,
+    const u_char *, u_int, const u_char *, u_int,
+    BIGNUM **, u_char **, u_int *);
+void mm_jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *,
+    BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
+    const u_char *, u_int, const u_char *, u_int,
+    const u_char *, u_int, const u_char *, u_int,
+    BIGNUM **, u_char **, u_int *);
+int mm_jpake_check_confirm(const BIGNUM *,
+    const u_char *, u_int, const u_char *, u_int, const u_char *, u_int);
+
+
+/* zlib allocation hooks */
+
+void *mm_zalloc(struct mm_master *, u_int, u_int);
+void mm_zfree(struct mm_master *, void *);
+void mm_init_compression(struct mm_master *);
+
+#endif /* _MM_WRAP_H_ */
diff --git a/.pc/gssapi.patch/readconf.c b/.pc/gssapi.patch/readconf.c
new file mode 100644 (file)
index 0000000..91dfa56
--- /dev/null
@@ -0,0 +1,1473 @@
+/* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for reading the configuration files.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "compat.h"
+#include "cipher.h"
+#include "pathnames.h"
+#include "log.h"
+#include "key.h"
+#include "readconf.h"
+#include "match.h"
+#include "misc.h"
+#include "buffer.h"
+#include "kex.h"
+#include "mac.h"
+
+/* Format of the configuration file:
+
+   # Configuration data is parsed as follows:
+   #  1. command line options
+   #  2. user-specific file
+   #  3. system-wide file
+   # Any configuration value is only changed the first time it is set.
+   # Thus, host-specific definitions should be at the beginning of the
+   # configuration file, and defaults at the end.
+
+   # Host-specific declarations.  These may override anything above.  A single
+   # host may match multiple declarations; these are processed in the order
+   # that they are given in.
+
+   Host *.ngs.fi ngs.fi
+     User foo
+
+   Host fake.com
+     HostName another.host.name.real.org
+     User blaah
+     Port 34289
+     ForwardX11 no
+     ForwardAgent no
+
+   Host books.com
+     RemoteForward 9999 shadows.cs.hut.fi:9999
+     Cipher 3des
+
+   Host fascist.blob.com
+     Port 23123
+     User tylonen
+     PasswordAuthentication no
+
+   Host puukko.hut.fi
+     User t35124p
+     ProxyCommand ssh-proxy %h %p
+
+   Host *.fr
+     PublicKeyAuthentication no
+
+   Host *.su
+     Cipher none
+     PasswordAuthentication no
+
+   Host vpn.fake.com
+     Tunnel yes
+     TunnelDevice 3
+
+   # Defaults for various options
+   Host *
+     ForwardAgent no
+     ForwardX11 no
+     PasswordAuthentication yes
+     RSAAuthentication yes
+     RhostsRSAAuthentication yes
+     StrictHostKeyChecking yes
+     TcpKeepAlive no
+     IdentityFile ~/.ssh/identity
+     Port 22
+     EscapeChar ~
+
+*/
+
+/* Keyword tokens. */
+
+typedef enum {
+       oBadOption,
+       oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
+       oGatewayPorts, oExitOnForwardFailure,
+       oPasswordAuthentication, oRSAAuthentication,
+       oChallengeResponseAuthentication, oXAuthLocation,
+       oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
+       oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+       oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
+       oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
+       oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
+       oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
+       oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
+       oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
+       oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
+       oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
+       oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+       oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+       oSendEnv, oControlPath, oControlMaster, oControlPersist,
+       oHashKnownHosts,
+       oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
+       oKexAlgorithms, oIPQoS, oRequestTTY,
+       oDeprecated, oUnsupported
+} OpCodes;
+
+/* Textual representations of the tokens. */
+
+static struct {
+       const char *name;
+       OpCodes opcode;
+} keywords[] = {
+       { "forwardagent", oForwardAgent },
+       { "forwardx11", oForwardX11 },
+       { "forwardx11trusted", oForwardX11Trusted },
+       { "forwardx11timeout", oForwardX11Timeout },
+       { "exitonforwardfailure", oExitOnForwardFailure },
+       { "xauthlocation", oXAuthLocation },
+       { "gatewayports", oGatewayPorts },
+       { "useprivilegedport", oUsePrivilegedPort },
+       { "rhostsauthentication", oDeprecated },
+       { "passwordauthentication", oPasswordAuthentication },
+       { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
+       { "kbdinteractivedevices", oKbdInteractiveDevices },
+       { "rsaauthentication", oRSAAuthentication },
+       { "pubkeyauthentication", oPubkeyAuthentication },
+       { "dsaauthentication", oPubkeyAuthentication },             /* alias */
+       { "rhostsrsaauthentication", oRhostsRSAAuthentication },
+       { "hostbasedauthentication", oHostbasedAuthentication },
+       { "challengeresponseauthentication", oChallengeResponseAuthentication },
+       { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
+       { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
+       { "kerberosauthentication", oUnsupported },
+       { "kerberostgtpassing", oUnsupported },
+       { "afstokenpassing", oUnsupported },
+#if defined(GSSAPI)
+       { "gssapiauthentication", oGssAuthentication },
+       { "gssapidelegatecredentials", oGssDelegateCreds },
+#else
+       { "gssapiauthentication", oUnsupported },
+       { "gssapidelegatecredentials", oUnsupported },
+#endif
+       { "fallbacktorsh", oDeprecated },
+       { "usersh", oDeprecated },
+       { "identityfile", oIdentityFile },
+       { "identityfile2", oIdentityFile },                     /* obsolete */
+       { "identitiesonly", oIdentitiesOnly },
+       { "hostname", oHostName },
+       { "hostkeyalias", oHostKeyAlias },
+       { "proxycommand", oProxyCommand },
+       { "port", oPort },
+       { "cipher", oCipher },
+       { "ciphers", oCiphers },
+       { "macs", oMacs },
+       { "protocol", oProtocol },
+       { "remoteforward", oRemoteForward },
+       { "localforward", oLocalForward },
+       { "user", oUser },
+       { "host", oHost },
+       { "escapechar", oEscapeChar },
+       { "globalknownhostsfile", oGlobalKnownHostsFile },
+       { "globalknownhostsfile2", oDeprecated },
+       { "userknownhostsfile", oUserKnownHostsFile },
+       { "userknownhostsfile2", oDeprecated }, 
+       { "connectionattempts", oConnectionAttempts },
+       { "batchmode", oBatchMode },
+       { "checkhostip", oCheckHostIP },
+       { "stricthostkeychecking", oStrictHostKeyChecking },
+       { "compression", oCompression },
+       { "compressionlevel", oCompressionLevel },
+       { "tcpkeepalive", oTCPKeepAlive },
+       { "keepalive", oTCPKeepAlive },                         /* obsolete */
+       { "numberofpasswordprompts", oNumberOfPasswordPrompts },
+       { "loglevel", oLogLevel },
+       { "dynamicforward", oDynamicForward },
+       { "preferredauthentications", oPreferredAuthentications },
+       { "hostkeyalgorithms", oHostKeyAlgorithms },
+       { "bindaddress", oBindAddress },
+#ifdef ENABLE_PKCS11
+       { "smartcarddevice", oPKCS11Provider },
+       { "pkcs11provider", oPKCS11Provider },
+#else
+       { "smartcarddevice", oUnsupported },
+       { "pkcs11provider", oUnsupported },
+#endif
+       { "clearallforwardings", oClearAllForwardings },
+       { "enablesshkeysign", oEnableSSHKeysign },
+       { "verifyhostkeydns", oVerifyHostKeyDNS },
+       { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
+       { "rekeylimit", oRekeyLimit },
+       { "connecttimeout", oConnectTimeout },
+       { "addressfamily", oAddressFamily },
+       { "serveraliveinterval", oServerAliveInterval },
+       { "serveralivecountmax", oServerAliveCountMax },
+       { "sendenv", oSendEnv },
+       { "controlpath", oControlPath },
+       { "controlmaster", oControlMaster },
+       { "controlpersist", oControlPersist },
+       { "hashknownhosts", oHashKnownHosts },
+       { "tunnel", oTunnel },
+       { "tunneldevice", oTunnelDevice },
+       { "localcommand", oLocalCommand },
+       { "permitlocalcommand", oPermitLocalCommand },
+       { "visualhostkey", oVisualHostKey },
+       { "useroaming", oUseRoaming },
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication",
+           oZeroKnowledgePasswordAuthentication },
+#else
+       { "zeroknowledgepasswordauthentication", oUnsupported },
+#endif
+       { "kexalgorithms", oKexAlgorithms },
+       { "ipqos", oIPQoS },
+       { "requesttty", oRequestTTY },
+
+       { NULL, oBadOption }
+};
+
+/*
+ * Adds a local TCP/IP port forward to options.  Never returns if there is an
+ * error.
+ */
+
+void
+add_local_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+#ifndef NO_IPPORT_RESERVED_CONCEPT
+       extern uid_t original_real_uid;
+       if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
+               fatal("Privileged ports can only be forwarded by root.");
+#endif
+       options->local_forwards = xrealloc(options->local_forwards,
+           options->num_local_forwards + 1,
+           sizeof(*options->local_forwards));
+       fwd = &options->local_forwards[options->num_local_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+}
+
+/*
+ * Adds a remote TCP/IP port forward to options.  Never returns if there is
+ * an error.
+ */
+
+void
+add_remote_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+
+       options->remote_forwards = xrealloc(options->remote_forwards,
+           options->num_remote_forwards + 1,
+           sizeof(*options->remote_forwards));
+       fwd = &options->remote_forwards[options->num_remote_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+       fwd->allocated_port = 0;
+}
+
+static void
+clear_forwardings(Options *options)
+{
+       int i;
+
+       for (i = 0; i < options->num_local_forwards; i++) {
+               if (options->local_forwards[i].listen_host != NULL)
+                       xfree(options->local_forwards[i].listen_host);
+               xfree(options->local_forwards[i].connect_host);
+       }
+       if (options->num_local_forwards > 0) {
+               xfree(options->local_forwards);
+               options->local_forwards = NULL;
+       }
+       options->num_local_forwards = 0;
+       for (i = 0; i < options->num_remote_forwards; i++) {
+               if (options->remote_forwards[i].listen_host != NULL)
+                       xfree(options->remote_forwards[i].listen_host);
+               xfree(options->remote_forwards[i].connect_host);
+       }
+       if (options->num_remote_forwards > 0) {
+               xfree(options->remote_forwards);
+               options->remote_forwards = NULL;
+       }
+       options->num_remote_forwards = 0;
+       options->tun_open = SSH_TUNMODE_NO;
+}
+
+/*
+ * Returns the number of the token pointed to by cp or oBadOption.
+ */
+
+static OpCodes
+parse_token(const char *cp, const char *filename, int linenum)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0)
+                       return keywords[i].opcode;
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return oBadOption;
+}
+
+/*
+ * Processes a single option line as used in the configuration files. This
+ * only sets those values that have not already been set.
+ */
+#define WHITESPACE " \t\r\n"
+
+int
+process_config_line(Options *options, const char *host,
+                   char *line, const char *filename, int linenum,
+                   int *activep)
+{
+       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+       char **cpptr, fwdarg[256];
+       u_int *uintptr, max_entries = 0;
+       int negated, opcode, *intptr, value, value2, scale;
+       LogLevel *log_level_ptr;
+       long long orig, val64;
+       size_t len;
+       Forward fwd;
+
+       /* Strip trailing whitespace */
+       for (len = strlen(line) - 1; len > 0; len--) {
+               if (strchr(WHITESPACE, line[len]) == NULL)
+                       break;
+               line[len] = '\0';
+       }
+
+       s = line;
+       /* Get the keyword. (Each line is supposed to begin with a keyword). */
+       if ((keyword = strdelim(&s)) == NULL)
+               return 0;
+       /* Ignore leading whitespace. */
+       if (*keyword == '\0')
+               keyword = strdelim(&s);
+       if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
+               return 0;
+
+       opcode = parse_token(keyword, filename, linenum);
+
+       switch (opcode) {
+       case oBadOption:
+               /* don't panic, but count bad options */
+               return -1;
+               /* NOTREACHED */
+       case oConnectTimeout:
+               intptr = &options->connection_timeout;
+parse_time:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardAgent:
+               intptr = &options->forward_agent;
+parse_flag:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else
+                       fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardX11:
+               intptr = &options->forward_x11;
+               goto parse_flag;
+
+       case oForwardX11Trusted:
+               intptr = &options->forward_x11_trusted;
+               goto parse_flag;
+       
+       case oForwardX11Timeout:
+               intptr = &options->forward_x11_timeout;
+               goto parse_time;
+
+       case oGatewayPorts:
+               intptr = &options->gateway_ports;
+               goto parse_flag;
+
+       case oExitOnForwardFailure:
+               intptr = &options->exit_on_forward_failure;
+               goto parse_flag;
+
+       case oUsePrivilegedPort:
+               intptr = &options->use_privileged_port;
+               goto parse_flag;
+
+       case oPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case oZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveDevices:
+               charptr = &options->kbd_interactive_devices;
+               goto parse_string;
+
+       case oPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case oRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case oRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case oHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case oChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case oGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case oGssDelegateCreds:
+               intptr = &options->gss_deleg_creds;
+               goto parse_flag;
+
+       case oBatchMode:
+               intptr = &options->batch_mode;
+               goto parse_flag;
+
+       case oCheckHostIP:
+               intptr = &options->check_host_ip;
+               goto parse_flag;
+
+       case oVerifyHostKeyDNS:
+               intptr = &options->verify_host_key_dns;
+               goto parse_yesnoask;
+
+       case oStrictHostKeyChecking:
+               intptr = &options->strict_host_key_checking;
+parse_yesnoask:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no/ask argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "ask") == 0)
+                       value = 2;
+               else
+                       fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCompression:
+               intptr = &options->compression;
+               goto parse_flag;
+
+       case oTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case oNoHostAuthenticationForLocalhost:
+               intptr = &options->no_host_authentication_for_localhost;
+               goto parse_flag;
+
+       case oNumberOfPasswordPrompts:
+               intptr = &options->number_of_password_prompts;
+               goto parse_int;
+
+       case oCompressionLevel:
+               intptr = &options->compression_level;
+               goto parse_int;
+
+       case oRekeyLimit:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               orig = val64 = strtoll(arg, &endofnumber, 10);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               switch (toupper(*endofnumber)) {
+               case '\0':
+                       scale = 1;
+                       break;
+               case 'K':
+                       scale = 1<<10;
+                       break;
+               case 'M':
+                       scale = 1<<20;
+                       break;
+               case 'G':
+                       scale = 1<<30;
+                       break;
+               default:
+                       fatal("%.200s line %d: Invalid RekeyLimit suffix",
+                           filename, linenum);
+               }
+               val64 *= scale;
+               /* detect integer wrap and too-large limits */
+               if ((val64 / scale) != orig || val64 > UINT_MAX)
+                       fatal("%.200s line %d: RekeyLimit too large",
+                           filename, linenum);
+               if (val64 < 16)
+                       fatal("%.200s line %d: RekeyLimit too small",
+                           filename, linenum);
+               if (*activep && options->rekey_limit == -1)
+                       options->rekey_limit = (u_int32_t)val64;
+               break;
+
+       case oIdentityFile:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (*activep) {
+                       intptr = &options->num_identity_files;
+                       if (*intptr >= SSH_MAX_IDENTITY_FILES)
+                               fatal("%.200s line %d: Too many identity files specified (max %d).",
+                                   filename, linenum, SSH_MAX_IDENTITY_FILES);
+                       charptr = &options->identity_files[*intptr];
+                       *charptr = xstrdup(arg);
+                       *intptr = *intptr + 1;
+               }
+               break;
+
+       case oXAuthLocation:
+               charptr=&options->xauth_location;
+               goto parse_string;
+
+       case oUser:
+               charptr = &options->user;
+parse_string:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case oGlobalKnownHostsFile:
+               cpptr = (char **)&options->system_hostfiles;
+               uintptr = &options->num_system_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+parse_char_array:
+               if (*activep && *uintptr == 0) {
+                       while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                               if ((*uintptr) >= max_entries)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               cpptr[(*uintptr)++] = xstrdup(arg);
+                       }
+               }
+               return 0;
+
+       case oUserKnownHostsFile:
+               cpptr = (char **)&options->user_hostfiles;
+               uintptr = &options->num_user_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+               goto parse_char_array;
+
+       case oHostName:
+               charptr = &options->hostname;
+               goto parse_string;
+
+       case oHostKeyAlias:
+               charptr = &options->host_key_alias;
+               goto parse_string;
+
+       case oPreferredAuthentications:
+               charptr = &options->preferred_authentications;
+               goto parse_string;
+
+       case oBindAddress:
+               charptr = &options->bind_address;
+               goto parse_string;
+
+       case oPKCS11Provider:
+               charptr = &options->pkcs11_provider;
+               goto parse_string;
+
+       case oProxyCommand:
+               charptr = &options->proxy_command;
+parse_command:
+               if (s == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               len = strspn(s, WHITESPACE "=");
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(s + len);
+               return 0;
+
+       case oPort:
+               intptr = &options->port;
+parse_int:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+
+               /* Octal, decimal, or hex format? */
+               value = strtol(arg, &endofnumber, 0);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oConnectionAttempts:
+               intptr = &options->connection_attempts;
+               goto parse_int;
+
+       case oCipher:
+               intptr = &options->cipher;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = cipher_number(arg);
+               if (value == -1)
+                       fatal("%.200s line %d: Bad cipher '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCiphers:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case oMacs:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case oKexAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case oHostKeyAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!key_names_valid2(arg))
+                       fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->hostkeyalgorithms == NULL)
+                       options->hostkeyalgorithms = xstrdup(arg);
+               break;
+
+       case oProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%.200s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case oLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&s);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case oLocalForward:
+       case oRemoteForward:
+       case oDynamicForward:
+               arg = strdelim(&s);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%.200s line %d: Missing port argument.",
+                           filename, linenum);
+
+               if (opcode == oLocalForward ||
+                   opcode == oRemoteForward) {
+                       arg2 = strdelim(&s);
+                       if (arg2 == NULL || *arg2 == '\0')
+                               fatal("%.200s line %d: Missing target argument.",
+                                   filename, linenum);
+
+                       /* construct a string for parse_forward */
+                       snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
+               } else if (opcode == oDynamicForward) {
+                       strlcpy(fwdarg, arg, sizeof(fwdarg));
+               }
+
+               if (parse_forward(&fwd, fwdarg,
+                   opcode == oDynamicForward ? 1 : 0,
+                   opcode == oRemoteForward ? 1 : 0) == 0)
+                       fatal("%.200s line %d: Bad forwarding specification.",
+                           filename, linenum);
+
+               if (*activep) {
+                       if (opcode == oLocalForward ||
+                           opcode == oDynamicForward)
+                               add_local_forward(options, &fwd);
+                       else if (opcode == oRemoteForward)
+                               add_remote_forward(options, &fwd);
+               }
+               break;
+
+       case oClearAllForwardings:
+               intptr = &options->clear_forwardings;
+               goto parse_flag;
+
+       case oHost:
+               *activep = 0;
+               arg2 = NULL;
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       negated = *arg == '!';
+                       if (negated)
+                               arg++;
+                       if (match_pattern(host, arg)) {
+                               if (negated) {
+                                       debug("%.200s line %d: Skipping Host "
+                                           "block because of negated match "
+                                           "for %.100s", filename, linenum,
+                                           arg);
+                                       *activep = 0;
+                                       break;
+                               }
+                               if (!*activep)
+                                       arg2 = arg; /* logged below */
+                               *activep = 1;
+                       }
+               }
+               if (*activep)
+                       debug("%.200s line %d: Applying options for %.100s",
+                           filename, linenum, arg2);
+               /* Avoid garbage check below, as strdelim is done. */
+               return 0;
+
+       case oEscapeChar:
+               intptr = &options->escape_char;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] == '^' && arg[2] == 0 &&
+                   (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
+                       value = (u_char) arg[1] & 31;
+               else if (strlen(arg) == 1)
+                       value = (u_char) arg[0];
+               else if (strcmp(arg, "none") == 0)
+                       value = SSH_ESCAPECHAR_NONE;
+               else {
+                       fatal("%.200s line %d: Bad escape character.",
+                           filename, linenum);
+                       /* NOTREACHED */
+                       value = 0;      /* Avoid compiler warning. */
+               }
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oAddressFamily:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing address family.",
+                           filename, linenum);
+               intptr = &options->address_family;
+               if (strcasecmp(arg, "inet") == 0)
+                       value = AF_INET;
+               else if (strcasecmp(arg, "inet6") == 0)
+                       value = AF_INET6;
+               else if (strcasecmp(arg, "any") == 0)
+                       value = AF_UNSPEC;
+               else
+                       fatal("Unsupported AddressFamily \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oEnableSSHKeysign:
+               intptr = &options->enable_ssh_keysign;
+               goto parse_flag;
+
+       case oIdentitiesOnly:
+               intptr = &options->identities_only;
+               goto parse_flag;
+
+       case oServerAliveInterval:
+               intptr = &options->server_alive_interval;
+               goto parse_time;
+
+       case oServerAliveCountMax:
+               intptr = &options->server_alive_count_max;
+               goto parse_int;
+
+       case oSendEnv:
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (!*activep)
+                               continue;
+                       if (options->num_send_env >= MAX_SEND_ENV)
+                               fatal("%s line %d: too many send env.",
+                                   filename, linenum);
+                       options->send_env[options->num_send_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case oControlPath:
+               charptr = &options->control_path;
+               goto parse_string;
+
+       case oControlMaster:
+               intptr = &options->control_master;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlMaster argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = SSHCTL_MASTER_YES;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = SSHCTL_MASTER_NO;
+               else if (strcmp(arg, "auto") == 0)
+                       value = SSHCTL_MASTER_AUTO;
+               else if (strcmp(arg, "ask") == 0)
+                       value = SSHCTL_MASTER_ASK;
+               else if (strcmp(arg, "autoask") == 0)
+                       value = SSHCTL_MASTER_AUTO_ASK;
+               else
+                       fatal("%.200s line %d: Bad ControlMaster argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oControlPersist:
+               /* no/false/yes/true, or a time spec */
+               intptr = &options->control_persist;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlPersist"
+                           " argument.", filename, linenum);
+               value = 0;
+               value2 = 0;     /* timeout */
+               if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if ((value2 = convtime(arg)) >= 0)
+                       value = 1;
+               else
+                       fatal("%.200s line %d: Bad ControlPersist argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1) {
+                       *intptr = value;
+                       options->control_persist_timeout = value2;
+               }
+               break;
+
+       case oHashKnownHosts:
+               intptr = &options->hash_known_hosts;
+               goto parse_flag;
+
+       case oTunnel:
+               intptr = &options->tun_open;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcasecmp(arg, "ethernet") == 0)
+                       value = SSH_TUNMODE_ETHERNET;
+               else if (strcasecmp(arg, "point-to-point") == 0)
+                       value = SSH_TUNMODE_POINTOPOINT;
+               else if (strcasecmp(arg, "yes") == 0)
+                       value = SSH_TUNMODE_DEFAULT;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = SSH_TUNMODE_NO;
+               else
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*activep)
+                       *intptr = value;
+               break;
+
+       case oTunnelDevice:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = a2tun(arg, &value2);
+               if (value == SSH_TUNID_ERR)
+                       fatal("%.200s line %d: Bad tun device.", filename, linenum);
+               if (*activep) {
+                       options->tun_local = value;
+                       options->tun_remote = value2;
+               }
+               break;
+
+       case oLocalCommand:
+               charptr = &options->local_command;
+               goto parse_command;
+
+       case oPermitLocalCommand:
+               intptr = &options->permit_local_command;
+               goto parse_flag;
+
+       case oVisualHostKey:
+               intptr = &options->visual_host_key;
+               goto parse_flag;
+
+       case oIPQoS:
+               arg = strdelim(&s);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&s);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case oUseRoaming:
+               intptr = &options->use_roaming;
+               goto parse_flag;
+
+       case oRequestTTY:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               intptr = &options->request_tty;
+               if (strcasecmp(arg, "yes") == 0)
+                       value = REQUEST_TTY_YES;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = REQUEST_TTY_NO;
+               else if (strcasecmp(arg, "force") == 0)
+                       value = REQUEST_TTY_FORCE;
+               else if (strcasecmp(arg, "auto") == 0)
+                       value = REQUEST_TTY_AUTO;
+               else
+                       fatal("Unsupported RequestTTY \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oDeprecated:
+               debug("%s line %d: Deprecated option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       case oUnsupported:
+               error("%s line %d: Unsupported option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       default:
+               fatal("process_config_line: Unimplemented opcode %d", opcode);
+       }
+
+       /* Check that there is no garbage at end of line. */
+       if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+               fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       }
+       return 0;
+}
+
+
+/*
+ * Reads the config file and modifies the options accordingly.  Options
+ * should already be initialized before this call.  This never returns if
+ * there is an error.  If the file does not exist, this returns 0.
+ */
+
+int
+read_config_file(const char *filename, const char *host, Options *options,
+    int checkperm)
+{
+       FILE *f;
+       char line[1024];
+       int active, linenum;
+       int bad_options = 0;
+
+       if ((f = fopen(filename, "r")) == NULL)
+               return 0;
+
+       if (checkperm) {
+               struct stat sb;
+
+               if (fstat(fileno(f), &sb) == -1)
+                       fatal("fstat %s: %s", filename, strerror(errno));
+               if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
+                   (sb.st_mode & 022) != 0))
+                       fatal("Bad owner or permissions on %s", filename);
+       }
+
+       debug("Reading configuration data %.200s", filename);
+
+       /*
+        * Mark that we are now processing the options.  This flag is turned
+        * on/off by Host specifications.
+        */
+       active = 1;
+       linenum = 0;
+       while (fgets(line, sizeof(line), f)) {
+               /* Update line number counter. */
+               linenum++;
+               if (process_config_line(options, host, line, filename, linenum, &active) != 0)
+                       bad_options++;
+       }
+       fclose(f);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+       return 1;
+}
+
+/*
+ * Initializes options to special values that indicate that they have not yet
+ * been set.  Read_config_file will only set options with this value. Options
+ * are processed in the following order: command line, user config file,
+ * system config file.  Last, fill_default_options is called.
+ */
+
+void
+initialize_options(Options * options)
+{
+       memset(options, 'X', sizeof(*options));
+       options->forward_agent = -1;
+       options->forward_x11 = -1;
+       options->forward_x11_trusted = -1;
+       options->forward_x11_timeout = -1;
+       options->exit_on_forward_failure = -1;
+       options->xauth_location = NULL;
+       options->gateway_ports = -1;
+       options->use_privileged_port = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->gss_authentication = -1;
+       options->gss_deleg_creds = -1;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->kbd_interactive_devices = NULL;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->batch_mode = -1;
+       options->check_host_ip = -1;
+       options->strict_host_key_checking = -1;
+       options->compression = -1;
+       options->tcp_keep_alive = -1;
+       options->compression_level = -1;
+       options->port = -1;
+       options->address_family = -1;
+       options->connection_attempts = -1;
+       options->connection_timeout = -1;
+       options->number_of_password_prompts = -1;
+       options->cipher = -1;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->hostkeyalgorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->num_identity_files = 0;
+       options->hostname = NULL;
+       options->host_key_alias = NULL;
+       options->proxy_command = NULL;
+       options->user = NULL;
+       options->escape_char = -1;
+       options->num_system_hostfiles = 0;
+       options->num_user_hostfiles = 0;
+       options->local_forwards = NULL;
+       options->num_local_forwards = 0;
+       options->remote_forwards = NULL;
+       options->num_remote_forwards = 0;
+       options->clear_forwardings = -1;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->preferred_authentications = NULL;
+       options->bind_address = NULL;
+       options->pkcs11_provider = NULL;
+       options->enable_ssh_keysign = - 1;
+       options->no_host_authentication_for_localhost = - 1;
+       options->identities_only = - 1;
+       options->rekey_limit = - 1;
+       options->verify_host_key_dns = -1;
+       options->server_alive_interval = -1;
+       options->server_alive_count_max = -1;
+       options->num_send_env = 0;
+       options->control_path = NULL;
+       options->control_master = -1;
+       options->control_persist = -1;
+       options->control_persist_timeout = 0;
+       options->hash_known_hosts = -1;
+       options->tun_open = -1;
+       options->tun_local = -1;
+       options->tun_remote = -1;
+       options->local_command = NULL;
+       options->permit_local_command = -1;
+       options->use_roaming = -1;
+       options->visual_host_key = -1;
+       options->zero_knowledge_password_authentication = -1;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+       options->request_tty = -1;
+}
+
+/*
+ * Called after processing other sources of option data, this fills those
+ * options for which no value has been specified with their default values.
+ */
+
+void
+fill_default_options(Options * options)
+{
+       int len;
+
+       if (options->forward_agent == -1)
+               options->forward_agent = 0;
+       if (options->forward_x11 == -1)
+               options->forward_x11 = 0;
+       if (options->forward_x11_trusted == -1)
+               options->forward_x11_trusted = 0;
+       if (options->forward_x11_timeout == -1)
+               options->forward_x11_timeout = 1200;
+       if (options->exit_on_forward_failure == -1)
+               options->exit_on_forward_failure = 0;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->use_privileged_port == -1)
+               options->use_privileged_port = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_deleg_creds == -1)
+               options->gss_deleg_creds = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 1;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->batch_mode == -1)
+               options->batch_mode = 0;
+       if (options->check_host_ip == -1)
+               options->check_host_ip = 1;
+       if (options->strict_host_key_checking == -1)
+               options->strict_host_key_checking = 2;  /* 2 is default */
+       if (options->compression == -1)
+               options->compression = 0;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->compression_level == -1)
+               options->compression_level = 6;
+       if (options->port == -1)
+               options->port = 0;      /* Filled in ssh_connect. */
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (options->connection_attempts == -1)
+               options->connection_attempts = 1;
+       if (options->number_of_password_prompts == -1)
+               options->number_of_password_prompts = 3;
+       /* Selected in ssh_login(). */
+       if (options->cipher == -1)
+               options->cipher = SSH_CIPHER_NOT_SET;
+       /* options->ciphers, default set in myproposals.h */
+       /* options->macs, default set in myproposals.h */
+       /* options->kex_algorithms, default set in myproposals.h */
+       /* options->hostkeyalgorithms, default set in myproposals.h */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_identity_files == 0) {
+               if (options->protocol & SSH_PROTO_1) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
+               }
+               if (options->protocol & SSH_PROTO_2) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
+
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
+#ifdef OPENSSL_HAS_ECC
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
+#endif
+               }
+       }
+       if (options->escape_char == -1)
+               options->escape_char = '~';
+       if (options->num_system_hostfiles == 0) {
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
+       }
+       if (options->num_user_hostfiles == 0) {
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE);
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE2);
+       }
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->clear_forwardings == 1)
+               clear_forwardings(options);
+       if (options->no_host_authentication_for_localhost == - 1)
+               options->no_host_authentication_for_localhost = 0;
+       if (options->identities_only == -1)
+               options->identities_only = 0;
+       if (options->enable_ssh_keysign == -1)
+               options->enable_ssh_keysign = 0;
+       if (options->rekey_limit == -1)
+               options->rekey_limit = 0;
+       if (options->verify_host_key_dns == -1)
+               options->verify_host_key_dns = 0;
+       if (options->server_alive_interval == -1)
+               options->server_alive_interval = 0;
+       if (options->server_alive_count_max == -1)
+               options->server_alive_count_max = 3;
+       if (options->control_master == -1)
+               options->control_master = 0;
+       if (options->control_persist == -1) {
+               options->control_persist = 0;
+               options->control_persist_timeout = 0;
+       }
+       if (options->hash_known_hosts == -1)
+               options->hash_known_hosts = 0;
+       if (options->tun_open == -1)
+               options->tun_open = SSH_TUNMODE_NO;
+       if (options->tun_local == -1)
+               options->tun_local = SSH_TUNID_ANY;
+       if (options->tun_remote == -1)
+               options->tun_remote = SSH_TUNID_ANY;
+       if (options->permit_local_command == -1)
+               options->permit_local_command = 0;
+       if (options->use_roaming == -1)
+               options->use_roaming = 1;
+       if (options->visual_host_key == -1)
+               options->visual_host_key = 0;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+       if (options->request_tty == -1)
+               options->request_tty = REQUEST_TTY_AUTO;
+       /* options->local_command should not be set by default */
+       /* options->proxy_command should not be set by default */
+       /* options->user will be set in the main program if appropriate */
+       /* options->hostname will be set in the main program if appropriate */
+       /* options->host_key_alias should not be set by default */
+       /* options->preferred_authentications will be set in ssh */
+}
+
+/*
+ * parse_forward
+ * parses a string containing a port forwarding specification of the form:
+ *   dynamicfwd == 0
+ *     [listenhost:]listenport:connecthost:connectport
+ *   dynamicfwd == 1
+ *     [listenhost:]listenport
+ * returns number of arguments parsed or zero on error
+ */
+int
+parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
+{
+       int i;
+       char *p, *cp, *fwdarg[4];
+
+       memset(fwd, '\0', sizeof(*fwd));
+
+       cp = p = xstrdup(fwdspec);
+
+       /* skip leading spaces */
+       while (isspace(*cp))
+               cp++;
+
+       for (i = 0; i < 4; ++i)
+               if ((fwdarg[i] = hpdelim(&cp)) == NULL)
+                       break;
+
+       /* Check for trailing garbage */
+       if (cp != NULL)
+               i = 0;  /* failure */
+
+       switch (i) {
+       case 1:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 2:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 3:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
+               fwd->connect_port = a2port(fwdarg[2]);
+               break;
+
+       case 4:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
+               fwd->connect_port = a2port(fwdarg[3]);
+               break;
+       default:
+               i = 0; /* failure */
+       }
+
+       xfree(p);
+
+       if (dynamicfwd) {
+               if (!(i == 1 || i == 2))
+                       goto fail_free;
+       } else {
+               if (!(i == 3 || i == 4))
+                       goto fail_free;
+               if (fwd->connect_port <= 0)
+                       goto fail_free;
+       }
+
+       if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
+               goto fail_free;
+
+       if (fwd->connect_host != NULL &&
+           strlen(fwd->connect_host) >= NI_MAXHOST)
+               goto fail_free;
+       if (fwd->listen_host != NULL &&
+           strlen(fwd->listen_host) >= NI_MAXHOST)
+               goto fail_free;
+
+
+       return (i);
+
+ fail_free:
+       if (fwd->connect_host != NULL) {
+               xfree(fwd->connect_host);
+               fwd->connect_host = NULL;
+       }
+       if (fwd->listen_host != NULL) {
+               xfree(fwd->listen_host);
+               fwd->listen_host = NULL;
+       }
+       return (0);
+}
diff --git a/.pc/gssapi.patch/readconf.h b/.pc/gssapi.patch/readconf.h
new file mode 100644 (file)
index 0000000..5944cff
--- /dev/null
@@ -0,0 +1,161 @@
+/* $OpenBSD: readconf.h,v 1.90 2011/05/24 07:15:47 djm Exp $ */
+
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for reading the configuration file.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#ifndef READCONF_H
+#define READCONF_H
+
+/* Data structure for representing a forwarding request. */
+
+typedef struct {
+       char     *listen_host;          /* Host (address) to listen on. */
+       int       listen_port;          /* Port to forward. */
+       char     *connect_host;         /* Host to connect. */
+       int       connect_port;         /* Port to connect on connect_host. */
+       int       allocated_port;       /* Dynamically allocated listen port */
+}       Forward;
+/* Data structure for representing option data. */
+
+#define MAX_SEND_ENV           256
+#define SSH_MAX_HOSTS_FILES    256
+
+typedef struct {
+       int     forward_agent;  /* Forward authentication agent. */
+       int     forward_x11;    /* Forward X11 display. */
+       int     forward_x11_timeout;    /* Expiration for Cookies */
+       int     forward_x11_trusted;    /* Trust Forward X11 display. */
+       int     exit_on_forward_failure;        /* Exit if bind(2) fails for -L/-R */
+       char   *xauth_location; /* Location for xauth program */
+       int     gateway_ports;  /* Allow remote connects to forwarded ports. */
+       int     use_privileged_port;    /* Don't use privileged port if false. */
+       int     rhosts_rsa_authentication;      /* Try rhosts with RSA
+                                                * authentication. */
+       int     rsa_authentication;     /* Try RSA authentication. */
+       int     pubkey_authentication;  /* Try ssh2 pubkey authentication. */
+       int     hostbased_authentication;       /* ssh2's rhosts_rsa */
+       int     challenge_response_authentication;
+                                       /* Try S/Key or TIS, authentication. */
+       int     gss_authentication;     /* Try GSS authentication */
+       int     gss_deleg_creds;        /* Delegate GSS credentials */
+       int     password_authentication;        /* Try password
+                                                * authentication. */
+       int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
+       char    *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
+       int     zero_knowledge_password_authentication; /* Try jpake */
+       int     batch_mode;     /* Batch mode: do not ask for passwords. */
+       int     check_host_ip;  /* Also keep track of keys for IP address */
+       int     strict_host_key_checking;       /* Strict host key checking. */
+       int     compression;    /* Compress packets in both directions. */
+       int     compression_level;      /* Compression level 1 (fast) to 9
+                                        * (best). */
+       int     tcp_keep_alive; /* Set SO_KEEPALIVE. */
+       int     ip_qos_interactive;     /* IP ToS/DSCP/class for interactive */
+       int     ip_qos_bulk;            /* IP ToS/DSCP/class for bulk traffic */
+       LogLevel log_level;     /* Level for logging. */
+
+       int     port;           /* Port to connect. */
+       int     address_family;
+       int     connection_attempts;    /* Max attempts (seconds) before
+                                        * giving up */
+       int     connection_timeout;     /* Max time (seconds) before
+                                        * aborting connection attempt */
+       int     number_of_password_prompts;     /* Max number of password
+                                                * prompts. */
+       int     cipher;         /* Cipher to use. */
+       char   *ciphers;        /* SSH2 ciphers in order of preference. */
+       char   *macs;           /* SSH2 macs in order of preference. */
+       char   *hostkeyalgorithms;      /* SSH2 server key types in order of preference. */
+       char   *kex_algorithms; /* SSH2 kex methods in order of preference. */
+       int     protocol;       /* Protocol in order of preference. */
+       char   *hostname;       /* Real host to connect. */
+       char   *host_key_alias; /* hostname alias for .ssh/known_hosts */
+       char   *proxy_command;  /* Proxy command for connecting the host. */
+       char   *user;           /* User to log in as. */
+       int     escape_char;    /* Escape character; -2 = none */
+
+       u_int   num_system_hostfiles;   /* Paths for /etc/ssh/ssh_known_hosts */
+       char   *system_hostfiles[SSH_MAX_HOSTS_FILES];
+       u_int   num_user_hostfiles;     /* Path for $HOME/.ssh/known_hosts */
+       char   *user_hostfiles[SSH_MAX_HOSTS_FILES];
+       char   *preferred_authentications;
+       char   *bind_address;   /* local socket address for connection to sshd */
+       char   *pkcs11_provider; /* PKCS#11 provider */
+       int     verify_host_key_dns;    /* Verify host key using DNS */
+
+       int     num_identity_files;     /* Number of files for RSA/DSA identities. */
+       char   *identity_files[SSH_MAX_IDENTITY_FILES];
+       Key    *identity_keys[SSH_MAX_IDENTITY_FILES];
+
+       /* Local TCP/IP forward requests. */
+       int     num_local_forwards;
+       Forward *local_forwards;
+
+       /* Remote TCP/IP forward requests. */
+       int     num_remote_forwards;
+       Forward *remote_forwards;
+       int     clear_forwardings;
+
+       int     enable_ssh_keysign;
+       int64_t rekey_limit;
+       int     no_host_authentication_for_localhost;
+       int     identities_only;
+       int     server_alive_interval;
+       int     server_alive_count_max;
+
+       int     num_send_env;
+       char   *send_env[MAX_SEND_ENV];
+
+       char    *control_path;
+       int     control_master;
+       int     control_persist; /* ControlPersist flag */
+       int     control_persist_timeout; /* ControlPersist timeout (seconds) */
+
+       int     hash_known_hosts;
+
+       int     tun_open;       /* tun(4) */
+       int     tun_local;      /* force tun device (optional) */
+       int     tun_remote;     /* force tun device (optional) */
+
+       char    *local_command;
+       int     permit_local_command;
+       int     visual_host_key;
+
+       int     use_roaming;
+
+       int     request_tty;
+}       Options;
+
+#define SSHCTL_MASTER_NO       0
+#define SSHCTL_MASTER_YES      1
+#define SSHCTL_MASTER_AUTO     2
+#define SSHCTL_MASTER_ASK      3
+#define SSHCTL_MASTER_AUTO_ASK 4
+
+#define REQUEST_TTY_AUTO       0
+#define REQUEST_TTY_NO         1
+#define REQUEST_TTY_YES                2
+#define REQUEST_TTY_FORCE      3
+
+void     initialize_options(Options *);
+void     fill_default_options(Options *);
+int     read_config_file(const char *, const char *, Options *, int);
+int     parse_forward(Forward *, const char *, int, int);
+
+int
+process_config_line(Options *, const char *, char *, const char *, int, int *);
+
+void    add_local_forward(Options *, const Forward *);
+void    add_remote_forward(Options *, const Forward *);
+
+#endif                         /* READCONF_H */
diff --git a/.pc/gssapi.patch/servconf.c b/.pc/gssapi.patch/servconf.c
new file mode 100644 (file)
index 0000000..91986e5
--- /dev/null
@@ -0,0 +1,1798 @@
+/* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */
+/*
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "compat.h"
+#include "pathnames.h"
+#include "misc.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "mac.h"
+#include "match.h"
+#include "channels.h"
+#include "groupaccess.h"
+
+static void add_listen_addr(ServerOptions *, char *, int);
+static void add_one_listen_addr(ServerOptions *, char *, int);
+
+/* Use of privilege separation or not */
+extern int use_privsep;
+extern Buffer cfg;
+
+/* Initializes the server options to their default values. */
+
+void
+initialize_server_options(ServerOptions *options)
+{
+       memset(options, 0, sizeof(*options));
+
+       /* Portable-specific options */
+       options->use_pam = -1;
+
+       /* Standard Options */
+       options->num_ports = 0;
+       options->ports_from_cmdline = 0;
+       options->listen_addrs = NULL;
+       options->address_family = -1;
+       options->num_host_key_files = 0;
+       options->num_host_cert_files = 0;
+       options->pid_file = NULL;
+       options->server_key_bits = -1;
+       options->login_grace_time = -1;
+       options->key_regeneration_time = -1;
+       options->permit_root_login = PERMIT_NOT_SET;
+       options->ignore_rhosts = -1;
+       options->ignore_user_known_hosts = -1;
+       options->print_motd = -1;
+       options->print_lastlog = -1;
+       options->x11_forwarding = -1;
+       options->x11_display_offset = -1;
+       options->x11_use_localhost = -1;
+       options->xauth_location = NULL;
+       options->strict_modes = -1;
+       options->tcp_keep_alive = -1;
+       options->log_facility = SYSLOG_FACILITY_NOT_SET;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->hostbased_uses_name_from_packet_only = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->kerberos_authentication = -1;
+       options->kerberos_or_local_passwd = -1;
+       options->kerberos_ticket_cleanup = -1;
+       options->kerberos_get_afs_token = -1;
+       options->gss_authentication=-1;
+       options->gss_cleanup_creds = -1;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->permit_empty_passwd = -1;
+       options->permit_user_env = -1;
+       options->use_login = -1;
+       options->compression = -1;
+       options->allow_tcp_forwarding = -1;
+       options->allow_agent_forwarding = -1;
+       options->num_allow_users = 0;
+       options->num_deny_users = 0;
+       options->num_allow_groups = 0;
+       options->num_deny_groups = 0;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->gateway_ports = -1;
+       options->num_subsystems = 0;
+       options->max_startups_begin = -1;
+       options->max_startups_rate = -1;
+       options->max_startups = -1;
+       options->max_authtries = -1;
+       options->max_sessions = -1;
+       options->banner = NULL;
+       options->use_dns = -1;
+       options->client_alive_interval = -1;
+       options->client_alive_count_max = -1;
+       options->num_authkeys_files = 0;
+       options->num_accept_env = 0;
+       options->permit_tun = -1;
+       options->num_permitted_opens = -1;
+       options->adm_forced_command = NULL;
+       options->chroot_directory = NULL;
+       options->zero_knowledge_password_authentication = -1;
+       options->revoked_keys_file = NULL;
+       options->trusted_user_ca_keys = NULL;
+       options->authorized_principals_file = NULL;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+}
+
+void
+fill_default_server_options(ServerOptions *options)
+{
+       /* Portable-specific options */
+       if (options->use_pam == -1)
+               options->use_pam = 0;
+
+       /* Standard Options */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_host_key_files == 0) {
+               /* fill default hostkeys for protocols */
+               if (options->protocol & SSH_PROTO_1)
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_KEY_FILE;
+               if (options->protocol & SSH_PROTO_2) {
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_RSA_KEY_FILE;
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_DSA_KEY_FILE;
+#ifdef OPENSSL_HAS_ECC
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_ECDSA_KEY_FILE;
+#endif
+               }
+       }
+       /* No certificates by default */
+       if (options->num_ports == 0)
+               options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+       if (options->listen_addrs == NULL)
+               add_listen_addr(options, NULL, 0);
+       if (options->pid_file == NULL)
+               options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
+       if (options->server_key_bits == -1)
+               options->server_key_bits = 1024;
+       if (options->login_grace_time == -1)
+               options->login_grace_time = 120;
+       if (options->key_regeneration_time == -1)
+               options->key_regeneration_time = 3600;
+       if (options->permit_root_login == PERMIT_NOT_SET)
+               options->permit_root_login = PERMIT_YES;
+       if (options->ignore_rhosts == -1)
+               options->ignore_rhosts = 1;
+       if (options->ignore_user_known_hosts == -1)
+               options->ignore_user_known_hosts = 0;
+       if (options->print_motd == -1)
+               options->print_motd = 1;
+       if (options->print_lastlog == -1)
+               options->print_lastlog = 1;
+       if (options->x11_forwarding == -1)
+               options->x11_forwarding = 0;
+       if (options->x11_display_offset == -1)
+               options->x11_display_offset = 10;
+       if (options->x11_use_localhost == -1)
+               options->x11_use_localhost = 1;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->strict_modes == -1)
+               options->strict_modes = 1;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
+               options->log_facility = SYSLOG_FACILITY_AUTH;
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->hostbased_uses_name_from_packet_only == -1)
+               options->hostbased_uses_name_from_packet_only = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->kerberos_authentication == -1)
+               options->kerberos_authentication = 0;
+       if (options->kerberos_or_local_passwd == -1)
+               options->kerberos_or_local_passwd = 1;
+       if (options->kerberos_ticket_cleanup == -1)
+               options->kerberos_ticket_cleanup = 1;
+       if (options->kerberos_get_afs_token == -1)
+               options->kerberos_get_afs_token = 0;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_cleanup_creds == -1)
+               options->gss_cleanup_creds = 1;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 0;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->permit_empty_passwd == -1)
+               options->permit_empty_passwd = 0;
+       if (options->permit_user_env == -1)
+               options->permit_user_env = 0;
+       if (options->use_login == -1)
+               options->use_login = 0;
+       if (options->compression == -1)
+               options->compression = COMP_DELAYED;
+       if (options->allow_tcp_forwarding == -1)
+               options->allow_tcp_forwarding = 1;
+       if (options->allow_agent_forwarding == -1)
+               options->allow_agent_forwarding = 1;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->max_startups == -1)
+               options->max_startups = 10;
+       if (options->max_startups_rate == -1)
+               options->max_startups_rate = 100;               /* 100% */
+       if (options->max_startups_begin == -1)
+               options->max_startups_begin = options->max_startups;
+       if (options->max_authtries == -1)
+               options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
+       if (options->max_sessions == -1)
+               options->max_sessions = DEFAULT_SESSIONS_MAX;
+       if (options->use_dns == -1)
+               options->use_dns = 1;
+       if (options->client_alive_interval == -1)
+               options->client_alive_interval = 0;
+       if (options->client_alive_count_max == -1)
+               options->client_alive_count_max = 3;
+       if (options->num_authkeys_files == 0) {
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
+       }
+       if (options->permit_tun == -1)
+               options->permit_tun = SSH_TUNMODE_NO;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+
+       /* Turn privilege separation on by default */
+       if (use_privsep == -1)
+               use_privsep = PRIVSEP_ON;
+
+#ifndef HAVE_MMAP
+       if (use_privsep && options->compression == 1) {
+               error("This platform does not support both privilege "
+                   "separation and compression");
+               error("Compression disabled");
+               options->compression = 0;
+       }
+#endif
+
+}
+
+/* Keyword tokens. */
+typedef enum {
+       sBadOption,             /* == unknown option */
+       /* Portable-specific options */
+       sUsePAM,
+       /* Standard Options */
+       sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
+       sPermitRootLogin, sLogFacility, sLogLevel,
+       sRhostsRSAAuthentication, sRSAAuthentication,
+       sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
+       sKerberosGetAFSToken,
+       sKerberosTgtPassing, sChallengeResponseAuthentication,
+       sPasswordAuthentication, sKbdInteractiveAuthentication,
+       sListenAddress, sAddressFamily,
+       sPrintMotd, sPrintLastLog, sIgnoreRhosts,
+       sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+       sStrictModes, sEmptyPasswd, sTCPKeepAlive,
+       sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
+       sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+       sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
+       sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
+       sMaxStartups, sMaxAuthTries, sMaxSessions,
+       sBanner, sUseDNS, sHostbasedAuthentication,
+       sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
+       sClientAliveCountMax, sAuthorizedKeysFile,
+       sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+       sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
+       sUsePrivilegeSeparation, sAllowAgentForwarding,
+       sZeroKnowledgePasswordAuthentication, sHostCertificate,
+       sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+       sKexAlgorithms, sIPQoS,
+       sDeprecated, sUnsupported
+} ServerOpCodes;
+
+#define SSHCFG_GLOBAL  0x01    /* allowed in main section of sshd_config */
+#define SSHCFG_MATCH   0x02    /* allowed inside a Match section */
+#define SSHCFG_ALL     (SSHCFG_GLOBAL|SSHCFG_MATCH)
+
+/* Textual representation of the tokens. */
+static struct {
+       const char *name;
+       ServerOpCodes opcode;
+       u_int flags;
+} keywords[] = {
+       /* Portable-specific options */
+#ifdef USE_PAM
+       { "usepam", sUsePAM, SSHCFG_GLOBAL },
+#else
+       { "usepam", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
+       /* Standard Options */
+       { "port", sPort, SSHCFG_GLOBAL },
+       { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
+       { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },          /* alias */
+       { "pidfile", sPidFile, SSHCFG_GLOBAL },
+       { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
+       { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
+       { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
+       { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
+       { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
+       { "loglevel", sLogLevel, SSHCFG_GLOBAL },
+       { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
+       { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
+       { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
+       { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
+       { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
+       { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
+       { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
+#ifdef KRB5
+       { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
+       { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
+       { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
+#ifdef USE_AFS
+       { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
+#else
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+#endif
+#else
+       { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
+       { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
+       { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
+#ifdef GSSAPI
+       { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+#else
+       { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
+       { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
+       { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
+       { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
+#else
+       { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
+#endif
+       { "checkmail", sDeprecated, SSHCFG_GLOBAL },
+       { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
+       { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
+       { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
+       { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
+       { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
+       { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
+       { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
+       { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
+       { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
+       { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
+       { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
+       { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
+       { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
+       { "uselogin", sUseLogin, SSHCFG_GLOBAL },
+       { "compression", sCompression, SSHCFG_GLOBAL },
+       { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
+       { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },  /* obsolete alias */
+       { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
+       { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
+       { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
+       { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
+       { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
+       { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
+       { "ciphers", sCiphers, SSHCFG_GLOBAL },
+       { "macs", sMacs, SSHCFG_GLOBAL },
+       { "protocol", sProtocol, SSHCFG_GLOBAL },
+       { "gatewayports", sGatewayPorts, SSHCFG_ALL },
+       { "subsystem", sSubsystem, SSHCFG_GLOBAL },
+       { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
+       { "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
+       { "maxsessions", sMaxSessions, SSHCFG_ALL },
+       { "banner", sBanner, SSHCFG_ALL },
+       { "usedns", sUseDNS, SSHCFG_GLOBAL },
+       { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
+       { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
+       { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
+       { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
+       { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
+       { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
+       { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
+       { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
+       { "permittunnel", sPermitTunnel, SSHCFG_ALL },
+       { "match", sMatch, SSHCFG_ALL },
+       { "permitopen", sPermitOpen, SSHCFG_ALL },
+       { "forcecommand", sForceCommand, SSHCFG_ALL },
+       { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+       { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
+       { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
+       { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
+       { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
+       { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+       { "ipqos", sIPQoS, SSHCFG_ALL },
+       { NULL, sBadOption, 0 }
+};
+
+static struct {
+       int val;
+       char *text;
+} tunmode_desc[] = {
+       { SSH_TUNMODE_NO, "no" },
+       { SSH_TUNMODE_POINTOPOINT, "point-to-point" },
+       { SSH_TUNMODE_ETHERNET, "ethernet" },
+       { SSH_TUNMODE_YES, "yes" },
+       { -1, NULL }
+};
+
+/*
+ * Returns the number of the token pointed to by cp or sBadOption.
+ */
+
+static ServerOpCodes
+parse_token(const char *cp, const char *filename,
+           int linenum, u_int *flags)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0) {
+                       *flags = keywords[i].flags;
+                       return keywords[i].opcode;
+               }
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return sBadOption;
+}
+
+char *
+derelativise_path(const char *path)
+{
+       char *expanded, *ret, cwd[MAXPATHLEN];
+
+       expanded = tilde_expand_filename(path, getuid());
+       if (*expanded == '/')
+               return expanded;
+       if (getcwd(cwd, sizeof(cwd)) == NULL)
+               fatal("%s: getcwd: %s", __func__, strerror(errno));
+       xasprintf(&ret, "%s/%s", cwd, expanded);
+       xfree(expanded);
+       return ret;
+}
+
+static void
+add_listen_addr(ServerOptions *options, char *addr, int port)
+{
+       u_int i;
+
+       if (options->num_ports == 0)
+               options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (port == 0)
+               for (i = 0; i < options->num_ports; i++)
+                       add_one_listen_addr(options, addr, options->ports[i]);
+       else
+               add_one_listen_addr(options, addr, port);
+}
+
+static void
+add_one_listen_addr(ServerOptions *options, char *addr, int port)
+{
+       struct addrinfo hints, *ai, *aitop;
+       char strport[NI_MAXSERV];
+       int gaierr;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = options->address_family;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
+       snprintf(strport, sizeof strport, "%d", port);
+       if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
+               fatal("bad addr or host: %s (%s)",
+                   addr ? addr : "<NULL>",
+                   ssh_gai_strerror(gaierr));
+       for (ai = aitop; ai->ai_next; ai = ai->ai_next)
+               ;
+       ai->ai_next = options->listen_addrs;
+       options->listen_addrs = aitop;
+}
+
+/*
+ * The strategy for the Match blocks is that the config file is parsed twice.
+ *
+ * The first time is at startup.  activep is initialized to 1 and the
+ * directives in the global context are processed and acted on.  Hitting a
+ * Match directive unsets activep and the directives inside the block are
+ * checked for syntax only.
+ *
+ * The second time is after a connection has been established but before
+ * authentication.  activep is initialized to 2 and global config directives
+ * are ignored since they have already been processed.  If the criteria in a
+ * Match block is met, activep is set and the subsequent directives
+ * processed and actioned until EOF or another Match block unsets it.  Any
+ * options set are copied into the main server config.
+ *
+ * Potential additions/improvements:
+ *  - Add Match support for pre-kex directives, eg Protocol, Ciphers.
+ *
+ *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
+ *     Match Address 192.168.0.*
+ *             Tag trusted
+ *     Match Group wheel
+ *             Tag trusted
+ *     Match Tag trusted
+ *             AllowTcpForwarding yes
+ *             GatewayPorts clientspecified
+ *             [...]
+ *
+ *  - Add a PermittedChannelRequests directive
+ *     Match Group shell
+ *             PermittedChannelRequests session,forwarded-tcpip
+ */
+
+static int
+match_cfg_line_group(const char *grps, int line, const char *user)
+{
+       int result = 0;
+       struct passwd *pw;
+
+       if (user == NULL)
+               goto out;
+
+       if ((pw = getpwnam(user)) == NULL) {
+               debug("Can't match group at line %d because user %.100s does "
+                   "not exist", line, user);
+       } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+               debug("Can't Match group because user %.100s not in any group "
+                   "at line %d", user, line);
+       } else if (ga_match_pattern_list(grps) != 1) {
+               debug("user %.100s does not match group list %.100s at line %d",
+                   user, grps, line);
+       } else {
+               debug("user %.100s matched group list %.100s at line %d", user,
+                   grps, line);
+               result = 1;
+       }
+out:
+       ga_free();
+       return result;
+}
+
+static int
+match_cfg_line(char **condition, int line, const char *user, const char *host,
+    const char *address)
+{
+       int result = 1;
+       char *arg, *attrib, *cp = *condition;
+       size_t len;
+
+       if (user == NULL)
+               debug3("checking syntax for 'Match %s'", cp);
+       else
+               debug3("checking match for '%s' user %s host %s addr %s", cp,
+                   user ? user : "(null)", host ? host : "(null)",
+                   address ? address : "(null)");
+
+       while ((attrib = strdelim(&cp)) && *attrib != '\0') {
+               if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
+                       error("Missing Match criteria for %s", attrib);
+                       return -1;
+               }
+               len = strlen(arg);
+               if (strcasecmp(attrib, "user") == 0) {
+                       if (!user) {
+                               result = 0;
+                               continue;
+                       }
+                       if (match_pattern_list(user, arg, len, 0) != 1)
+                               result = 0;
+                       else
+                               debug("user %.100s matched 'User %.100s' at "
+                                   "line %d", user, arg, line);
+               } else if (strcasecmp(attrib, "group") == 0) {
+                       switch (match_cfg_line_group(arg, line, user)) {
+                       case -1:
+                               return -1;
+                       case 0:
+                               result = 0;
+                       }
+               } else if (strcasecmp(attrib, "host") == 0) {
+                       if (!host) {
+                               result = 0;
+                               continue;
+                       }
+                       if (match_hostname(host, arg, len) != 1)
+                               result = 0;
+                       else
+                               debug("connection from %.100s matched 'Host "
+                                   "%.100s' at line %d", host, arg, line);
+               } else if (strcasecmp(attrib, "address") == 0) {
+                       switch (addr_match_list(address, arg)) {
+                       case 1:
+                               debug("connection from %.100s matched 'Address "
+                                   "%.100s' at line %d", address, arg, line);
+                               break;
+                       case 0:
+                       case -1:
+                               result = 0;
+                               break;
+                       case -2:
+                               return -1;
+                       }
+               } else {
+                       error("Unsupported Match attribute %s", attrib);
+                       return -1;
+               }
+       }
+       if (user != NULL)
+               debug3("match %sfound", result ? "" : "not ");
+       *condition = cp;
+       return result;
+}
+
+#define WHITESPACE " \t\r\n"
+
+/* Multistate option parsing */
+struct multistate {
+       char *key;
+       int value;
+};
+static const struct multistate multistate_addressfamily[] = {
+       { "inet",                       AF_INET },
+       { "inet6",                      AF_INET6 },
+       { "any",                        AF_UNSPEC },
+       { NULL, -1 }
+};
+static const struct multistate multistate_permitrootlogin[] = {
+       { "without-password",           PERMIT_NO_PASSWD },
+       { "forced-commands-only",       PERMIT_FORCED_ONLY },
+       { "yes",                        PERMIT_YES },
+       { "no",                         PERMIT_NO },
+       { NULL, -1 }
+};
+static const struct multistate multistate_compression[] = {
+       { "delayed",                    COMP_DELAYED },
+       { "yes",                        COMP_ZLIB },
+       { "no",                         COMP_NONE },
+       { NULL, -1 }
+};
+static const struct multistate multistate_gatewayports[] = {
+       { "clientspecified",            2 },
+       { "yes",                        1 },
+       { "no",                         0 },
+       { NULL, -1 }
+};
+static const struct multistate multistate_privsep[] = {
+       { "sandbox",                    PRIVSEP_SANDBOX },
+       { "yes",                        PRIVSEP_ON },
+       { "no",                         PRIVSEP_OFF },
+       { NULL, -1 }
+};
+
+int
+process_server_config_line(ServerOptions *options, char *line,
+    const char *filename, int linenum, int *activep, const char *user,
+    const char *host, const char *address)
+{
+       char *cp, **charptr, *arg, *p;
+       int cmdline = 0, *intptr, value, value2, n;
+       SyslogFacility *log_facility_ptr;
+       LogLevel *log_level_ptr;
+       ServerOpCodes opcode;
+       int port;
+       u_int i, flags = 0;
+       size_t len;
+       const struct multistate *multistate_ptr;
+
+       cp = line;
+       if ((arg = strdelim(&cp)) == NULL)
+               return 0;
+       /* Ignore leading whitespace */
+       if (*arg == '\0')
+               arg = strdelim(&cp);
+       if (!arg || !*arg || *arg == '#')
+               return 0;
+       intptr = NULL;
+       charptr = NULL;
+       opcode = parse_token(arg, filename, linenum, &flags);
+
+       if (activep == NULL) { /* We are processing a command line directive */
+               cmdline = 1;
+               activep = &cmdline;
+       }
+       if (*activep && opcode != sMatch)
+               debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
+       if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
+               if (user == NULL) {
+                       fatal("%s line %d: Directive '%s' is not allowed "
+                           "within a Match block", filename, linenum, arg);
+               } else { /* this is a directive we have already processed */
+                       while (arg)
+                               arg = strdelim(&cp);
+                       return 0;
+               }
+       }
+
+       switch (opcode) {
+       /* Portable-specific options */
+       case sUsePAM:
+               intptr = &options->use_pam;
+               goto parse_flag;
+
+       /* Standard Options */
+       case sBadOption:
+               return -1;
+       case sPort:
+               /* ignore ports from configfile if cmdline specifies ports */
+               if (options->ports_from_cmdline)
+                       return 0;
+               if (options->listen_addrs != NULL)
+                       fatal("%s line %d: ports must be specified before "
+                           "ListenAddress.", filename, linenum);
+               if (options->num_ports >= MAX_PORTS)
+                       fatal("%s line %d: too many ports.",
+                           filename, linenum);
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing port number.",
+                           filename, linenum);
+               options->ports[options->num_ports++] = a2port(arg);
+               if (options->ports[options->num_ports-1] <= 0)
+                       fatal("%s line %d: Badly formatted port number.",
+                           filename, linenum);
+               break;
+
+       case sServerKeyBits:
+               intptr = &options->server_key_bits;
+ parse_int:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing integer value.",
+                           filename, linenum);
+               value = atoi(arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sLoginGraceTime:
+               intptr = &options->login_grace_time;
+ parse_time:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sKeyRegenerationTime:
+               intptr = &options->key_regeneration_time;
+               goto parse_time;
+
+       case sListenAddress:
+               arg = strdelim(&cp);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%s line %d: missing address",
+                           filename, linenum);
+               /* check for bare IPv6 address: no "[]" and 2 or more ":" */
+               if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
+                   && strchr(p+1, ':') != NULL) {
+                       add_listen_addr(options, arg, 0);
+                       break;
+               }
+               p = hpdelim(&arg);
+               if (p == NULL)
+                       fatal("%s line %d: bad address:port usage",
+                           filename, linenum);
+               p = cleanhostname(p);
+               if (arg == NULL)
+                       port = 0;
+               else if ((port = a2port(arg)) <= 0)
+                       fatal("%s line %d: bad port number", filename, linenum);
+
+               add_listen_addr(options, p, port);
+
+               break;
+
+       case sAddressFamily:
+               intptr = &options->address_family;
+               multistate_ptr = multistate_addressfamily;
+               if (options->listen_addrs != NULL)
+                       fatal("%s line %d: address family must be specified "
+                           "before ListenAddress.", filename, linenum);
+ parse_multistate:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               value = -1;
+               for (i = 0; multistate_ptr[i].key != NULL; i++) {
+                       if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
+                               value = multistate_ptr[i].value;
+                               break;
+                       }
+               }
+               if (value == -1)
+                       fatal("%s line %d: unsupported option \"%s\".",
+                           filename, linenum, arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sHostKeyFile:
+               intptr = &options->num_host_key_files;
+               if (*intptr >= MAX_HOSTKEYS)
+                       fatal("%s line %d: too many host keys specified (max %d).",
+                           filename, linenum, MAX_HOSTKEYS);
+               charptr = &options->host_key_files[*intptr];
+ parse_filename:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL) {
+                       *charptr = derelativise_path(arg);
+                       /* increase optional counter */
+                       if (intptr != NULL)
+                               *intptr = *intptr + 1;
+               }
+               break;
+
+       case sHostCertificate:
+               intptr = &options->num_host_cert_files;
+               if (*intptr >= MAX_HOSTKEYS)
+                       fatal("%s line %d: too many host certificates "
+                           "specified (max %d).", filename, linenum,
+                           MAX_HOSTCERTS);
+               charptr = &options->host_cert_files[*intptr];
+               goto parse_filename;
+               break;
+
+       case sPidFile:
+               charptr = &options->pid_file;
+               goto parse_filename;
+
+       case sPermitRootLogin:
+               intptr = &options->permit_root_login;
+               multistate_ptr = multistate_permitrootlogin;
+               goto parse_multistate;
+
+       case sIgnoreRhosts:
+               intptr = &options->ignore_rhosts;
+ parse_flag:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing yes/no argument.",
+                           filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcmp(arg, "yes") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0)
+                       value = 0;
+               else
+                       fatal("%s line %d: Bad yes/no argument: %s",
+                               filename, linenum, arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sIgnoreUserKnownHosts:
+               intptr = &options->ignore_user_known_hosts;
+               goto parse_flag;
+
+       case sRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case sHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case sHostbasedUsesNameFromPacketOnly:
+               intptr = &options->hostbased_uses_name_from_packet_only;
+               goto parse_flag;
+
+       case sRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case sPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case sKerberosAuthentication:
+               intptr = &options->kerberos_authentication;
+               goto parse_flag;
+
+       case sKerberosOrLocalPasswd:
+               intptr = &options->kerberos_or_local_passwd;
+               goto parse_flag;
+
+       case sKerberosTicketCleanup:
+               intptr = &options->kerberos_ticket_cleanup;
+               goto parse_flag;
+
+       case sKerberosGetAFSToken:
+               intptr = &options->kerberos_get_afs_token;
+               goto parse_flag;
+
+       case sGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case sGssCleanupCreds:
+               intptr = &options->gss_cleanup_creds;
+               goto parse_flag;
+
+       case sPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case sZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case sKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case sChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case sPrintMotd:
+               intptr = &options->print_motd;
+               goto parse_flag;
+
+       case sPrintLastLog:
+               intptr = &options->print_lastlog;
+               goto parse_flag;
+
+       case sX11Forwarding:
+               intptr = &options->x11_forwarding;
+               goto parse_flag;
+
+       case sX11DisplayOffset:
+               intptr = &options->x11_display_offset;
+               goto parse_int;
+
+       case sX11UseLocalhost:
+               intptr = &options->x11_use_localhost;
+               goto parse_flag;
+
+       case sXAuthLocation:
+               charptr = &options->xauth_location;
+               goto parse_filename;
+
+       case sStrictModes:
+               intptr = &options->strict_modes;
+               goto parse_flag;
+
+       case sTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case sEmptyPasswd:
+               intptr = &options->permit_empty_passwd;
+               goto parse_flag;
+
+       case sPermitUserEnvironment:
+               intptr = &options->permit_user_env;
+               goto parse_flag;
+
+       case sUseLogin:
+               intptr = &options->use_login;
+               goto parse_flag;
+
+       case sCompression:
+               intptr = &options->compression;
+               multistate_ptr = multistate_compression;
+               goto parse_multistate;
+
+       case sGatewayPorts:
+               intptr = &options->gateway_ports;
+               multistate_ptr = multistate_gatewayports;
+               goto parse_multistate;
+
+       case sUseDNS:
+               intptr = &options->use_dns;
+               goto parse_flag;
+
+       case sLogFacility:
+               log_facility_ptr = &options->log_facility;
+               arg = strdelim(&cp);
+               value = log_facility_number(arg);
+               if (value == SYSLOG_FACILITY_NOT_SET)
+                       fatal("%.200s line %d: unsupported log facility '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*log_facility_ptr == -1)
+                       *log_facility_ptr = (SyslogFacility) value;
+               break;
+
+       case sLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&cp);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*log_level_ptr == -1)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case sAllowTcpForwarding:
+               intptr = &options->allow_tcp_forwarding;
+               goto parse_flag;
+
+       case sAllowAgentForwarding:
+               intptr = &options->allow_agent_forwarding;
+               goto parse_flag;
+
+       case sUsePrivilegeSeparation:
+               intptr = &use_privsep;
+               multistate_ptr = multistate_privsep;
+               goto parse_multistate;
+
+       case sAllowUsers:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_allow_users >= MAX_ALLOW_USERS)
+                               fatal("%s line %d: too many allow users.",
+                                   filename, linenum);
+                       options->allow_users[options->num_allow_users++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sDenyUsers:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_deny_users >= MAX_DENY_USERS)
+                               fatal("%s line %d: too many deny users.",
+                                   filename, linenum);
+                       options->deny_users[options->num_deny_users++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sAllowGroups:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
+                               fatal("%s line %d: too many allow groups.",
+                                   filename, linenum);
+                       options->allow_groups[options->num_allow_groups++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sDenyGroups:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_deny_groups >= MAX_DENY_GROUPS)
+                               fatal("%s line %d: too many deny groups.",
+                                   filename, linenum);
+                       options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
+               }
+               break;
+
+       case sCiphers:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case sMacs:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%s line %d: Bad SSH2 mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case sKexAlgorithms:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case sProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case sSubsystem:
+               if (options->num_subsystems >= MAX_SUBSYSTEMS) {
+                       fatal("%s line %d: too many subsystems defined.",
+                           filename, linenum);
+               }
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing subsystem name.",
+                           filename, linenum);
+               if (!*activep) {
+                       arg = strdelim(&cp);
+                       break;
+               }
+               for (i = 0; i < options->num_subsystems; i++)
+                       if (strcmp(arg, options->subsystem_name[i]) == 0)
+                               fatal("%s line %d: Subsystem '%s' already defined.",
+                                   filename, linenum, arg);
+               options->subsystem_name[options->num_subsystems] = xstrdup(arg);
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing subsystem command.",
+                           filename, linenum);
+               options->subsystem_command[options->num_subsystems] = xstrdup(arg);
+
+               /* Collect arguments (separate to executable) */
+               p = xstrdup(arg);
+               len = strlen(p) + 1;
+               while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
+                       len += 1 + strlen(arg);
+                       p = xrealloc(p, 1, len);
+                       strlcat(p, " ", len);
+                       strlcat(p, arg, len);
+               }
+               options->subsystem_args[options->num_subsystems] = p;
+               options->num_subsystems++;
+               break;
+
+       case sMaxStartups:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing MaxStartups spec.",
+                           filename, linenum);
+               if ((n = sscanf(arg, "%d:%d:%d",
+                   &options->max_startups_begin,
+                   &options->max_startups_rate,
+                   &options->max_startups)) == 3) {
+                       if (options->max_startups_begin >
+                           options->max_startups ||
+                           options->max_startups_rate > 100 ||
+                           options->max_startups_rate < 1)
+                               fatal("%s line %d: Illegal MaxStartups spec.",
+                                   filename, linenum);
+               } else if (n != 1)
+                       fatal("%s line %d: Illegal MaxStartups spec.",
+                           filename, linenum);
+               else
+                       options->max_startups = options->max_startups_begin;
+               break;
+
+       case sMaxAuthTries:
+               intptr = &options->max_authtries;
+               goto parse_int;
+
+       case sMaxSessions:
+               intptr = &options->max_sessions;
+               goto parse_int;
+
+       case sBanner:
+               charptr = &options->banner;
+               goto parse_filename;
+
+       /*
+        * These options can contain %X options expanded at
+        * connect time, so that you can specify paths like:
+        *
+        * AuthorizedKeysFile   /etc/ssh_keys/%u
+        */
+       case sAuthorizedKeysFile:
+               if (*activep && options->num_authkeys_files == 0) {
+                       while ((arg = strdelim(&cp)) && *arg != '\0') {
+                               if (options->num_authkeys_files >=
+                                   MAX_AUTHKEYS_FILES)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               options->authorized_keys_files[
+                                   options->num_authkeys_files++] =
+                                   tilde_expand_filename(arg, getuid());
+                       }
+               }
+               return 0;
+
+       case sAuthorizedPrincipalsFile:
+               charptr = &options->authorized_principals_file;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL) {
+                       *charptr = tilde_expand_filename(arg, getuid());
+                       /* increase optional counter */
+                       if (intptr != NULL)
+                               *intptr = *intptr + 1;
+               }
+               break;
+
+       case sClientAliveInterval:
+               intptr = &options->client_alive_interval;
+               goto parse_time;
+
+       case sClientAliveCountMax:
+               intptr = &options->client_alive_count_max;
+               goto parse_int;
+
+       case sAcceptEnv:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (options->num_accept_env >= MAX_ACCEPT_ENV)
+                               fatal("%s line %d: too many allow env.",
+                                   filename, linenum);
+                       if (!*activep)
+                               break;
+                       options->accept_env[options->num_accept_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sPermitTunnel:
+               intptr = &options->permit_tun;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = -1;
+               for (i = 0; tunmode_desc[i].val != -1; i++)
+                       if (strcmp(tunmode_desc[i].text, arg) == 0) {
+                               value = tunmode_desc[i].val;
+                               break;
+                       }
+               if (value == -1)
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sMatch:
+               if (cmdline)
+                       fatal("Match directive not supported as a command-line "
+                          "option");
+               value = match_cfg_line(&cp, linenum, user, host, address);
+               if (value < 0)
+                       fatal("%s line %d: Bad Match condition", filename,
+                           linenum);
+               *activep = value;
+               break;
+
+       case sPermitOpen:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing PermitOpen specification",
+                           filename, linenum);
+               n = options->num_permitted_opens;       /* modified later */
+               if (strcmp(arg, "any") == 0) {
+                       if (*activep && n == -1) {
+                               channel_clear_adm_permitted_opens();
+                               options->num_permitted_opens = 0;
+                       }
+                       break;
+               }
+               if (*activep && n == -1)
+                       channel_clear_adm_permitted_opens();
+               for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
+                       p = hpdelim(&arg);
+                       if (p == NULL)
+                               fatal("%s line %d: missing host in PermitOpen",
+                                   filename, linenum);
+                       p = cleanhostname(p);
+                       if (arg == NULL || (port = a2port(arg)) <= 0)
+                               fatal("%s line %d: bad port number in "
+                                   "PermitOpen", filename, linenum);
+                       if (*activep && n == -1)
+                               options->num_permitted_opens =
+                                   channel_add_adm_permitted_opens(p, port);
+               }
+               break;
+
+       case sForceCommand:
+               if (cp == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename,
+                           linenum);
+               len = strspn(cp, WHITESPACE);
+               if (*activep && options->adm_forced_command == NULL)
+                       options->adm_forced_command = xstrdup(cp + len);
+               return 0;
+
+       case sChrootDirectory:
+               charptr = &options->chroot_directory;
+
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case sTrustedUserCAKeys:
+               charptr = &options->trusted_user_ca_keys;
+               goto parse_filename;
+
+       case sRevokedKeys:
+               charptr = &options->revoked_keys_file;
+               goto parse_filename;
+
+       case sIPQoS:
+               arg = strdelim(&cp);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&cp);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case sDeprecated:
+               logit("%s line %d: Deprecated option %s",
+                   filename, linenum, arg);
+               while (arg)
+                   arg = strdelim(&cp);
+               break;
+
+       case sUnsupported:
+               logit("%s line %d: Unsupported option %s",
+                   filename, linenum, arg);
+               while (arg)
+                   arg = strdelim(&cp);
+               break;
+
+       default:
+               fatal("%s line %d: Missing handler for opcode %s (%d)",
+                   filename, linenum, arg, opcode);
+       }
+       if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
+               fatal("%s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       return 0;
+}
+
+/* Reads the server configuration file. */
+
+void
+load_server_config(const char *filename, Buffer *conf)
+{
+       char line[1024], *cp;
+       FILE *f;
+
+       debug2("%s: filename %s", __func__, filename);
+       if ((f = fopen(filename, "r")) == NULL) {
+               perror(filename);
+               exit(1);
+       }
+       buffer_clear(conf);
+       while (fgets(line, sizeof(line), f)) {
+               /*
+                * Trim out comments and strip whitespace
+                * NB - preserve newlines, they are needed to reproduce
+                * line numbers later for error messages
+                */
+               if ((cp = strchr(line, '#')) != NULL)
+                       memcpy(cp, "\n", 2);
+               cp = line + strspn(line, " \t\r");
+
+               buffer_append(conf, cp, strlen(cp));
+       }
+       buffer_append(conf, "\0", 1);
+       fclose(f);
+       debug2("%s: done config len = %d", __func__, buffer_len(conf));
+}
+
+void
+parse_server_match_config(ServerOptions *options, const char *user,
+    const char *host, const char *address)
+{
+       ServerOptions mo;
+
+       initialize_server_options(&mo);
+       parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
+       copy_set_server_options(options, &mo, 0);
+}
+
+/* Helper macros */
+#define M_CP_INTOPT(n) do {\
+       if (src->n != -1) \
+               dst->n = src->n; \
+} while (0)
+#define M_CP_STROPT(n) do {\
+       if (src->n != NULL) { \
+               if (dst->n != NULL) \
+                       xfree(dst->n); \
+               dst->n = src->n; \
+       } \
+} while(0)
+#define M_CP_STRARRAYOPT(n, num_n) do {\
+       if (src->num_n != 0) { \
+               for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
+                       dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
+       } \
+} while(0)
+
+/*
+ * Copy any supported values that are set.
+ *
+ * If the preauth flag is set, we do not bother copying the string or
+ * array values that are not used pre-authentication, because any that we
+ * do use must be explictly sent in mm_getpwnamallow().
+ */
+void
+copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
+{
+       M_CP_INTOPT(password_authentication);
+       M_CP_INTOPT(gss_authentication);
+       M_CP_INTOPT(rsa_authentication);
+       M_CP_INTOPT(pubkey_authentication);
+       M_CP_INTOPT(kerberos_authentication);
+       M_CP_INTOPT(hostbased_authentication);
+       M_CP_INTOPT(hostbased_uses_name_from_packet_only);
+       M_CP_INTOPT(kbd_interactive_authentication);
+       M_CP_INTOPT(zero_knowledge_password_authentication);
+       M_CP_INTOPT(permit_root_login);
+       M_CP_INTOPT(permit_empty_passwd);
+
+       M_CP_INTOPT(allow_tcp_forwarding);
+       M_CP_INTOPT(allow_agent_forwarding);
+       M_CP_INTOPT(permit_tun);
+       M_CP_INTOPT(gateway_ports);
+       M_CP_INTOPT(x11_display_offset);
+       M_CP_INTOPT(x11_forwarding);
+       M_CP_INTOPT(x11_use_localhost);
+       M_CP_INTOPT(max_sessions);
+       M_CP_INTOPT(max_authtries);
+       M_CP_INTOPT(ip_qos_interactive);
+       M_CP_INTOPT(ip_qos_bulk);
+
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+
+       /*
+        * The only things that should be below this point are string options
+        * which are only used after authentication.
+        */
+       if (preauth)
+               return;
+
+       M_CP_STROPT(adm_forced_command);
+       M_CP_STROPT(chroot_directory);
+}
+
+#undef M_CP_INTOPT
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+
+void
+parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
+    const char *user, const char *host, const char *address)
+{
+       int active, linenum, bad_options = 0;
+       char *cp, *obuf, *cbuf;
+
+       debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
+
+       obuf = cbuf = xstrdup(buffer_ptr(conf));
+       active = user ? 0 : 1;
+       linenum = 1;
+       while ((cp = strsep(&cbuf, "\n")) != NULL) {
+               if (process_server_config_line(options, cp, filename,
+                   linenum++, &active, user, host, address) != 0)
+                       bad_options++;
+       }
+       xfree(obuf);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+}
+
+static const char *
+fmt_multistate_int(int val, const struct multistate *m)
+{
+       u_int i;
+
+       for (i = 0; m[i].key != NULL; i++) {
+               if (m[i].value == val)
+                       return m[i].key;
+       }
+       return "UNKNOWN";
+}
+
+static const char *
+fmt_intarg(ServerOpCodes code, int val)
+{
+       if (val == -1)
+               return "unset";
+       switch (code) {
+       case sAddressFamily:
+               return fmt_multistate_int(val, multistate_addressfamily);
+       case sPermitRootLogin:
+               return fmt_multistate_int(val, multistate_permitrootlogin);
+       case sGatewayPorts:
+               return fmt_multistate_int(val, multistate_gatewayports);
+       case sCompression:
+               return fmt_multistate_int(val, multistate_compression);
+       case sUsePrivilegeSeparation:
+               return fmt_multistate_int(val, multistate_privsep);
+       case sProtocol:
+               switch (val) {
+               case SSH_PROTO_1:
+                       return "1";
+               case SSH_PROTO_2:
+                       return "2";
+               case (SSH_PROTO_1|SSH_PROTO_2):
+                       return "2,1";
+               default:
+                       return "UNKNOWN";
+               }
+       default:
+               switch (val) {
+               case 0:
+                       return "no";
+               case 1:
+                       return "yes";
+               default:
+                       return "UNKNOWN";
+               }
+       }
+}
+
+static const char *
+lookup_opcode_name(ServerOpCodes code)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name != NULL; i++)
+               if (keywords[i].opcode == code)
+                       return(keywords[i].name);
+       return "UNKNOWN";
+}
+
+static void
+dump_cfg_int(ServerOpCodes code, int val)
+{
+       printf("%s %d\n", lookup_opcode_name(code), val);
+}
+
+static void
+dump_cfg_fmtint(ServerOpCodes code, int val)
+{
+       printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
+}
+
+static void
+dump_cfg_string(ServerOpCodes code, const char *val)
+{
+       if (val == NULL)
+               return;
+       printf("%s %s\n", lookup_opcode_name(code), val);
+}
+
+static void
+dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
+{
+       u_int i;
+
+       for (i = 0; i < count; i++)
+               printf("%s %s\n", lookup_opcode_name(code), vals[i]);
+}
+
+static void
+dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
+{
+       u_int i;
+
+       printf("%s", lookup_opcode_name(code));
+       for (i = 0; i < count; i++)
+               printf(" %s",  vals[i]);
+       printf("\n");
+}
+
+void
+dump_config(ServerOptions *o)
+{
+       u_int i;
+       int ret;
+       struct addrinfo *ai;
+       char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
+
+       /* these are usually at the top of the config */
+       for (i = 0; i < o->num_ports; i++)
+               printf("port %d\n", o->ports[i]);
+       dump_cfg_fmtint(sProtocol, o->protocol);
+       dump_cfg_fmtint(sAddressFamily, o->address_family);
+
+       /* ListenAddress must be after Port */
+       for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
+                   sizeof(addr), port, sizeof(port),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           (ret != EAI_SYSTEM) ? gai_strerror(ret) :
+                           strerror(errno));
+               } else {
+                       if (ai->ai_family == AF_INET6)
+                               printf("listenaddress [%s]:%s\n", addr, port);
+                       else
+                               printf("listenaddress %s:%s\n", addr, port);
+               }
+       }
+
+       /* integer arguments */
+#ifdef USE_PAM
+       dump_cfg_int(sUsePAM, o->use_pam);
+#endif
+       dump_cfg_int(sServerKeyBits, o->server_key_bits);
+       dump_cfg_int(sLoginGraceTime, o->login_grace_time);
+       dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
+       dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
+       dump_cfg_int(sMaxAuthTries, o->max_authtries);
+       dump_cfg_int(sMaxSessions, o->max_sessions);
+       dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
+       dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
+
+       /* formatted integer arguments */
+       dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
+       dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
+       dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
+       dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
+       dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
+       dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
+           o->hostbased_uses_name_from_packet_only);
+       dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
+       dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
+#ifdef KRB5
+       dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
+       dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
+       dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
+# ifdef USE_AFS
+       dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
+# endif
+#endif
+#ifdef GSSAPI
+       dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+       dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
+#endif
+#ifdef JPAKE
+       dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
+           o->zero_knowledge_password_authentication);
+#endif
+       dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
+       dump_cfg_fmtint(sKbdInteractiveAuthentication,
+           o->kbd_interactive_authentication);
+       dump_cfg_fmtint(sChallengeResponseAuthentication,
+           o->challenge_response_authentication);
+       dump_cfg_fmtint(sPrintMotd, o->print_motd);
+       dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
+       dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
+       dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
+       dump_cfg_fmtint(sStrictModes, o->strict_modes);
+       dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
+       dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
+       dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
+       dump_cfg_fmtint(sUseLogin, o->use_login);
+       dump_cfg_fmtint(sCompression, o->compression);
+       dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
+       dump_cfg_fmtint(sUseDNS, o->use_dns);
+       dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
+       dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
+
+       /* string arguments */
+       dump_cfg_string(sPidFile, o->pid_file);
+       dump_cfg_string(sXAuthLocation, o->xauth_location);
+       dump_cfg_string(sCiphers, o->ciphers);
+       dump_cfg_string(sMacs, o->macs);
+       dump_cfg_string(sBanner, o->banner);
+       dump_cfg_string(sForceCommand, o->adm_forced_command);
+       dump_cfg_string(sChrootDirectory, o->chroot_directory);
+       dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
+       dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
+       dump_cfg_string(sAuthorizedPrincipalsFile,
+           o->authorized_principals_file);
+
+       /* string arguments requiring a lookup */
+       dump_cfg_string(sLogLevel, log_level_name(o->log_level));
+       dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
+
+       /* string array arguments */
+       dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
+           o->authorized_keys_files);
+       dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
+            o->host_key_files);
+       dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
+            o->host_cert_files);
+       dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
+       dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
+       dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
+       dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
+       dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
+
+       /* other arguments */
+       for (i = 0; i < o->num_subsystems; i++)
+               printf("subsystem %s %s\n", o->subsystem_name[i],
+                   o->subsystem_args[i]);
+
+       printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
+           o->max_startups_rate, o->max_startups);
+
+       for (i = 0; tunmode_desc[i].val != -1; i++)
+               if (tunmode_desc[i].val == o->permit_tun) {
+                       s = tunmode_desc[i].text;
+                       break;
+               }
+       dump_cfg_string(sPermitTunnel, s);
+
+       printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
+       printf("%s\n", iptos2str(o->ip_qos_bulk));
+
+       channel_print_adm_permitted_opens();
+}
diff --git a/.pc/gssapi.patch/servconf.h b/.pc/gssapi.patch/servconf.h
new file mode 100644 (file)
index 0000000..89f38e2
--- /dev/null
@@ -0,0 +1,198 @@
+/* $OpenBSD: servconf.h,v 1.99 2011/06/22 21:57:01 djm Exp $ */
+
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Definitions for server configuration data and for the functions reading it.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#ifndef SERVCONF_H
+#define SERVCONF_H
+
+#define MAX_PORTS              256     /* Max # ports. */
+
+#define MAX_ALLOW_USERS                256     /* Max # users on allow list. */
+#define MAX_DENY_USERS         256     /* Max # users on deny list. */
+#define MAX_ALLOW_GROUPS       256     /* Max # groups on allow list. */
+#define MAX_DENY_GROUPS                256     /* Max # groups on deny list. */
+#define MAX_SUBSYSTEMS         256     /* Max # subsystems. */
+#define MAX_HOSTKEYS           256     /* Max # hostkeys. */
+#define MAX_HOSTCERTS          256     /* Max # host certificates. */
+#define MAX_ACCEPT_ENV         256     /* Max # of env vars. */
+#define MAX_MATCH_GROUPS       256     /* Max # of groups for Match. */
+#define MAX_AUTHKEYS_FILES     256     /* Max # of authorized_keys files. */
+
+/* permit_root_login */
+#define        PERMIT_NOT_SET          -1
+#define        PERMIT_NO               0
+#define        PERMIT_FORCED_ONLY      1
+#define        PERMIT_NO_PASSWD        2
+#define        PERMIT_YES              3
+
+/* use_privsep */
+#define PRIVSEP_OFF            0
+#define PRIVSEP_ON             1
+#define PRIVSEP_SANDBOX                2
+
+#define DEFAULT_AUTH_FAIL_MAX  6       /* Default for MaxAuthTries */
+#define DEFAULT_SESSIONS_MAX   10      /* Default for MaxSessions */
+
+/* Magic name for internal sftp-server */
+#define INTERNAL_SFTP_NAME     "internal-sftp"
+
+typedef struct {
+       u_int   num_ports;
+       u_int   ports_from_cmdline;
+       int     ports[MAX_PORTS];       /* Port number to listen on. */
+       char   *listen_addr;            /* Address on which the server listens. */
+       struct addrinfo *listen_addrs;  /* Addresses on which the server listens. */
+       int     address_family;         /* Address family used by the server. */
+       char   *host_key_files[MAX_HOSTKEYS];   /* Files containing host keys. */
+       int     num_host_key_files;     /* Number of files for host keys. */
+       char   *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */
+       int     num_host_cert_files;     /* Number of files for host certs. */
+       char   *pid_file;       /* Where to put our pid */
+       int     server_key_bits;/* Size of the server key. */
+       int     login_grace_time;       /* Disconnect if no auth in this time
+                                        * (sec). */
+       int     key_regeneration_time;  /* Server key lifetime (seconds). */
+       int     permit_root_login;      /* PERMIT_*, see above */
+       int     ignore_rhosts;  /* Ignore .rhosts and .shosts. */
+       int     ignore_user_known_hosts;        /* Ignore ~/.ssh/known_hosts
+                                                * for RhostsRsaAuth */
+       int     print_motd;     /* If true, print /etc/motd. */
+       int     print_lastlog;  /* If true, print lastlog */
+       int     x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
+       int     x11_display_offset;     /* What DISPLAY number to start
+                                        * searching at */
+       int     x11_use_localhost;      /* If true, use localhost for fake X11 server. */
+       char   *xauth_location; /* Location of xauth program */
+       int     strict_modes;   /* If true, require string home dir modes. */
+       int     tcp_keep_alive; /* If true, set SO_KEEPALIVE. */
+       int     ip_qos_interactive;     /* IP ToS/DSCP/class for interactive */
+       int     ip_qos_bulk;            /* IP ToS/DSCP/class for bulk traffic */
+       char   *ciphers;        /* Supported SSH2 ciphers. */
+       char   *macs;           /* Supported SSH2 macs. */
+       char   *kex_algorithms; /* SSH2 kex methods in order of preference. */
+       int     protocol;       /* Supported protocol versions. */
+       int     gateway_ports;  /* If true, allow remote connects to forwarded ports. */
+       SyslogFacility log_facility;    /* Facility for system logging. */
+       LogLevel log_level;     /* Level for system logging. */
+       int     rhosts_rsa_authentication;      /* If true, permit rhosts RSA
+                                                * authentication. */
+       int     hostbased_authentication;       /* If true, permit ssh2 hostbased auth */
+       int     hostbased_uses_name_from_packet_only; /* experimental */
+       int     rsa_authentication;     /* If true, permit RSA authentication. */
+       int     pubkey_authentication;  /* If true, permit ssh2 pubkey authentication. */
+       int     kerberos_authentication;        /* If true, permit Kerberos
+                                                * authentication. */
+       int     kerberos_or_local_passwd;       /* If true, permit kerberos
+                                                * and any other password
+                                                * authentication mechanism,
+                                                * such as SecurID or
+                                                * /etc/passwd */
+       int     kerberos_ticket_cleanup;        /* If true, destroy ticket
+                                                * file on logout. */
+       int     kerberos_get_afs_token;         /* If true, try to get AFS token if
+                                                * authenticated with Kerberos. */
+       int     gss_authentication;     /* If true, permit GSSAPI authentication */
+       int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
+       int     password_authentication;        /* If true, permit password
+                                                * authentication. */
+       int     kbd_interactive_authentication; /* If true, permit */
+       int     challenge_response_authentication;
+       int     zero_knowledge_password_authentication;
+                                       /* If true, permit jpake auth */
+       int     permit_empty_passwd;    /* If false, do not permit empty
+                                        * passwords. */
+       int     permit_user_env;        /* If true, read ~/.ssh/environment */
+       int     use_login;      /* If true, login(1) is used */
+       int     compression;    /* If true, compression is allowed */
+       int     allow_tcp_forwarding;
+       int     allow_agent_forwarding;
+       u_int num_allow_users;
+       char   *allow_users[MAX_ALLOW_USERS];
+       u_int num_deny_users;
+       char   *deny_users[MAX_DENY_USERS];
+       u_int num_allow_groups;
+       char   *allow_groups[MAX_ALLOW_GROUPS];
+       u_int num_deny_groups;
+       char   *deny_groups[MAX_DENY_GROUPS];
+
+       u_int num_subsystems;
+       char   *subsystem_name[MAX_SUBSYSTEMS];
+       char   *subsystem_command[MAX_SUBSYSTEMS];
+       char   *subsystem_args[MAX_SUBSYSTEMS];
+
+       u_int num_accept_env;
+       char   *accept_env[MAX_ACCEPT_ENV];
+
+       int     max_startups_begin;
+       int     max_startups_rate;
+       int     max_startups;
+       int     max_authtries;
+       int     max_sessions;
+       char   *banner;                 /* SSH-2 banner message */
+       int     use_dns;
+       int     client_alive_interval;  /*
+                                        * poke the client this often to
+                                        * see if it's still there
+                                        */
+       int     client_alive_count_max; /*
+                                        * If the client is unresponsive
+                                        * for this many intervals above,
+                                        * disconnect the session
+                                        */
+
+       u_int num_authkeys_files;       /* Files containing public keys */
+       char   *authorized_keys_files[MAX_AUTHKEYS_FILES];
+
+       char   *adm_forced_command;
+
+       int     use_pam;                /* Enable auth via PAM */
+
+       int     permit_tun;
+
+       int     num_permitted_opens;
+
+       char   *chroot_directory;
+       char   *revoked_keys_file;
+       char   *trusted_user_ca_keys;
+       char   *authorized_principals_file;
+}       ServerOptions;
+
+/*
+ * These are string config options that must be copied between the
+ * Match sub-config and the main config, and must be sent from the
+ * privsep slave to the privsep master. We use a macro to ensure all
+ * the options are copied and the copies are done in the correct order.
+ */
+#define COPY_MATCH_STRING_OPTS() do { \
+               M_CP_STROPT(banner); \
+               M_CP_STROPT(trusted_user_ca_keys); \
+               M_CP_STROPT(revoked_keys_file); \
+               M_CP_STROPT(authorized_principals_file); \
+               M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
+       } while (0)
+
+void    initialize_server_options(ServerOptions *);
+void    fill_default_server_options(ServerOptions *);
+int     process_server_config_line(ServerOptions *, char *, const char *, int,
+            int *, const char *, const char *, const char *);
+void    load_server_config(const char *, Buffer *);
+void    parse_server_config(ServerOptions *, const char *, Buffer *,
+            const char *, const char *, const char *);
+void    parse_server_match_config(ServerOptions *, const char *, const char *,
+            const char *);
+void    copy_set_server_options(ServerOptions *, ServerOptions *, int);
+void    dump_config(ServerOptions *);
+char   *derelativise_path(const char *);
+
+#endif                         /* SERVCONF_H */
diff --git a/.pc/gssapi.patch/ssh-gss.h b/.pc/gssapi.patch/ssh-gss.h
new file mode 100644 (file)
index 0000000..c29a1b7
--- /dev/null
@@ -0,0 +1,131 @@
+/* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
+/*
+ * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SSH_GSS_H
+#define _SSH_GSS_H
+
+#ifdef GSSAPI
+
+#ifdef HAVE_GSSAPI_H
+#include <gssapi.h>
+#elif defined(HAVE_GSSAPI_GSSAPI_H)
+#include <gssapi/gssapi.h>
+#endif
+
+#ifdef KRB5
+# ifndef HEIMDAL
+#  ifdef HAVE_GSSAPI_GENERIC_H
+#   include <gssapi_generic.h>
+#  elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H)
+#   include <gssapi/gssapi_generic.h>
+#  endif
+
+/* MIT Kerberos doesn't seem to define GSS_NT_HOSTBASED_SERVICE */
+
+#ifndef GSS_C_NT_HOSTBASED_SERVICE
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#endif /* GSS_C_NT_... */
+#endif /* !HEIMDAL */
+#endif /* KRB5 */
+
+/* draft-ietf-secsh-gsskeyex-06 */
+#define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE              60
+#define SSH2_MSG_USERAUTH_GSSAPI_TOKEN                 61
+#define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE     63
+#define SSH2_MSG_USERAUTH_GSSAPI_ERROR                 64
+#define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK                        65
+#define SSH2_MSG_USERAUTH_GSSAPI_MIC                   66
+
+#define SSH_GSS_OIDTYPE 0x06
+
+typedef struct {
+       char *filename;
+       char *envvar;
+       char *envval;
+       void *data;
+} ssh_gssapi_ccache;
+
+typedef struct {
+       gss_buffer_desc displayname;
+       gss_buffer_desc exportedname;
+       gss_cred_id_t creds;
+       struct ssh_gssapi_mech_struct *mech;
+       ssh_gssapi_ccache store;
+} ssh_gssapi_client;
+
+typedef struct ssh_gssapi_mech_struct {
+       char *enc_name;
+       char *name;
+       gss_OID_desc oid;
+       int (*dochild) (ssh_gssapi_client *);
+       int (*userok) (ssh_gssapi_client *, char *);
+       int (*localname) (ssh_gssapi_client *, char **);
+       void (*storecreds) (ssh_gssapi_client *);
+} ssh_gssapi_mech;
+
+typedef struct {
+       OM_uint32       major; /* both */
+       OM_uint32       minor; /* both */
+       gss_ctx_id_t    context; /* both */
+       gss_name_t      name; /* both */
+       gss_OID         oid; /* client */
+       gss_cred_id_t   creds; /* server */
+       gss_name_t      client; /* server */
+       gss_cred_id_t   client_creds; /* server */
+} Gssctxt;
+
+extern ssh_gssapi_mech *supported_mechs[];
+
+int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
+void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
+void ssh_gssapi_set_oid(Gssctxt *, gss_OID);
+void ssh_gssapi_supported_oids(gss_OID_set *);
+ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *);
+
+OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *);
+OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int,
+    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
+OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *,
+    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
+OM_uint32 ssh_gssapi_getclient(Gssctxt *, ssh_gssapi_client *);
+void ssh_gssapi_error(Gssctxt *);
+char *ssh_gssapi_last_error(Gssctxt *, OM_uint32 *, OM_uint32 *);
+void ssh_gssapi_build_ctx(Gssctxt **);
+void ssh_gssapi_delete_ctx(Gssctxt **);
+OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
+void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
+
+/* In the server */
+OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
+int ssh_gssapi_userok(char *name);
+OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+void ssh_gssapi_do_child(char ***, u_int *);
+void ssh_gssapi_cleanup_creds(void);
+void ssh_gssapi_storecreds(void);
+
+#endif /* GSSAPI */
+
+#endif /* _SSH_GSS_H */
diff --git a/.pc/gssapi.patch/ssh_config b/.pc/gssapi.patch/ssh_config
new file mode 100644 (file)
index 0000000..1893674
--- /dev/null
@@ -0,0 +1,47 @@
+#      $OpenBSD: ssh_config,v 1.26 2010/01/11 01:39:46 dtucker Exp $
+
+# This is the ssh client system-wide configuration file.  See
+# ssh_config(5) for more information.  This file provides defaults for
+# users, and the values can be changed in per-user configuration files
+# or on the command line.
+
+# Configuration data is parsed as follows:
+#  1. command line options
+#  2. user-specific file
+#  3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# Site-wide defaults for some commonly used options.  For a comprehensive
+# list of available options, their meanings and defaults, please see the
+# ssh_config(5) man page.
+
+# Host *
+#   ForwardAgent no
+#   ForwardX11 no
+#   RhostsRSAAuthentication no
+#   RSAAuthentication yes
+#   PasswordAuthentication yes
+#   HostbasedAuthentication no
+#   GSSAPIAuthentication no
+#   GSSAPIDelegateCredentials no
+#   BatchMode no
+#   CheckHostIP yes
+#   AddressFamily any
+#   ConnectTimeout 0
+#   StrictHostKeyChecking ask
+#   IdentityFile ~/.ssh/identity
+#   IdentityFile ~/.ssh/id_rsa
+#   IdentityFile ~/.ssh/id_dsa
+#   Port 22
+#   Protocol 2,1
+#   Cipher 3des
+#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
+#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
+#   EscapeChar ~
+#   Tunnel no
+#   TunnelDevice any:any
+#   PermitLocalCommand no
+#   VisualHostKey no
+#   ProxyCommand ssh -q -W %h:%p gateway.example.com
diff --git a/.pc/gssapi.patch/ssh_config.5 b/.pc/gssapi.patch/ssh_config.5
new file mode 100644 (file)
index 0000000..a782d6f
--- /dev/null
@@ -0,0 +1,1294 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Nm ~/.ssh/config
+.Nm /etc/ssh/ssh_config
+.Sh DESCRIPTION
+.Xr ssh 1
+obtains configuration data from the following sources in
+the following order:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+command-line options
+.It
+user's configuration file
+.Pq Pa ~/.ssh/config
+.It
+system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+.El
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections separated by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp ,
+and
+.Nm sftp
+.Fl o
+option.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+If more than one pattern is provided, they should be separated by whitespace.
+A single
+.Ql *
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e. the name is not converted to
+a canonicalized host name before matching).
+.Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm AddressFamily
+Specifies which address family to use when connecting.
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Use the specified address on the local machine as the source address of
+the connection.
+Only useful on systems with more than one address.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge-response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Xr ssh 1
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote, and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared.
+This option is primarily useful when used from the
+.Xr ssh 1
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout (in seconds) used when connecting to the
+SSH server, instead of using the default system TCP timeout.
+This value is used only when the target is down or really unreachable,
+not when it refuses the connection.
+.It Cm ControlMaster
+Enables the sharing of multiple sessions over a single network connection.
+When set to
+.Dq yes ,
+.Xr ssh 1
+will listen for connections on a control socket specified using the
+.Cm ControlPath
+argument.
+Additional sessions can connect to this socket using the same
+.Cm ControlPath
+with
+.Cm ControlMaster
+set to
+.Dq no
+(the default).
+These sessions will try to reuse the master instance's network connection
+rather than initiating new ones, but will fall back to connecting normally
+if the control socket does not exist, or is not listening.
+.Pp
+Setting this to
+.Dq ask
+will cause ssh
+to listen for control connections, but require confirmation using the
+.Ev SSH_ASKPASS
+program before they are accepted (see
+.Xr ssh-add 1
+for details).
+If the
+.Cm ControlPath
+cannot be opened,
+ssh will continue without connecting to a master instance.
+.Pp
+X11 and
+.Xr ssh-agent 1
+forwarding is supported over these multiplexed connections, however the
+display and agent forwarded will be the one belonging to the master
+connection i.e. it is not possible to forward multiple displays or agents.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
+.It Cm ControlPath
+Specify the path to the control socket used for connection sharing as described
+in the
+.Cm ControlMaster
+section above or the string
+.Dq none
+to disable connection sharing.
+In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
+.Ql %l
+will be substituted by the local host name (including any domain name),
+.Ql %h
+will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
+.Ql %p
+the port,
+.Ql %r
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+at least %h, %p, and %r.
+This ensures that shared connections are uniquely identified.
+.It Cm ControlPersist
+When used in conjunction with
+.Cm ControlMaster ,
+specifies that the master connection should remain open
+in the background (waiting for future client connections)
+after the initial client connection has been closed.
+If set to
+.Dq no ,
+then the master connection will not be placed into the background,
+and will close as soon as the initial client connection is closed.
+If set to
+.Dq yes ,
+then the master connection will remain in the background indefinitely
+(until killed or closed via a mechanism such as the
+.Xr ssh 1
+.Dq Fl O No exit
+option).
+If set to a time in seconds, or a time in any of the formats documented in
+.Xr sshd_config 5 ,
+then the backgrounded master connection will automatically terminate
+after it has remained idle (with no client connections) for the
+specified time.
+.It Cm DynamicForward
+Specifies that a TCP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+.Pp
+The argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port .
+.Sm on
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.Pp
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Xr ssh 1
+will act as a SOCKS server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm EnableSSHKeysign
+Setting this option to
+.Dq yes
+in the global client configuration file
+.Pa /etc/ssh/ssh_config
+enables the use of the helper program
+.Xr ssh-keysign 8
+during
+.Cm HostbasedAuthentication .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option should be placed in the non-hostspecific section.
+See
+.Xr ssh-keysign 8
+for more information.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ExitOnForwardFailure
+Specifies whether
+.Xr ssh 1
+should terminate the connection if it cannot set up all requested
+dynamic, tunnel, local, and remote port forwardings.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's Unix-domain socket)
+can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X11 authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring
+if the
+.Cm ForwardX11Trusted
+option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
+.It Cm ForwardX11Trusted
+If this option is set to
+.Dq yes ,
+remote X11 clients will have full access to the original X11 display.
+.Pp
+If this option is set to
+.Dq no ,
+remote X11 clients will be considered untrusted and prevented
+from stealing or tampering with data belonging to trusted X11
+clients.
+Furthermore, the
+.Xr xauth 1
+token used for the session will be set to expire after 20 minutes.
+Remote clients will be refused access after this time.
+.Pp
+The default is
+.Dq no .
+.Pp
+See the X11 SECURITY extension specification for full details on
+the restrictions imposed on untrusted clients.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Xr ssh 1
+binds local port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIDelegateCredentials
+Forward (delegate) credentials to the server.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm HashKnownHosts
+Indicates that
+.Xr ssh 1
+should hash host names and addresses when they are added to
+.Pa ~/.ssh/known_hosts .
+These hashed names may be used normally by
+.Xr ssh 1
+and
+.Xr sshd 8 ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+The default is
+.Dq no .
+Note that existing names and addresses in known hosts files
+will not be converted automatically,
+but may be manually hashed using
+.Xr ssh-keygen 1 .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
+ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-rsa,ssh-dss
+.Ed
+.Pp
+If hostkeys are known for the destination host then this default is modified
+to prefer their algorithms.
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling SSH connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+If the hostname contains the character sequence
+.Ql %h ,
+then this will be replaced with the host name specified on the command line
+(this is useful for manipulating unqualified names).
+The default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentitiesOnly
+Specifies that
+.Xr ssh 1
+should only use the authentication identity files configured in the
+.Nm
+files,
+even if
+.Xr ssh-agent 1
+offers more identities.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option is intended for situations where ssh-agent
+offers many different identities.
+The default is
+.Dq no .
+.It Cm IdentityFile
+Specifies a file from which the user's DSA, ECDSA or DSA authentication
+identity is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+.Xr ssh 1
+will try to load certificate information from the filename obtained by
+appending
+.Pa -cert.pub
+to the path of a specified
+.Cm IdentityFile .
+.Pp
+The file name may use the tilde
+syntax to refer to a user's home directory or one of the following
+escape characters:
+.Ql %d
+(local user's home directory),
+.Ql %u
+(local user name),
+.Ql %l
+(local host name),
+.Ql %h
+(remote host name) or
+.Ql %r
+(remote user name).
+.Pp
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KbdInteractiveAuthentication
+Specifies whether to use keyboard-interactive authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm KbdInteractiveDevices
+Specifies the list of methods to use in keyboard-interactive authentication.
+Multiple method names must be comma-separated.
+The default is to use the server specified list.
+The methods available vary depending on what the server supports.
+For an OpenSSH server,
+it may be zero or more of:
+.Dq bsdauth ,
+.Dq pam ,
+and
+.Dq skey .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
+diffie-hellman-group-exchange-sha256,
+diffie-hellman-group-exchange-sha1,
+diffie-hellman-group14-sha1,
+diffie-hellman-group1-sha1
+.Ed
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+The following escape character substitutions will be performed:
+.Ql %d
+(local user's home directory),
+.Ql %h
+(remote host name),
+.Ql %l
+(local host name),
+.Ql %n
+(host name as provided on the command line),
+.Ql %p
+(remote port),
+.Ql %r
+(remote user name) or
+.Ql %u
+(local user name).
+.Pp
+The command is run synchronously and does not have access to the
+session of the
+.Xr ssh 1
+that spawned it.
+It should not be used for interactive commands.
+.Pp
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
+.It Cm LocalForward
+Specifies that a TCP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional forwardings can be
+given on the command line.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr ssh 1 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+The default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic !\& Ns Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm PKCS11Provider
+Specifies which PKCS#11 provider to use.
+The argument to this keyword is the PKCS#11 shared library
+.Xr ssh 1
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Cm Port
+Specifies the port number to connect on the remote host.
+The default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods.
+This allows a client to prefer one method (e.g.\&
+.Cm keyboard-interactive )
+over another method (e.g.\&
+.Cm password ) .
+The default is:
+.Bd -literal -offset indent
+gssapi-with-mic,hostbased,publickey,
+keyboard-interactive,password
+.Ed
+.It Cm Protocol
+Specifies the protocol versions
+.Xr ssh 1
+should support in order of preference.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+When this option is set to
+.Dq 2,1
+.Nm ssh
+will try version 2 and fall back to version 1
+if version 2 is not available.
+The default is
+.Sq 2 .
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+the user's shell.
+In the command string, any occurrence of
+.Ql %h
+will be substituted by the host name to
+connect,
+.Ql %p
+by the port, and
+.Ql %r
+by the remote user name.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Setting the command to
+.Dq none
+disables this option entirely.
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+This directive is useful in conjunction with
+.Xr nc 1
+and its proxy support.
+For example, the following directive would connect via an HTTP proxy at
+192.0.2.0:
+.Bd -literal -offset 3n
+ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
+.Ed
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RekeyLimit
+Specifies the maximum amount of data that may be transmitted before the
+session key is renegotiated.
+The argument is the number of bytes, with an optional suffix of
+.Sq K ,
+.Sq M ,
+or
+.Sq G
+to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
+The default is between
+.Sq 1G
+and
+.Sq 4G ,
+depending on the cipher.
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+.Pp
+If the
+.Ar bind_address
+is not specified, the default is to only bind to loopback addresses.
+If the
+.Ar bind_address
+is
+.Ql *
+or an empty string, then the forwarding is requested to listen on all
+interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Xr ssh 1
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SendEnv
+Specifies what variables from the local
+.Xr environ 7
+should be sent to the server.
+Note that environment passing is only supported for protocol 2.
+The server must also support it, and the server must be configured to
+accept these environment variables.
+Refer to
+.Cm AcceptEnv
+in
+.Xr sshd_config 5
+for how to configure the server.
+Variables are specified by name, which may contain wildcard characters.
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm SendEnv
+directives.
+The default is not to send any environment variables.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm ServerAliveCountMax
+Sets the number of server alive messages (see below) which may be
+sent without
+.Xr ssh 1
+receiving any messages back from the server.
+If this threshold is reached while server alive messages are being sent,
+ssh will disconnect from the server, terminating the session.
+It is important to note that the use of server alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The server alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The server alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If, for example,
+.Cm ServerAliveInterval
+(see below) is set to 15 and
+.Cm ServerAliveCountMax
+is left at the default, if the server becomes unresponsive,
+ssh will disconnect after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ServerAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the server,
+.Xr ssh 1
+will send a message through the encrypted
+channel to request a response from the server.
+The default
+is 0, indicating that these messages will not be sent to the server.
+This option applies to protocol version 2 only.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will never automatically add host keys to the
+.Pa ~/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+though it can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained or when connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+ssh will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+ssh will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm Tunnel
+Request
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2),
+or
+.Dq no .
+Specifying
+.Dq yes
+requests the default tunnel mode, which is
+.Dq point-to-point .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Specifies the
+.Xr tun 4
+devices to open on the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The argument must be
+.Sm off
+.Ar local_tun Op : Ar remote_tun .
+.Sm on
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+The default is
+.Dq any:any .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+If set to
+.Dq yes ,
+.Xr ssh 1
+must be setuid root.
+Note that this option must be set to
+.Dq yes
+for
+.Cm RhostsRSAAuthentication
+with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
+.It Cm VerifyHostKeyDNS
+Specifies whether to verify the remote key using DNS and SSHFP resource
+records.
+If this option is set to
+.Dq yes ,
+the client will implicitly trust keys that match a secure fingerprint
+from DNS.
+Insecure fingerprints will be handled as if this option was set to
+.Dq ask .
+If this option is set to
+.Dq ask ,
+information on fingerprint match will be displayed, but the user will still
+need to confirm new host keys according to the
+.Cm StrictHostKeyChecking
+option.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.Pp
+See also
+.Sx VERIFYING HOST KEYS
+in
+.Xr ssh 1 .
+.It Cm VisualHostKey
+If this flag is set to
+.Dq yes ,
+an ASCII art representation of the remote host key fingerprint is
+printed in addition to the hex fingerprint string at login and
+for unknown host keys.
+If this flag is set to
+.Dq no ,
+no fingerprint strings are printed at login and
+only the hex fingerprint string will be printed for unknown host keys.
+The default is
+.Dq no .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh PATTERNS
+A
+.Em pattern
+consists of zero or more non-whitespace characters,
+.Sq *
+(a wildcard that matches zero or more characters),
+or
+.Sq ?\&
+(a wildcard that matches exactly one character).
+For example, to specify a set of declarations for any host in the
+.Dq .co.uk
+set of domains,
+the following pattern could be used:
+.Pp
+.Dl Host *.co.uk
+.Pp
+The following pattern
+would match any host in the 192.168.0.[0-9] network range:
+.Pp
+.Dl Host 192.168.0.?
+.Pp
+A
+.Em pattern-list
+is a comma-separated list of patterns.
+Patterns within pattern-lists may be negated
+by preceding them with an exclamation mark
+.Pq Sq !\& .
+For example,
+to allow a key to be used from anywhere within an organisation
+except from the
+.Dq dialup
+pool,
+the following entry (in authorized_keys) could be used:
+.Pp
+.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the SSH client.
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh SEE ALSO
+.Xr ssh 1
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/gssapi.patch/sshconnect2.c b/.pc/gssapi.patch/sshconnect2.c
new file mode 100644 (file)
index 0000000..c24b202
--- /dev/null
@@ -0,0 +1,1920 @@
+/* $OpenBSD: sshconnect2.c,v 1.188 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2008 Damien Miller.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
+#include <vis.h>
+#endif
+
+#include "openbsd-compat/sys-queue.h"
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh2.h"
+#include "buffer.h"
+#include "packet.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "myproposal.h"
+#include "sshconnect.h"
+#include "authfile.h"
+#include "dh.h"
+#include "authfd.h"
+#include "log.h"
+#include "readconf.h"
+#include "misc.h"
+#include "match.h"
+#include "dispatch.h"
+#include "canohost.h"
+#include "msg.h"
+#include "pathnames.h"
+#include "uidswap.h"
+#include "hostfile.h"
+#include "schnorr.h"
+#include "jpake.h"
+
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
+/* import */
+extern char *client_version_string;
+extern char *server_version_string;
+extern Options options;
+
+/*
+ * SSH2 key exchange
+ */
+
+u_char *session_id2 = NULL;
+u_int session_id2_len = 0;
+
+char *xxx_host;
+struct sockaddr *xxx_hostaddr;
+
+Kex *xxx_kex = NULL;
+
+static int
+verify_host_key_callback(Key *hostkey)
+{
+       if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
+               fatal("Host key verification failed.");
+       return 0;
+}
+
+static char *
+order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
+{
+       char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
+       size_t maxlen;
+       struct hostkeys *hostkeys;
+       int ktype;
+       u_int i;
+
+       /* Find all hostkeys for this hostname */
+       get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL);
+       hostkeys = init_hostkeys();
+       for (i = 0; i < options.num_user_hostfiles; i++)
+               load_hostkeys(hostkeys, hostname, options.user_hostfiles[i]);
+       for (i = 0; i < options.num_system_hostfiles; i++)
+               load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
+
+       oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
+       maxlen = strlen(avail) + 1;
+       first = xmalloc(maxlen);
+       last = xmalloc(maxlen);
+       *first = *last = '\0';
+
+#define ALG_APPEND(to, from) \
+       do { \
+               if (*to != '\0') \
+                       strlcat(to, ",", maxlen); \
+               strlcat(to, from, maxlen); \
+       } while (0)
+
+       while ((alg = strsep(&avail, ",")) && *alg != '\0') {
+               if ((ktype = key_type_from_name(alg)) == KEY_UNSPEC)
+                       fatal("%s: unknown alg %s", __func__, alg);
+               if (lookup_key_in_hostkeys_by_type(hostkeys,
+                   key_type_plain(ktype), NULL))
+                       ALG_APPEND(first, alg);
+               else
+                       ALG_APPEND(last, alg);
+       }
+#undef ALG_APPEND
+       xasprintf(&ret, "%s%s%s", first, *first == '\0' ? "" : ",", last);
+       if (*first != '\0')
+               debug3("%s: prefer hostkeyalgs: %s", __func__, first);
+
+       xfree(first);
+       xfree(last);
+       xfree(hostname);
+       xfree(oavail);
+       free_hostkeys(hostkeys);
+
+       return ret;
+}
+
+void
+ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
+{
+       Kex *kex;
+
+       xxx_host = host;
+       xxx_hostaddr = hostaddr;
+
+       if (options.ciphers == (char *)-1) {
+               logit("No valid ciphers for protocol version 2 given, using defaults.");
+               options.ciphers = NULL;
+       }
+       if (options.ciphers != NULL) {
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       myproposal[PROPOSAL_ENC_ALGS_STOC] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
+       if (options.compression) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none";
+       } else {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib";
+       }
+       if (options.macs != NULL) {
+               myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+               myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+       }
+       if (options.hostkeyalgorithms != NULL)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
+                   options.hostkeyalgorithms;
+       else {
+               /* Prefer algorithms that we already have keys for */
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
+                   order_hostkeyalgs(host, hostaddr, port);
+       }
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+
+       if (options.rekey_limit)
+               packet_set_rekey_limit((u_int32_t)options.rekey_limit);
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->verify_host_key=&verify_host_key_callback;
+
+       xxx_kex = kex;
+
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+
+       if (options.use_roaming && !kex->roaming) {
+               debug("Roaming not allowed by server");
+               options.use_roaming = 0;
+       }
+
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
+
+#ifdef DEBUG_KEXDH
+       /* send 1st encrypted/maced/compressed message */
+       packet_start(SSH2_MSG_IGNORE);
+       packet_put_cstring("markus");
+       packet_send();
+       packet_write_wait();
+#endif
+}
+
+/*
+ * Authenticate user
+ */
+
+typedef struct Authctxt Authctxt;
+typedef struct Authmethod Authmethod;
+typedef struct identity Identity;
+typedef struct idlist Idlist;
+
+struct identity {
+       TAILQ_ENTRY(identity) next;
+       AuthenticationConnection *ac;   /* set if agent supports key */
+       Key     *key;                   /* public/private key */
+       char    *filename;              /* comment for agent-only keys */
+       int     tried;
+       int     isprivate;              /* key points to the private key */
+};
+TAILQ_HEAD(idlist, identity);
+
+struct Authctxt {
+       const char *server_user;
+       const char *local_user;
+       const char *host;
+       const char *service;
+       Authmethod *method;
+       sig_atomic_t success;
+       char *authlist;
+       /* pubkey */
+       Idlist keys;
+       AuthenticationConnection *agent;
+       /* hostbased */
+       Sensitive *sensitive;
+       /* kbd-interactive */
+       int info_req_seen;
+       /* generic */
+       void *methoddata;
+};
+struct Authmethod {
+       char    *name;          /* string to compare against server's list */
+       int     (*userauth)(Authctxt *authctxt);
+       void    (*cleanup)(Authctxt *authctxt);
+       int     *enabled;       /* flag in option struct that enables method */
+       int     *batch_flag;    /* flag in option struct that disables method */
+};
+
+void   input_userauth_success(int, u_int32_t, void *);
+void   input_userauth_success_unexpected(int, u_int32_t, void *);
+void   input_userauth_failure(int, u_int32_t, void *);
+void   input_userauth_banner(int, u_int32_t, void *);
+void   input_userauth_error(int, u_int32_t, void *);
+void   input_userauth_info_req(int, u_int32_t, void *);
+void   input_userauth_pk_ok(int, u_int32_t, void *);
+void   input_userauth_passwd_changereq(int, u_int32_t, void *);
+void   input_userauth_jpake_server_step1(int, u_int32_t, void *);
+void   input_userauth_jpake_server_step2(int, u_int32_t, void *);
+void   input_userauth_jpake_server_confirm(int, u_int32_t, void *);
+
+int    userauth_none(Authctxt *);
+int    userauth_pubkey(Authctxt *);
+int    userauth_passwd(Authctxt *);
+int    userauth_kbdint(Authctxt *);
+int    userauth_hostbased(Authctxt *);
+int    userauth_jpake(Authctxt *);
+
+void   userauth_jpake_cleanup(Authctxt *);
+
+#ifdef GSSAPI
+int    userauth_gssapi(Authctxt *authctxt);
+void   input_gssapi_response(int type, u_int32_t, void *);
+void   input_gssapi_token(int type, u_int32_t, void *);
+void   input_gssapi_hash(int type, u_int32_t, void *);
+void   input_gssapi_error(int, u_int32_t, void *);
+void   input_gssapi_errtok(int, u_int32_t, void *);
+#endif
+
+void   userauth(Authctxt *, char *);
+
+static int sign_and_send_pubkey(Authctxt *, Identity *);
+static void pubkey_prepare(Authctxt *);
+static void pubkey_cleanup(Authctxt *);
+static Key *load_identity_file(char *);
+
+static Authmethod *authmethod_get(char *authlist);
+static Authmethod *authmethod_lookup(const char *name);
+static char *authmethods_get(void);
+
+Authmethod authmethods[] = {
+#ifdef GSSAPI
+       {"gssapi-with-mic",
+               userauth_gssapi,
+               NULL,
+               &options.gss_authentication,
+               NULL},
+#endif
+       {"hostbased",
+               userauth_hostbased,
+               NULL,
+               &options.hostbased_authentication,
+               NULL},
+       {"publickey",
+               userauth_pubkey,
+               NULL,
+               &options.pubkey_authentication,
+               NULL},
+#ifdef JPAKE
+       {"jpake-01@openssh.com",
+               userauth_jpake,
+               userauth_jpake_cleanup,
+               &options.zero_knowledge_password_authentication,
+               &options.batch_mode},
+#endif
+       {"keyboard-interactive",
+               userauth_kbdint,
+               NULL,
+               &options.kbd_interactive_authentication,
+               &options.batch_mode},
+       {"password",
+               userauth_passwd,
+               NULL,
+               &options.password_authentication,
+               &options.batch_mode},
+       {"none",
+               userauth_none,
+               NULL,
+               NULL,
+               NULL},
+       {NULL, NULL, NULL, NULL, NULL}
+};
+
+void
+ssh_userauth2(const char *local_user, const char *server_user, char *host,
+    Sensitive *sensitive)
+{
+       Authctxt authctxt;
+       int type;
+
+       if (options.challenge_response_authentication)
+               options.kbd_interactive_authentication = 1;
+
+       packet_start(SSH2_MSG_SERVICE_REQUEST);
+       packet_put_cstring("ssh-userauth");
+       packet_send();
+       debug("SSH2_MSG_SERVICE_REQUEST sent");
+       packet_write_wait();
+       type = packet_read();
+       if (type != SSH2_MSG_SERVICE_ACCEPT)
+               fatal("Server denied authentication request: %d", type);
+       if (packet_remaining() > 0) {
+               char *reply = packet_get_string(NULL);
+               debug2("service_accept: %s", reply);
+               xfree(reply);
+       } else {
+               debug2("buggy server: service_accept w/o service");
+       }
+       packet_check_eom();
+       debug("SSH2_MSG_SERVICE_ACCEPT received");
+
+       if (options.preferred_authentications == NULL)
+               options.preferred_authentications = authmethods_get();
+
+       /* setup authentication context */
+       memset(&authctxt, 0, sizeof(authctxt));
+       pubkey_prepare(&authctxt);
+       authctxt.server_user = server_user;
+       authctxt.local_user = local_user;
+       authctxt.host = host;
+       authctxt.service = "ssh-connection";            /* service name */
+       authctxt.success = 0;
+       authctxt.method = authmethod_lookup("none");
+       authctxt.authlist = NULL;
+       authctxt.methoddata = NULL;
+       authctxt.sensitive = sensitive;
+       authctxt.info_req_seen = 0;
+       if (authctxt.method == NULL)
+               fatal("ssh_userauth2: internal error: cannot send userauth none request");
+
+       /* initial userauth request */
+       userauth_none(&authctxt);
+
+       dispatch_init(&input_userauth_error);
+       dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
+       dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
+       dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
+       dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt);     /* loop until success */
+
+       pubkey_cleanup(&authctxt);
+       dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
+
+       debug("Authentication succeeded (%s).", authctxt.method->name);
+}
+
+void
+userauth(Authctxt *authctxt, char *authlist)
+{
+       if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
+               authctxt->method->cleanup(authctxt);
+
+       if (authctxt->methoddata) {
+               xfree(authctxt->methoddata);
+               authctxt->methoddata = NULL;
+       }
+       if (authlist == NULL) {
+               authlist = authctxt->authlist;
+       } else {
+               if (authctxt->authlist)
+                       xfree(authctxt->authlist);
+               authctxt->authlist = authlist;
+       }
+       for (;;) {
+               Authmethod *method = authmethod_get(authlist);
+               if (method == NULL)
+                       fatal("Permission denied (%s).", authlist);
+               authctxt->method = method;
+
+               /* reset the per method handler */
+               dispatch_range(SSH2_MSG_USERAUTH_PER_METHOD_MIN,
+                   SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL);
+
+               /* and try new method */
+               if (method->userauth(authctxt) != 0) {
+                       debug2("we sent a %s packet, wait for reply", method->name);
+                       break;
+               } else {
+                       debug2("we did not send a packet, disable method");
+                       method->enabled = NULL;
+               }
+       }
+}
+
+/* ARGSUSED */
+void
+input_userauth_error(int type, u_int32_t seq, void *ctxt)
+{
+       fatal("input_userauth_error: bad message during authentication: "
+           "type %d", type);
+}
+
+/* ARGSUSED */
+void
+input_userauth_banner(int type, u_int32_t seq, void *ctxt)
+{
+       char *msg, *raw, *lang;
+       u_int len;
+
+       debug3("input_userauth_banner");
+       raw = packet_get_string(&len);
+       lang = packet_get_string(NULL);
+       if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) {
+               if (len > 65536)
+                       len = 65536;
+               msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */
+               strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL|VIS_NOSLASH);
+               fprintf(stderr, "%s", msg);
+               xfree(msg);
+       }
+       xfree(raw);
+       xfree(lang);
+}
+
+/* ARGSUSED */
+void
+input_userauth_success(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_success: no authentication context");
+       if (authctxt->authlist) {
+               xfree(authctxt->authlist);
+               authctxt->authlist = NULL;
+       }
+       if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
+               authctxt->method->cleanup(authctxt);
+       if (authctxt->methoddata) {
+               xfree(authctxt->methoddata);
+               authctxt->methoddata = NULL;
+       }
+       authctxt->success = 1;                  /* break out */
+}
+
+void
+input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+
+       if (authctxt == NULL)
+               fatal("%s: no authentication context", __func__);
+
+       fatal("Unexpected authentication success during %s.",
+           authctxt->method->name);
+}
+
+/* ARGSUSED */
+void
+input_userauth_failure(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       char *authlist = NULL;
+       int partial;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_failure: no authentication context");
+
+       authlist = packet_get_string(NULL);
+       partial = packet_get_char();
+       packet_check_eom();
+
+       if (partial != 0)
+               logit("Authenticated with partial success.");
+       debug("Authentications that can continue: %s", authlist);
+
+       userauth(authctxt, authlist);
+}
+
+/* ARGSUSED */
+void
+input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Key *key = NULL;
+       Identity *id = NULL;
+       Buffer b;
+       int pktype, sent = 0;
+       u_int alen, blen;
+       char *pkalg, *fp;
+       u_char *pkblob;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_pk_ok: no authentication context");
+       if (datafellows & SSH_BUG_PKOK) {
+               /* this is similar to SSH_BUG_PKAUTH */
+               debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
+               pkblob = packet_get_string(&blen);
+               buffer_init(&b);
+               buffer_append(&b, pkblob, blen);
+               pkalg = buffer_get_string(&b, &alen);
+               buffer_free(&b);
+       } else {
+               pkalg = packet_get_string(&alen);
+               pkblob = packet_get_string(&blen);
+       }
+       packet_check_eom();
+
+       debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
+
+       if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
+               debug("unknown pkalg %s", pkalg);
+               goto done;
+       }
+       if ((key = key_from_blob(pkblob, blen)) == NULL) {
+               debug("no key from blob. pkalg %s", pkalg);
+               goto done;
+       }
+       if (key->type != pktype) {
+               error("input_userauth_pk_ok: type mismatch "
+                   "for decoded key (received %d, expected %d)",
+                   key->type, pktype);
+               goto done;
+       }
+       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+       debug2("input_userauth_pk_ok: fp %s", fp);
+       xfree(fp);
+
+       /*
+        * search keys in the reverse order, because last candidate has been
+        * moved to the end of the queue.  this also avoids confusion by
+        * duplicate keys
+        */
+       TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) {
+               if (key_equal(key, id->key)) {
+                       sent = sign_and_send_pubkey(authctxt, id);
+                       break;
+               }
+       }
+done:
+       if (key != NULL)
+               key_free(key);
+       xfree(pkalg);
+       xfree(pkblob);
+
+       /* try another method if we did not send a packet */
+       if (sent == 0)
+               userauth(authctxt, NULL);
+}
+
+#ifdef GSSAPI
+int
+userauth_gssapi(Authctxt *authctxt)
+{
+       Gssctxt *gssctxt = NULL;
+       static gss_OID_set gss_supported = NULL;
+       static u_int mech = 0;
+       OM_uint32 min;
+       int ok = 0;
+
+       /* Try one GSSAPI method at a time, rather than sending them all at
+        * once. */
+
+       if (gss_supported == NULL)
+               gss_indicate_mechs(&min, &gss_supported);
+
+       /* Check to see if the mechanism is usable before we offer it */
+       while (mech < gss_supported->count && !ok) {
+               /* My DER encoding requires length<128 */
+               if (gss_supported->elements[mech].length < 128 &&
+                   ssh_gssapi_check_mechanism(&gssctxt, 
+                   &gss_supported->elements[mech], authctxt->host)) {
+                       ok = 1; /* Mechanism works */
+               } else {
+                       mech++;
+               }
+       }
+
+       if (!ok)
+               return 0;
+
+       authctxt->methoddata=(void *)gssctxt;
+
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+
+       packet_put_int(1);
+
+       packet_put_int((gss_supported->elements[mech].length) + 2);
+       packet_put_char(SSH_GSS_OIDTYPE);
+       packet_put_char(gss_supported->elements[mech].length);
+       packet_put_raw(gss_supported->elements[mech].elements,
+           gss_supported->elements[mech].length);
+
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
+
+       mech++; /* Move along to next candidate */
+
+       return 1;
+}
+
+static OM_uint32
+process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt = authctxt->methoddata;
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc gssbuf;
+       OM_uint32 status, ms, flags;
+       Buffer b;
+
+       status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+           recv_tok, &send_tok, &flags);
+
+       if (send_tok.length > 0) {
+               if (GSS_ERROR(status))
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+               else
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+
+               packet_put_string(send_tok.value, send_tok.length);
+               packet_send();
+               gss_release_buffer(&ms, &send_tok);
+       }
+
+       if (status == GSS_S_COMPLETE) {
+               /* send either complete or MIC, depending on mechanism */
+               if (!(flags & GSS_C_INTEG_FLAG)) {
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
+                       packet_send();
+               } else {
+                       ssh_gssapi_buildmic(&b, authctxt->server_user,
+                           authctxt->service, "gssapi-with-mic");
+
+                       gssbuf.value = buffer_ptr(&b);
+                       gssbuf.length = buffer_len(&b);
+
+                       status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
+
+                       if (!GSS_ERROR(status)) {
+                               packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC);
+                               packet_put_string(mic.value, mic.length);
+
+                               packet_send();
+                       }
+
+                       buffer_free(&b);
+                       gss_release_buffer(&ms, &mic);
+               }
+       }
+
+       return status;
+}
+
+/* ARGSUSED */
+void
+input_gssapi_response(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       int oidlen;
+       char *oidv;
+
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+       gssctxt = authctxt->methoddata;
+
+       /* Setup our OID */
+       oidv = packet_get_string(&oidlen);
+
+       if (oidlen <= 2 ||
+           oidv[0] != SSH_GSS_OIDTYPE ||
+           oidv[1] != oidlen - 2) {
+               xfree(oidv);
+               debug("Badly encoded mechanism OID received");
+               userauth(authctxt, NULL);
+               return;
+       }
+
+       if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2))
+               fatal("Server returned different OID than expected");
+
+       packet_check_eom();
+
+       xfree(oidv);
+
+       if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
+               /* Start again with next method on list */
+               debug("Trying to start again");
+               userauth(authctxt, NULL);
+               return;
+       }
+}
+
+/* ARGSUSED */
+void
+input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       gss_buffer_desc recv_tok;
+       OM_uint32 status;
+       u_int slen;
+
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+
+       recv_tok.value = packet_get_string(&slen);
+       recv_tok.length = slen; /* safe typecast */
+
+       packet_check_eom();
+
+       status = process_gssapi_token(ctxt, &recv_tok);
+
+       xfree(recv_tok.value);
+
+       if (GSS_ERROR(status)) {
+               /* Start again with the next method in the list */
+               userauth(authctxt, NULL);
+               return;
+       }
+}
+
+/* ARGSUSED */
+void
+input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc recv_tok;
+       OM_uint32 status, ms;
+       u_int len;
+
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+       gssctxt = authctxt->methoddata;
+
+       recv_tok.value = packet_get_string(&len);
+       recv_tok.length = len;
+
+       packet_check_eom();
+
+       /* Stick it into GSSAPI and see what it says */
+       status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+           &recv_tok, &send_tok, NULL);
+
+       xfree(recv_tok.value);
+       gss_release_buffer(&ms, &send_tok);
+
+       /* Server will be returning a failed packet after this one */
+}
+
+/* ARGSUSED */
+void
+input_gssapi_error(int type, u_int32_t plen, void *ctxt)
+{
+       OM_uint32 maj, min;
+       char *msg;
+       char *lang;
+
+       maj=packet_get_int();
+       min=packet_get_int();
+       msg=packet_get_string(NULL);
+       lang=packet_get_string(NULL);
+
+       packet_check_eom();
+
+       debug("Server GSSAPI Error:\n%s", msg);
+       xfree(msg);
+       xfree(lang);
+}
+#endif /* GSSAPI */
+
+int
+userauth_none(Authctxt *authctxt)
+{
+       /* initial userauth request */
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_send();
+       return 1;
+}
+
+int
+userauth_passwd(Authctxt *authctxt)
+{
+       static int attempt = 0;
+       char prompt[150];
+       char *password;
+       const char *host = options.host_key_alias ?  options.host_key_alias :
+           authctxt->host;
+
+       if (attempt++ >= options.number_of_password_prompts)
+               return 0;
+
+       if (attempt != 1)
+               error("Permission denied, please try again.");
+
+       snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
+           authctxt->server_user, host);
+       password = read_passphrase(prompt, 0);
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_char(0);
+       packet_put_cstring(password);
+       memset(password, 0, strlen(password));
+       xfree(password);
+       packet_add_padding(64);
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+           &input_userauth_passwd_changereq);
+
+       return 1;
+}
+
+/*
+ * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
+ */
+/* ARGSUSED */
+void
+input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       char *info, *lang, *password = NULL, *retype = NULL;
+       char prompt[150];
+       const char *host = options.host_key_alias ? options.host_key_alias :
+           authctxt->host;
+
+       debug2("input_userauth_passwd_changereq");
+
+       if (authctxt == NULL)
+               fatal("input_userauth_passwd_changereq: "
+                   "no authentication context");
+
+       info = packet_get_string(NULL);
+       lang = packet_get_string(NULL);
+       if (strlen(info) > 0)
+               logit("%s", info);
+       xfree(info);
+       xfree(lang);
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_char(1);                     /* additional info */
+       snprintf(prompt, sizeof(prompt),
+           "Enter %.30s@%.128s's old password: ",
+           authctxt->server_user, host);
+       password = read_passphrase(prompt, 0);
+       packet_put_cstring(password);
+       memset(password, 0, strlen(password));
+       xfree(password);
+       password = NULL;
+       while (password == NULL) {
+               snprintf(prompt, sizeof(prompt),
+                   "Enter %.30s@%.128s's new password: ",
+                   authctxt->server_user, host);
+               password = read_passphrase(prompt, RP_ALLOW_EOF);
+               if (password == NULL) {
+                       /* bail out */
+                       return;
+               }
+               snprintf(prompt, sizeof(prompt),
+                   "Retype %.30s@%.128s's new password: ",
+                   authctxt->server_user, host);
+               retype = read_passphrase(prompt, 0);
+               if (strcmp(password, retype) != 0) {
+                       memset(password, 0, strlen(password));
+                       xfree(password);
+                       logit("Mismatch; try again, EOF to quit.");
+                       password = NULL;
+               }
+               memset(retype, 0, strlen(retype));
+               xfree(retype);
+       }
+       packet_put_cstring(password);
+       memset(password, 0, strlen(password));
+       xfree(password);
+       packet_add_padding(64);
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+           &input_userauth_passwd_changereq);
+}
+
+#ifdef JPAKE
+static char *
+pw_encrypt(const char *password, const char *crypt_scheme, const char *salt)
+{
+       /* OpenBSD crypt(3) handles all of these */
+       if (strcmp(crypt_scheme, "crypt") == 0 ||
+           strcmp(crypt_scheme, "bcrypt") == 0 ||
+           strcmp(crypt_scheme, "md5crypt") == 0 ||
+           strcmp(crypt_scheme, "crypt-extended") == 0)
+               return xstrdup(crypt(password, salt));
+       error("%s: unsupported password encryption scheme \"%.100s\"",
+           __func__, crypt_scheme);
+       return NULL;
+}
+
+static BIGNUM *
+jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme,
+    const char *salt)
+{
+       char prompt[256], *password, *crypted;
+       u_char *secret;
+       u_int secret_len;
+       BIGNUM *ret;
+
+       snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ",
+           authctxt->server_user, authctxt->host);
+       password = read_passphrase(prompt, 0);
+
+       if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) {
+               logit("Disabling %s authentication", authctxt->method->name);
+               authctxt->method->enabled = NULL;
+               /* Continue with an empty password to fail gracefully */
+               crypted = xstrdup("");
+       }
+
+#ifdef JPAKE_DEBUG
+       debug3("%s: salt = %s", __func__, salt);
+       debug3("%s: scheme = %s", __func__, crypt_scheme);
+       debug3("%s: crypted = %s", __func__, crypted);
+#endif
+
+       if (hash_buffer(crypted, strlen(crypted), EVP_sha256(),
+           &secret, &secret_len) != 0)
+               fatal("%s: hash_buffer", __func__);
+
+       bzero(password, strlen(password));
+       bzero(crypted, strlen(crypted));
+       xfree(password);
+       xfree(crypted);
+
+       if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL)
+               fatal("%s: BN_bin2bn (secret)", __func__);
+       bzero(secret, secret_len);
+       xfree(secret);
+
+       return ret;
+}
+
+/* ARGSUSED */
+void
+input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       struct jpake_ctx *pctx = authctxt->methoddata;
+       u_char *x3_proof, *x4_proof, *x2_s_proof;
+       u_int x3_proof_len, x4_proof_len, x2_s_proof_len;
+       char *crypt_scheme, *salt;
+
+       /* Disable this message */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL);
+
+       if ((pctx->g_x3 = BN_new()) == NULL ||
+           (pctx->g_x4 = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       /* Fetch step 1 values */
+       crypt_scheme = packet_get_string(NULL);
+       salt = packet_get_string(NULL);
+       pctx->server_id = packet_get_string(&pctx->server_id_len);
+       packet_get_bignum2(pctx->g_x3);
+       packet_get_bignum2(pctx->g_x4);
+       x3_proof = packet_get_string(&x3_proof_len);
+       x4_proof = packet_get_string(&x4_proof_len);
+       packet_check_eom();
+
+       JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
+
+       /* Obtain password and derive secret */
+       pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt);
+       bzero(crypt_scheme, strlen(crypt_scheme));
+       bzero(salt, strlen(salt));
+       xfree(crypt_scheme);
+       xfree(salt);
+       JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__));
+
+       /* Calculate step 2 values */
+       jpake_step2(pctx->grp, pctx->s, pctx->g_x1,
+           pctx->g_x3, pctx->g_x4, pctx->x2,
+           pctx->server_id, pctx->server_id_len,
+           pctx->client_id, pctx->client_id_len,
+           x3_proof, x3_proof_len,
+           x4_proof, x4_proof_len,
+           &pctx->a,
+           &x2_s_proof, &x2_s_proof_len);
+
+       bzero(x3_proof, x3_proof_len);
+       bzero(x4_proof, x4_proof_len);
+       xfree(x3_proof);
+       xfree(x4_proof);
+
+       JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
+
+       /* Send values for step 2 */
+       packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2);
+       packet_put_bignum2(pctx->a);
+       packet_put_string(x2_s_proof, x2_s_proof_len);
+       packet_send();
+
+       bzero(x2_s_proof, x2_s_proof_len);
+       xfree(x2_s_proof);
+
+       /* Expect step 2 packet from peer */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2,
+           input_userauth_jpake_server_step2);
+}
+
+/* ARGSUSED */
+void
+input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       struct jpake_ctx *pctx = authctxt->methoddata;
+       u_char *x4_s_proof;
+       u_int x4_s_proof_len;
+
+       /* Disable this message */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL);
+
+       if ((pctx->b = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       /* Fetch step 2 values */
+       packet_get_bignum2(pctx->b);
+       x4_s_proof = packet_get_string(&x4_s_proof_len);
+       packet_check_eom();
+
+       JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
+
+       /* Derive shared key and calculate confirmation hash */
+       jpake_key_confirm(pctx->grp, pctx->s, pctx->b,
+           pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4,
+           pctx->client_id, pctx->client_id_len,
+           pctx->server_id, pctx->server_id_len,
+           session_id2, session_id2_len,
+           x4_s_proof, x4_s_proof_len,
+           &pctx->k,
+           &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len);
+
+       bzero(x4_s_proof, x4_s_proof_len);
+       xfree(x4_s_proof);
+
+       JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
+
+       /* Send key confirmation proof */
+       packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM);
+       packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
+       packet_send();
+
+       /* Expect confirmation from peer */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM,
+           input_userauth_jpake_server_confirm);
+}
+
+/* ARGSUSED */
+void
+input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       struct jpake_ctx *pctx = authctxt->methoddata;
+
+       /* Disable this message */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL);
+
+       pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len);
+       packet_check_eom();
+
+       JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
+
+       /* Verify expected confirmation hash */
+       if (jpake_check_confirm(pctx->k,
+           pctx->server_id, pctx->server_id_len,
+           session_id2, session_id2_len,
+           pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1)
+               debug("%s: %s success", __func__, authctxt->method->name);
+       else {
+               debug("%s: confirmation mismatch", __func__);
+               /* XXX stash this so if auth succeeds then we can warn/kill */
+       }
+
+       userauth_jpake_cleanup(authctxt);
+}
+#endif /* JPAKE */
+
+static int
+identity_sign(Identity *id, u_char **sigp, u_int *lenp,
+    u_char *data, u_int datalen)
+{
+       Key *prv;
+       int ret;
+
+       /* the agent supports this key */
+       if (id->ac)
+               return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
+                   data, datalen));
+       /*
+        * we have already loaded the private key or
+        * the private key is stored in external hardware
+        */
+       if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
+               return (key_sign(id->key, sigp, lenp, data, datalen));
+       /* load the private key from the file */
+       if ((prv = load_identity_file(id->filename)) == NULL)
+               return (-1);
+       ret = key_sign(prv, sigp, lenp, data, datalen);
+       key_free(prv);
+       return (ret);
+}
+
+static int
+sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
+{
+       Buffer b;
+       u_char *blob, *signature;
+       u_int bloblen, slen;
+       u_int skip = 0;
+       int ret = -1;
+       int have_sig = 1;
+       char *fp;
+
+       fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+       debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
+       xfree(fp);
+
+       if (key_to_blob(id->key, &blob, &bloblen) == 0) {
+               /* we cannot handle this key */
+               debug3("sign_and_send_pubkey: cannot handle key");
+               return 0;
+       }
+       /* data to be signed */
+       buffer_init(&b);
+       if (datafellows & SSH_OLD_SESSIONID) {
+               buffer_append(&b, session_id2, session_id2_len);
+               skip = session_id2_len;
+       } else {
+               buffer_put_string(&b, session_id2, session_id2_len);
+               skip = buffer_len(&b);
+       }
+       buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+       buffer_put_cstring(&b, authctxt->server_user);
+       buffer_put_cstring(&b,
+           datafellows & SSH_BUG_PKSERVICE ?
+           "ssh-userauth" :
+           authctxt->service);
+       if (datafellows & SSH_BUG_PKAUTH) {
+               buffer_put_char(&b, have_sig);
+       } else {
+               buffer_put_cstring(&b, authctxt->method->name);
+               buffer_put_char(&b, have_sig);
+               buffer_put_cstring(&b, key_ssh_name(id->key));
+       }
+       buffer_put_string(&b, blob, bloblen);
+
+       /* generate signature */
+       ret = identity_sign(id, &signature, &slen,
+           buffer_ptr(&b), buffer_len(&b));
+       if (ret == -1) {
+               xfree(blob);
+               buffer_free(&b);
+               return 0;
+       }
+#ifdef DEBUG_PK
+       buffer_dump(&b);
+#endif
+       if (datafellows & SSH_BUG_PKSERVICE) {
+               buffer_clear(&b);
+               buffer_append(&b, session_id2, session_id2_len);
+               skip = session_id2_len;
+               buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+               buffer_put_cstring(&b, authctxt->server_user);
+               buffer_put_cstring(&b, authctxt->service);
+               buffer_put_cstring(&b, authctxt->method->name);
+               buffer_put_char(&b, have_sig);
+               if (!(datafellows & SSH_BUG_PKAUTH))
+                       buffer_put_cstring(&b, key_ssh_name(id->key));
+               buffer_put_string(&b, blob, bloblen);
+       }
+       xfree(blob);
+
+       /* append signature */
+       buffer_put_string(&b, signature, slen);
+       xfree(signature);
+
+       /* skip session id and packet type */
+       if (buffer_len(&b) < skip + 1)
+               fatal("userauth_pubkey: internal error");
+       buffer_consume(&b, skip + 1);
+
+       /* put remaining data from buffer into packet */
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_raw(buffer_ptr(&b), buffer_len(&b));
+       buffer_free(&b);
+       packet_send();
+
+       return 1;
+}
+
+static int
+send_pubkey_test(Authctxt *authctxt, Identity *id)
+{
+       u_char *blob;
+       u_int bloblen, have_sig = 0;
+
+       debug3("send_pubkey_test");
+
+       if (key_to_blob(id->key, &blob, &bloblen) == 0) {
+               /* we cannot handle this key */
+               debug3("send_pubkey_test: cannot handle key");
+               return 0;
+       }
+       /* register callback for USERAUTH_PK_OK message */
+       dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
+
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_char(have_sig);
+       if (!(datafellows & SSH_BUG_PKAUTH))
+               packet_put_cstring(key_ssh_name(id->key));
+       packet_put_string(blob, bloblen);
+       xfree(blob);
+       packet_send();
+       return 1;
+}
+
+static Key *
+load_identity_file(char *filename)
+{
+       Key *private;
+       char prompt[300], *passphrase;
+       int perm_ok = 0, quit, i;
+       struct stat st;
+
+       if (stat(filename, &st) < 0) {
+               debug3("no such identity: %s", filename);
+               return NULL;
+       }
+       private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok);
+       if (!perm_ok)
+               return NULL;
+       if (private == NULL) {
+               if (options.batch_mode)
+                       return NULL;
+               snprintf(prompt, sizeof prompt,
+                   "Enter passphrase for key '%.100s': ", filename);
+               for (i = 0; i < options.number_of_password_prompts; i++) {
+                       passphrase = read_passphrase(prompt, 0);
+                       if (strcmp(passphrase, "") != 0) {
+                               private = key_load_private_type(KEY_UNSPEC,
+                                   filename, passphrase, NULL, NULL);
+                               quit = 0;
+                       } else {
+                               debug2("no passphrase given, try next key");
+                               quit = 1;
+                       }
+                       memset(passphrase, 0, strlen(passphrase));
+                       xfree(passphrase);
+                       if (private != NULL || quit)
+                               break;
+                       debug2("bad passphrase given, try again...");
+               }
+       }
+       return private;
+}
+
+/*
+ * try keys in the following order:
+ *     1. agent keys that are found in the config file
+ *     2. other agent keys
+ *     3. keys that are only listed in the config file
+ */
+static void
+pubkey_prepare(Authctxt *authctxt)
+{
+       Identity *id;
+       Idlist agent, files, *preferred;
+       Key *key;
+       AuthenticationConnection *ac;
+       char *comment;
+       int i, found;
+
+       TAILQ_INIT(&agent);     /* keys from the agent */
+       TAILQ_INIT(&files);     /* keys from the config file */
+       preferred = &authctxt->keys;
+       TAILQ_INIT(preferred);  /* preferred order of keys */
+
+       /* list of keys stored in the filesystem */
+       for (i = 0; i < options.num_identity_files; i++) {
+               key = options.identity_keys[i];
+               if (key && key->type == KEY_RSA1)
+                       continue;
+               if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER)
+                       continue;
+               options.identity_keys[i] = NULL;
+               id = xcalloc(1, sizeof(*id));
+               id->key = key;
+               id->filename = xstrdup(options.identity_files[i]);
+               TAILQ_INSERT_TAIL(&files, id, next);
+       }
+       /* list of keys supported by the agent */
+       if ((ac = ssh_get_authentication_connection())) {
+               for (key = ssh_get_first_identity(ac, &comment, 2);
+                   key != NULL;
+                   key = ssh_get_next_identity(ac, &comment, 2)) {
+                       found = 0;
+                       TAILQ_FOREACH(id, &files, next) {
+                               /* agent keys from the config file are preferred */
+                               if (key_equal(key, id->key)) {
+                                       key_free(key);
+                                       xfree(comment);
+                                       TAILQ_REMOVE(&files, id, next);
+                                       TAILQ_INSERT_TAIL(preferred, id, next);
+                                       id->ac = ac;
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       if (!found && !options.identities_only) {
+                               id = xcalloc(1, sizeof(*id));
+                               id->key = key;
+                               id->filename = comment;
+                               id->ac = ac;
+                               TAILQ_INSERT_TAIL(&agent, id, next);
+                       }
+               }
+               /* append remaining agent keys */
+               for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
+                       TAILQ_REMOVE(&agent, id, next);
+                       TAILQ_INSERT_TAIL(preferred, id, next);
+               }
+               authctxt->agent = ac;
+       }
+       /* append remaining keys from the config file */
+       for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
+               TAILQ_REMOVE(&files, id, next);
+               TAILQ_INSERT_TAIL(preferred, id, next);
+       }
+       TAILQ_FOREACH(id, preferred, next) {
+               debug2("key: %s (%p)", id->filename, id->key);
+       }
+}
+
+static void
+pubkey_cleanup(Authctxt *authctxt)
+{
+       Identity *id;
+
+       if (authctxt->agent != NULL)
+               ssh_close_authentication_connection(authctxt->agent);
+       for (id = TAILQ_FIRST(&authctxt->keys); id;
+           id = TAILQ_FIRST(&authctxt->keys)) {
+               TAILQ_REMOVE(&authctxt->keys, id, next);
+               if (id->key)
+                       key_free(id->key);
+               if (id->filename)
+                       xfree(id->filename);
+               xfree(id);
+       }
+}
+
+int
+userauth_pubkey(Authctxt *authctxt)
+{
+       Identity *id;
+       int sent = 0;
+
+       while ((id = TAILQ_FIRST(&authctxt->keys))) {
+               if (id->tried++)
+                       return (0);
+               /* move key to the end of the queue */
+               TAILQ_REMOVE(&authctxt->keys, id, next);
+               TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
+               /*
+                * send a test message if we have the public key. for
+                * encrypted keys we cannot do this and have to load the
+                * private key instead
+                */
+               if (id->key && id->key->type != KEY_RSA1) {
+                       debug("Offering %s public key: %s", key_type(id->key),
+                           id->filename);
+                       sent = send_pubkey_test(authctxt, id);
+               } else if (id->key == NULL) {
+                       debug("Trying private key: %s", id->filename);
+                       id->key = load_identity_file(id->filename);
+                       if (id->key != NULL) {
+                               id->isprivate = 1;
+                               sent = sign_and_send_pubkey(authctxt, id);
+                               key_free(id->key);
+                               id->key = NULL;
+                       }
+               }
+               if (sent)
+                       return (sent);
+       }
+       return (0);
+}
+
+/*
+ * Send userauth request message specifying keyboard-interactive method.
+ */
+int
+userauth_kbdint(Authctxt *authctxt)
+{
+       static int attempt = 0;
+
+       if (attempt++ >= options.number_of_password_prompts)
+               return 0;
+       /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
+       if (attempt > 1 && !authctxt->info_req_seen) {
+               debug3("userauth_kbdint: disable: no info_req_seen");
+               dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
+               return 0;
+       }
+
+       debug2("userauth_kbdint");
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_cstring("");                                 /* lang */
+       packet_put_cstring(options.kbd_interactive_devices ?
+           options.kbd_interactive_devices : "");
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
+       return 1;
+}
+
+/*
+ * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
+ */
+void
+input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       char *name, *inst, *lang, *prompt, *response;
+       u_int num_prompts, i;
+       int echo = 0;
+
+       debug2("input_userauth_info_req");
+
+       if (authctxt == NULL)
+               fatal("input_userauth_info_req: no authentication context");
+
+       authctxt->info_req_seen = 1;
+
+       name = packet_get_string(NULL);
+       inst = packet_get_string(NULL);
+       lang = packet_get_string(NULL);
+       if (strlen(name) > 0)
+               logit("%s", name);
+       if (strlen(inst) > 0)
+               logit("%s", inst);
+       xfree(name);
+       xfree(inst);
+       xfree(lang);
+
+       num_prompts = packet_get_int();
+       /*
+        * Begin to build info response packet based on prompts requested.
+        * We commit to providing the correct number of responses, so if
+        * further on we run into a problem that prevents this, we have to
+        * be sure and clean this up and send a correct error response.
+        */
+       packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
+       packet_put_int(num_prompts);
+
+       debug2("input_userauth_info_req: num_prompts %d", num_prompts);
+       for (i = 0; i < num_prompts; i++) {
+               prompt = packet_get_string(NULL);
+               echo = packet_get_char();
+
+               response = read_passphrase(prompt, echo ? RP_ECHO : 0);
+
+               packet_put_cstring(response);
+               memset(response, 0, strlen(response));
+               xfree(response);
+               xfree(prompt);
+       }
+       packet_check_eom(); /* done with parsing incoming message. */
+
+       packet_add_padding(64);
+       packet_send();
+}
+
+static int
+ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
+    u_char *data, u_int datalen)
+{
+       Buffer b;
+       struct stat st;
+       pid_t pid;
+       int to[2], from[2], status, version = 2;
+
+       debug2("ssh_keysign called");
+
+       if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
+               error("ssh_keysign: not installed: %s", strerror(errno));
+               return -1;
+       }
+       if (fflush(stdout) != 0)
+               error("ssh_keysign: fflush: %s", strerror(errno));
+       if (pipe(to) < 0) {
+               error("ssh_keysign: pipe: %s", strerror(errno));
+               return -1;
+       }
+       if (pipe(from) < 0) {
+               error("ssh_keysign: pipe: %s", strerror(errno));
+               return -1;
+       }
+       if ((pid = fork()) < 0) {
+               error("ssh_keysign: fork: %s", strerror(errno));
+               return -1;
+       }
+       if (pid == 0) {
+               /* keep the socket on exec */
+               fcntl(packet_get_connection_in(), F_SETFD, 0);
+               permanently_drop_suid(getuid());
+               close(from[0]);
+               if (dup2(from[1], STDOUT_FILENO) < 0)
+                       fatal("ssh_keysign: dup2: %s", strerror(errno));
+               close(to[1]);
+               if (dup2(to[0], STDIN_FILENO) < 0)
+                       fatal("ssh_keysign: dup2: %s", strerror(errno));
+               close(from[1]);
+               close(to[0]);
+               execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
+               fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
+                   strerror(errno));
+       }
+       close(from[1]);
+       close(to[0]);
+
+       buffer_init(&b);
+       buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
+       buffer_put_string(&b, data, datalen);
+       if (ssh_msg_send(to[1], version, &b) == -1)
+               fatal("ssh_keysign: couldn't send request");
+
+       if (ssh_msg_recv(from[0], &b) < 0) {
+               error("ssh_keysign: no reply");
+               buffer_free(&b);
+               return -1;
+       }
+       close(from[0]);
+       close(to[1]);
+
+       while (waitpid(pid, &status, 0) < 0)
+               if (errno != EINTR)
+                       break;
+
+       if (buffer_get_char(&b) != version) {
+               error("ssh_keysign: bad version");
+               buffer_free(&b);
+               return -1;
+       }
+       *sigp = buffer_get_string(&b, lenp);
+       buffer_free(&b);
+
+       return 0;
+}
+
+int
+userauth_hostbased(Authctxt *authctxt)
+{
+       Key *private = NULL;
+       Sensitive *sensitive = authctxt->sensitive;
+       Buffer b;
+       u_char *signature, *blob;
+       char *chost, *pkalg, *p;
+       const char *service;
+       u_int blen, slen;
+       int ok, i, found = 0;
+
+       /* check for a useful key */
+       for (i = 0; i < sensitive->nkeys; i++) {
+               private = sensitive->keys[i];
+               if (private && private->type != KEY_RSA1) {
+                       found = 1;
+                       /* we take and free the key */
+                       sensitive->keys[i] = NULL;
+                       break;
+               }
+       }
+       if (!found) {
+               debug("No more client hostkeys for hostbased authentication.");
+               return 0;
+       }
+       if (key_to_blob(private, &blob, &blen) == 0) {
+               key_free(private);
+               return 0;
+       }
+       /* figure out a name for the client host */
+       p = get_local_name(packet_get_connection_in());
+       if (p == NULL) {
+               error("userauth_hostbased: cannot get local ipaddr/name");
+               key_free(private);
+               xfree(blob);
+               return 0;
+       }
+       xasprintf(&chost, "%s.", p);
+       debug2("userauth_hostbased: chost %s", chost);
+       xfree(p);
+
+       service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
+           authctxt->service;
+       pkalg = xstrdup(key_ssh_name(private));
+       buffer_init(&b);
+       /* construct data */
+       buffer_put_string(&b, session_id2, session_id2_len);
+       buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+       buffer_put_cstring(&b, authctxt->server_user);
+       buffer_put_cstring(&b, service);
+       buffer_put_cstring(&b, authctxt->method->name);
+       buffer_put_cstring(&b, pkalg);
+       buffer_put_string(&b, blob, blen);
+       buffer_put_cstring(&b, chost);
+       buffer_put_cstring(&b, authctxt->local_user);
+#ifdef DEBUG_PK
+       buffer_dump(&b);
+#endif
+       if (sensitive->external_keysign)
+               ok = ssh_keysign(private, &signature, &slen,
+                   buffer_ptr(&b), buffer_len(&b));
+       else
+               ok = key_sign(private, &signature, &slen,
+                   buffer_ptr(&b), buffer_len(&b));
+       key_free(private);
+       buffer_free(&b);
+       if (ok != 0) {
+               error("key_sign failed");
+               xfree(chost);
+               xfree(pkalg);
+               xfree(blob);
+               return 0;
+       }
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_cstring(pkalg);
+       packet_put_string(blob, blen);
+       packet_put_cstring(chost);
+       packet_put_cstring(authctxt->local_user);
+       packet_put_string(signature, slen);
+       memset(signature, 's', slen);
+       xfree(signature);
+       xfree(chost);
+       xfree(pkalg);
+       xfree(blob);
+
+       packet_send();
+       return 1;
+}
+
+#ifdef JPAKE
+int
+userauth_jpake(Authctxt *authctxt)
+{
+       struct jpake_ctx *pctx;
+       u_char *x1_proof, *x2_proof;
+       u_int x1_proof_len, x2_proof_len;
+       static int attempt = 0; /* XXX share with userauth_password's? */
+
+       if (attempt++ >= options.number_of_password_prompts)
+               return 0;
+       if (attempt != 1)
+               error("Permission denied, please try again.");
+
+       if (authctxt->methoddata != NULL)
+               fatal("%s: authctxt->methoddata already set (%p)",
+                   __func__, authctxt->methoddata);
+
+       authctxt->methoddata = pctx = jpake_new();
+
+       /*
+        * Send request immediately, to get the protocol going while
+        * we do the initial computations.
+        */
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_send();
+       packet_write_wait();
+
+       jpake_step1(pctx->grp,
+           &pctx->client_id, &pctx->client_id_len,
+           &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2,
+           &x1_proof, &x1_proof_len,
+           &x2_proof, &x2_proof_len);
+
+       JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
+
+       packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1);
+       packet_put_string(pctx->client_id, pctx->client_id_len);
+       packet_put_bignum2(pctx->g_x1);
+       packet_put_bignum2(pctx->g_x2);
+       packet_put_string(x1_proof, x1_proof_len);
+       packet_put_string(x2_proof, x2_proof_len);
+       packet_send();
+
+       bzero(x1_proof, x1_proof_len);
+       bzero(x2_proof, x2_proof_len);
+       xfree(x1_proof);
+       xfree(x2_proof);
+
+       /* Expect step 1 packet from peer */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1,
+           input_userauth_jpake_server_step1);
+       dispatch_set(SSH2_MSG_USERAUTH_SUCCESS,
+           &input_userauth_success_unexpected);
+
+       return 1;
+}
+
+void
+userauth_jpake_cleanup(Authctxt *authctxt)
+{
+       debug3("%s: clean up", __func__);
+       if (authctxt->methoddata != NULL) {
+               jpake_free(authctxt->methoddata);
+               authctxt->methoddata = NULL;
+       }
+       dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
+}
+#endif /* JPAKE */
+
+/* find auth method */
+
+/*
+ * given auth method name, if configurable options permit this method fill
+ * in auth_ident field and return true, otherwise return false.
+ */
+static int
+authmethod_is_enabled(Authmethod *method)
+{
+       if (method == NULL)
+               return 0;
+       /* return false if options indicate this method is disabled */
+       if  (method->enabled == NULL || *method->enabled == 0)
+               return 0;
+       /* return false if batch mode is enabled but method needs interactive mode */
+       if  (method->batch_flag != NULL && *method->batch_flag != 0)
+               return 0;
+       return 1;
+}
+
+static Authmethod *
+authmethod_lookup(const char *name)
+{
+       Authmethod *method = NULL;
+       if (name != NULL)
+               for (method = authmethods; method->name != NULL; method++)
+                       if (strcmp(name, method->name) == 0)
+                               return method;
+       debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
+       return NULL;
+}
+
+/* XXX internal state */
+static Authmethod *current = NULL;
+static char *supported = NULL;
+static char *preferred = NULL;
+
+/*
+ * Given the authentication method list sent by the server, return the
+ * next method we should try.  If the server initially sends a nil list,
+ * use a built-in default list.
+ */
+static Authmethod *
+authmethod_get(char *authlist)
+{
+       char *name = NULL;
+       u_int next;
+
+       /* Use a suitable default if we're passed a nil list.  */
+       if (authlist == NULL || strlen(authlist) == 0)
+               authlist = options.preferred_authentications;
+
+       if (supported == NULL || strcmp(authlist, supported) != 0) {
+               debug3("start over, passed a different list %s", authlist);
+               if (supported != NULL)
+                       xfree(supported);
+               supported = xstrdup(authlist);
+               preferred = options.preferred_authentications;
+               debug3("preferred %s", preferred);
+               current = NULL;
+       } else if (current != NULL && authmethod_is_enabled(current))
+               return current;
+
+       for (;;) {
+               if ((name = match_list(preferred, supported, &next)) == NULL) {
+                       debug("No more authentication methods to try.");
+                       current = NULL;
+                       return NULL;
+               }
+               preferred += next;
+               debug3("authmethod_lookup %s", name);
+               debug3("remaining preferred: %s", preferred);
+               if ((current = authmethod_lookup(name)) != NULL &&
+                   authmethod_is_enabled(current)) {
+                       debug3("authmethod_is_enabled %s", name);
+                       debug("Next authentication method: %s", name);
+                       xfree(name);
+                       return current;
+               }
+       }
+       if (name != NULL)
+               xfree(name);
+}
+
+static char *
+authmethods_get(void)
+{
+       Authmethod *method = NULL;
+       Buffer b;
+       char *list;
+
+       buffer_init(&b);
+       for (method = authmethods; method->name != NULL; method++) {
+               if (authmethod_is_enabled(method)) {
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       buffer_append(&b, method->name, strlen(method->name));
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       list = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       return list;
+}
+
diff --git a/.pc/gssapi.patch/sshd.c b/.pc/gssapi.patch/sshd.c
new file mode 100644 (file)
index 0000000..cc10395
--- /dev/null
@@ -0,0 +1,2371 @@
+/* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * This program is the ssh daemon.  It listens for connections from clients,
+ * and performs authentication, executes use commands or shell, and forwards
+ * information to/from the application to the user client over an encrypted
+ * connection.  This can also handle forwarding of X11, TCP/IP, and
+ * authentication agent connections.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 implementation:
+ * Privilege Separation:
+ *
+ * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2002 Niels Provos.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include "openbsd-compat/sys-tree.h"
+#include "openbsd-compat/sys-queue.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/md5.h>
+#include <openssl/rand.h>
+#include "openbsd-compat/openssl-compat.h"
+
+#ifdef HAVE_SECUREWARE
+#include <sys/security.h>
+#include <prot.h>
+#endif
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "rsa.h"
+#include "sshpty.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "dh.h"
+#include "myproposal.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "atomicio.h"
+#include "canohost.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "misc.h"
+#include "msg.h"
+#include "dispatch.h"
+#include "channels.h"
+#include "session.h"
+#include "monitor_mm.h"
+#include "monitor.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "roaming.h"
+#include "ssh-sandbox.h"
+#include "version.h"
+
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int allow_severity;
+int deny_severity;
+#endif /* LIBWRAP */
+
+#ifndef O_NOCTTY
+#define O_NOCTTY       0
+#endif
+
+/* Re-exec fds */
+#define REEXEC_DEVCRYPTO_RESERVED_FD   (STDERR_FILENO + 1)
+#define REEXEC_STARTUP_PIPE_FD         (STDERR_FILENO + 2)
+#define REEXEC_CONFIG_PASS_FD          (STDERR_FILENO + 3)
+#define REEXEC_MIN_FREE_FD             (STDERR_FILENO + 4)
+
+extern char *__progname;
+
+/* Server configuration options. */
+ServerOptions options;
+
+/* Name of the server configuration file. */
+char *config_file_name = _PATH_SERVER_CONFIG_FILE;
+
+/*
+ * Debug mode flag.  This can be set on the command line.  If debug
+ * mode is enabled, extra debugging output will be sent to the system
+ * log, the daemon will not go to background, and will exit after processing
+ * the first connection.
+ */
+int debug_flag = 0;
+
+/* Flag indicating that the daemon should only test the configuration and keys. */
+int test_flag = 0;
+
+/* Flag indicating that the daemon is being started from inetd. */
+int inetd_flag = 0;
+
+/* Flag indicating that sshd should not detach and become a daemon. */
+int no_daemon_flag = 0;
+
+/* debug goes to stderr unless inetd_flag is set */
+int log_stderr = 0;
+
+/* Saved arguments to main(). */
+char **saved_argv;
+int saved_argc;
+
+/* re-exec */
+int rexeced_flag = 0;
+int rexec_flag = 1;
+int rexec_argc = 0;
+char **rexec_argv;
+
+/*
+ * The sockets that the server is listening; this is used in the SIGHUP
+ * signal handler.
+ */
+#define        MAX_LISTEN_SOCKS        16
+int listen_socks[MAX_LISTEN_SOCKS];
+int num_listen_socks = 0;
+
+/*
+ * the client's version string, passed by sshd2 in compat mode. if != NULL,
+ * sshd will skip the version-number exchange
+ */
+char *client_version_string = NULL;
+char *server_version_string = NULL;
+
+/* for rekeying XXX fixme */
+Kex *xxx_kex;
+
+/*
+ * Any really sensitive data in the application is contained in this
+ * structure. The idea is that this structure could be locked into memory so
+ * that the pages do not get written into swap.  However, there are some
+ * problems. The private key contains BIGNUMs, and we do not (in principle)
+ * have access to the internals of them, and locking just the structure is
+ * not very useful.  Currently, memory locking is not implemented.
+ */
+struct {
+       Key     *server_key;            /* ephemeral server key */
+       Key     *ssh1_host_key;         /* ssh1 host key */
+       Key     **host_keys;            /* all private host keys */
+       Key     **host_certificates;    /* all public host certificates */
+       int     have_ssh1_key;
+       int     have_ssh2_key;
+       u_char  ssh1_cookie[SSH_SESSION_KEY_LENGTH];
+} sensitive_data;
+
+/*
+ * Flag indicating whether the RSA server key needs to be regenerated.
+ * Is set in the SIGALRM handler and cleared when the key is regenerated.
+ */
+static volatile sig_atomic_t key_do_regen = 0;
+
+/* This is set to true when a signal is received. */
+static volatile sig_atomic_t received_sighup = 0;
+static volatile sig_atomic_t received_sigterm = 0;
+
+/* session identifier, used by RSA-auth */
+u_char session_id[16];
+
+/* same for ssh2 */
+u_char *session_id2 = NULL;
+u_int session_id2_len = 0;
+
+/* record remote hostname or ip */
+u_int utmp_len = MAXHOSTNAMELEN;
+
+/* options.max_startup sized array of fd ints */
+int *startup_pipes = NULL;
+int startup_pipe;              /* in child */
+
+/* variables used for privilege separation */
+int use_privsep = -1;
+struct monitor *pmonitor = NULL;
+
+/* global authentication context */
+Authctxt *the_authctxt = NULL;
+
+/* sshd_config buffer */
+Buffer cfg;
+
+/* message to be displayed after login */
+Buffer loginmsg;
+
+/* Unprivileged user */
+struct passwd *privsep_pw = NULL;
+
+/* Prototypes for various functions defined later in this file. */
+void destroy_sensitive_data(void);
+void demote_sensitive_data(void);
+
+static void do_ssh1_kex(void);
+static void do_ssh2_kex(void);
+
+/*
+ * Close all listening sockets
+ */
+static void
+close_listen_socks(void)
+{
+       int i;
+
+       for (i = 0; i < num_listen_socks; i++)
+               close(listen_socks[i]);
+       num_listen_socks = -1;
+}
+
+static void
+close_startup_pipes(void)
+{
+       int i;
+
+       if (startup_pipes)
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               close(startup_pipes[i]);
+}
+
+/*
+ * Signal handler for SIGHUP.  Sshd execs itself when it receives SIGHUP;
+ * the effect is to reread the configuration file (and to regenerate
+ * the server key).
+ */
+
+/*ARGSUSED*/
+static void
+sighup_handler(int sig)
+{
+       int save_errno = errno;
+
+       received_sighup = 1;
+       signal(SIGHUP, sighup_handler);
+       errno = save_errno;
+}
+
+/*
+ * Called from the main program after receiving SIGHUP.
+ * Restarts the server.
+ */
+static void
+sighup_restart(void)
+{
+       logit("Received SIGHUP; restarting.");
+       close_listen_socks();
+       close_startup_pipes();
+       alarm(0);  /* alarm timer persists across exec */
+       signal(SIGHUP, SIG_IGN); /* will be restored after exec */
+       execv(saved_argv[0], saved_argv);
+       logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
+           strerror(errno));
+       exit(1);
+}
+
+/*
+ * Generic signal handler for terminating signals in the master daemon.
+ */
+/*ARGSUSED*/
+static void
+sigterm_handler(int sig)
+{
+       received_sigterm = sig;
+}
+
+/*
+ * SIGCHLD handler.  This is called whenever a child dies.  This will then
+ * reap any zombies left by exited children.
+ */
+/*ARGSUSED*/
+static void
+main_sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+           (pid < 0 && errno == EINTR))
+               ;
+
+       signal(SIGCHLD, main_sigchld_handler);
+       errno = save_errno;
+}
+
+/*
+ * Signal handler for the alarm after the login grace period has expired.
+ */
+/*ARGSUSED*/
+static void
+grace_alarm_handler(int sig)
+{
+       if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
+               kill(pmonitor->m_pid, SIGALRM);
+
+       /* Log error and exit. */
+       sigdie("Timeout before authentication for %s", get_remote_ipaddr());
+}
+
+/*
+ * Signal handler for the key regeneration alarm.  Note that this
+ * alarm only occurs in the daemon waiting for connections, and it does not
+ * do anything with the private key or random state before forking.
+ * Thus there should be no concurrency control/asynchronous execution
+ * problems.
+ */
+static void
+generate_ephemeral_server_key(void)
+{
+       verbose("Generating %s%d bit RSA key.",
+           sensitive_data.server_key ? "new " : "", options.server_key_bits);
+       if (sensitive_data.server_key != NULL)
+               key_free(sensitive_data.server_key);
+       sensitive_data.server_key = key_generate(KEY_RSA1,
+           options.server_key_bits);
+       verbose("RSA key generation complete.");
+
+       arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+       arc4random_stir();
+}
+
+/*ARGSUSED*/
+static void
+key_regeneration_alarm(int sig)
+{
+       int save_errno = errno;
+
+       signal(SIGALRM, SIG_DFL);
+       errno = save_errno;
+       key_do_regen = 1;
+}
+
+static void
+sshd_exchange_identification(int sock_in, int sock_out)
+{
+       u_int i;
+       int mismatch;
+       int remote_major, remote_minor;
+       int major, minor;
+       char *s, *newline = "\n";
+       char buf[256];                  /* Must not be larger than remote_version. */
+       char remote_version[256];       /* Must be at least as big as buf. */
+
+       if ((options.protocol & SSH_PROTO_1) &&
+           (options.protocol & SSH_PROTO_2)) {
+               major = PROTOCOL_MAJOR_1;
+               minor = 99;
+       } else if (options.protocol & SSH_PROTO_2) {
+               major = PROTOCOL_MAJOR_2;
+               minor = PROTOCOL_MINOR_2;
+               newline = "\r\n";
+       } else {
+               major = PROTOCOL_MAJOR_1;
+               minor = PROTOCOL_MINOR_1;
+       }
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+           SSH_VERSION, newline);
+       server_version_string = xstrdup(buf);
+
+       /* Send our protocol version identification. */
+       if (roaming_atomicio(vwrite, sock_out, server_version_string,
+           strlen(server_version_string))
+           != strlen(server_version_string)) {
+               logit("Could not write ident string to %s", get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+
+       /* Read other sides version identification. */
+       memset(buf, 0, sizeof(buf));
+       for (i = 0; i < sizeof(buf) - 1; i++) {
+               if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {
+                       logit("Did not receive identification string from %s",
+                           get_remote_ipaddr());
+                       cleanup_exit(255);
+               }
+               if (buf[i] == '\r') {
+                       buf[i] = 0;
+                       /* Kludge for F-Secure Macintosh < 1.0.2 */
+                       if (i == 12 &&
+                           strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
+                               break;
+                       continue;
+               }
+               if (buf[i] == '\n') {
+                       buf[i] = 0;
+                       break;
+               }
+       }
+       buf[sizeof(buf) - 1] = 0;
+       client_version_string = xstrdup(buf);
+
+       /*
+        * Check that the versions match.  In future this might accept
+        * several versions and set appropriate flags to handle them.
+        */
+       if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
+           &remote_major, &remote_minor, remote_version) != 3) {
+               s = "Protocol mismatch.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Bad protocol version identification '%.100s' from %s",
+                   client_version_string, get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+       debug("Client protocol version %d.%d; client software version %.100s",
+           remote_major, remote_minor, remote_version);
+
+       compat_datafellows(remote_version);
+
+       if (datafellows & SSH_BUG_PROBE) {
+               logit("probed from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       if (datafellows & SSH_BUG_SCANNER) {
+               logit("scanned from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       mismatch = 0;
+       switch (remote_major) {
+       case 1:
+               if (remote_minor == 99) {
+                       if (options.protocol & SSH_PROTO_2)
+                               enable_compat20();
+                       else
+                               mismatch = 1;
+                       break;
+               }
+               if (!(options.protocol & SSH_PROTO_1)) {
+                       mismatch = 1;
+                       break;
+               }
+               if (remote_minor < 3) {
+                       packet_disconnect("Your ssh version is too old and "
+                           "is no longer supported.  Please install a newer version.");
+               } else if (remote_minor == 3) {
+                       /* note that this disables agent-forwarding */
+                       enable_compat13();
+               }
+               break;
+       case 2:
+               if (options.protocol & SSH_PROTO_2) {
+                       enable_compat20();
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               mismatch = 1;
+               break;
+       }
+       chop(server_version_string);
+       debug("Local version string %.200s", server_version_string);
+
+       if (mismatch) {
+               s = "Protocol major versions differ.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Protocol major versions differ for %s: %.200s vs. %.200s",
+                   get_remote_ipaddr(),
+                   server_version_string, client_version_string);
+               cleanup_exit(255);
+       }
+}
+
+/* Destroy the host and server keys.  They will no longer be needed. */
+void
+destroy_sensitive_data(void)
+{
+       int i;
+
+       if (sensitive_data.server_key) {
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = NULL;
+       }
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = NULL;
+               }
+               if (sensitive_data.host_certificates[i]) {
+                       key_free(sensitive_data.host_certificates[i]);
+                       sensitive_data.host_certificates[i] = NULL;
+               }
+       }
+       sensitive_data.ssh1_host_key = NULL;
+       memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
+}
+
+/* Demote private to public keys for network child */
+void
+demote_sensitive_data(void)
+{
+       Key *tmp;
+       int i;
+
+       if (sensitive_data.server_key) {
+               tmp = key_demote(sensitive_data.server_key);
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = tmp;
+       }
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       tmp = key_demote(sensitive_data.host_keys[i]);
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = tmp;
+                       if (tmp->type == KEY_RSA1)
+                               sensitive_data.ssh1_host_key = tmp;
+               }
+               /* Certs do not need demotion */
+       }
+
+       /* We do not clear ssh1_host key and cookie.  XXX - Okay Niels? */
+}
+
+static void
+privsep_preauth_child(void)
+{
+       u_int32_t rnd[256];
+       gid_t gidset[1];
+
+       /* Enable challenge-response authentication for privilege separation */
+       privsep_challenge_enable();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       /* Change our root directory */
+       if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+               fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+                   strerror(errno));
+       if (chdir("/") == -1)
+               fatal("chdir(\"/\"): %s", strerror(errno));
+
+       /* Drop our privileges */
+       debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
+           (u_int)privsep_pw->pw_gid);
+#if 0
+       /* XXX not ready, too heavy after chroot */
+       do_setusercontext(privsep_pw);
+#else
+       gidset[0] = privsep_pw->pw_gid;
+       if (setgroups(1, gidset) < 0)
+               fatal("setgroups: %.100s", strerror(errno));
+       permanently_set_uid(privsep_pw);
+#endif
+}
+
+static int
+privsep_preauth(Authctxt *authctxt)
+{
+       int status;
+       pid_t pid;
+       struct ssh_sandbox *box = NULL;
+
+       /* Set up unprivileged child process to deal with network data */
+       pmonitor = monitor_init();
+       /* Store a pointer to the kex for later rekeying */
+       pmonitor->m_pkex = &xxx_kex;
+
+       if (use_privsep == PRIVSEP_SANDBOX)
+               box = ssh_sandbox_init();
+       pid = fork();
+       if (pid == -1) {
+               fatal("fork of unprivileged child failed");
+       } else if (pid != 0) {
+               debug2("Network child is on pid %ld", (long)pid);
+
+               if (box != NULL)
+                       ssh_sandbox_parent_preauth(box, pid);
+               pmonitor->m_pid = pid;
+               monitor_child_preauth(authctxt, pmonitor);
+
+               /* Sync memory */
+               monitor_sync(pmonitor);
+
+               /* Wait for the child's exit status */
+               while (waitpid(pid, &status, 0) < 0) {
+                       if (errno != EINTR)
+                               fatal("%s: waitpid: %s", __func__,
+                                   strerror(errno));
+               }
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status) != 0)
+                               fatal("%s: preauth child exited with status %d",
+                                   __func__, WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status))
+                       fatal("%s: preauth child terminated by signal %d",
+                           __func__, WTERMSIG(status));
+               if (box != NULL)
+                       ssh_sandbox_parent_finish(box);
+               return 1;
+       } else {
+               /* child */
+               close(pmonitor->m_sendfd);
+               close(pmonitor->m_log_recvfd);
+
+               /* Arrange for logging to be sent to the monitor */
+               set_log_handler(mm_log_handler, pmonitor);
+
+               /* Demote the child */
+               if (getuid() == 0 || geteuid() == 0)
+                       privsep_preauth_child();
+               setproctitle("%s", "[net]");
+               if (box != NULL)
+                       ssh_sandbox_child(box);
+
+               return 0;
+       }
+}
+
+static void
+privsep_postauth(Authctxt *authctxt)
+{
+       u_int32_t rnd[256];
+
+#ifdef DISABLE_FD_PASSING
+       if (1) {
+#else
+       if (authctxt->pw->pw_uid == 0 || options.use_login) {
+#endif
+               /* File descriptor passing is broken or root login */
+               use_privsep = 0;
+               goto skip;
+       }
+
+       /* New socket pair */
+       monitor_reinit(pmonitor);
+
+       pmonitor->m_pid = fork();
+       if (pmonitor->m_pid == -1)
+               fatal("fork of unprivileged child failed");
+       else if (pmonitor->m_pid != 0) {
+               verbose("User child is on pid %ld", (long)pmonitor->m_pid);
+               buffer_clear(&loginmsg);
+               monitor_child_postauth(pmonitor);
+
+               /* NEVERREACHED */
+               exit(0);
+       }
+
+       /* child */
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Drop privileges */
+       do_setusercontext(authctxt->pw);
+
+ skip:
+       /* It is safe now to apply the key state */
+       monitor_apply_keystate(pmonitor);
+
+       /*
+        * Tell the packet layer that authentication was successful, since
+        * this information is not part of the key state.
+        */
+       packet_set_authenticated();
+}
+
+static char *
+list_hostkey_types(void)
+{
+       Buffer b;
+       const char *p;
+       char *ret;
+       int i;
+       Key *key;
+
+       buffer_init(&b);
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = sensitive_data.host_keys[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+               /* If the private key has a cert peer, then list that too */
+               key = sensitive_data.host_certificates[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       ret = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       debug("list_hostkey_types: %s", ret);
+       return ret;
+}
+
+static Key *
+get_hostkey_by_type(int type, int need_private)
+{
+       int i;
+       Key *key;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               switch (type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       key = sensitive_data.host_certificates[i];
+                       break;
+               default:
+                       key = sensitive_data.host_keys[i];
+                       break;
+               }
+               if (key != NULL && key->type == type)
+                       return need_private ?
+                           sensitive_data.host_keys[i] : key;
+       }
+       return NULL;
+}
+
+Key *
+get_hostkey_public_by_type(int type)
+{
+       return get_hostkey_by_type(type, 0);
+}
+
+Key *
+get_hostkey_private_by_type(int type)
+{
+       return get_hostkey_by_type(type, 1);
+}
+
+Key *
+get_hostkey_by_index(int ind)
+{
+       if (ind < 0 || ind >= options.num_host_key_files)
+               return (NULL);
+       return (sensitive_data.host_keys[ind]);
+}
+
+int
+get_hostkey_index(Key *key)
+{
+       int i;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (key_is_cert(key)) {
+                       if (key == sensitive_data.host_certificates[i])
+                               return (i);
+               } else {
+                       if (key == sensitive_data.host_keys[i])
+                               return (i);
+               }
+       }
+       return (-1);
+}
+
+/*
+ * returns 1 if connection should be dropped, 0 otherwise.
+ * dropping starts at connection #max_startups_begin with a probability
+ * of (max_startups_rate/100). the probability increases linearly until
+ * all connections are dropped for startups > max_startups
+ */
+static int
+drop_connection(int startups)
+{
+       int p, r;
+
+       if (startups < options.max_startups_begin)
+               return 0;
+       if (startups >= options.max_startups)
+               return 1;
+       if (options.max_startups_rate == 100)
+               return 1;
+
+       p  = 100 - options.max_startups_rate;
+       p *= startups - options.max_startups_begin;
+       p /= options.max_startups - options.max_startups_begin;
+       p += options.max_startups_rate;
+       r = arc4random_uniform(100);
+
+       debug("drop_connection: p %d, r %d", p, r);
+       return (r < p) ? 1 : 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "%s, %s\n",
+           SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+       fprintf(stderr,
+"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
+"            [-f config_file] [-g login_grace_time] [-h host_key_file]\n"
+"            [-k key_gen_time] [-o option] [-p port] [-u len]\n"
+       );
+       exit(1);
+}
+
+static void
+send_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+
+       debug3("%s: entering fd = %d config len %d", __func__, fd,
+           buffer_len(conf));
+
+       /*
+        * Protocol from reexec master to child:
+        *      string  configuration
+        *      u_int   ephemeral_key_follows
+        *      bignum  e               (only if ephemeral_key_follows == 1)
+        *      bignum  n                       "
+        *      bignum  d                       "
+        *      bignum  iqmp                    "
+        *      bignum  p                       "
+        *      bignum  q                       "
+        *      string rngseed          (only if OpenSSL is not self-seeded)
+        */
+       buffer_init(&m);
+       buffer_put_cstring(&m, buffer_ptr(conf));
+
+       if (sensitive_data.server_key != NULL &&
+           sensitive_data.server_key->type == KEY_RSA1) {
+               buffer_put_int(&m, 1);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
+       } else
+               buffer_put_int(&m, 0);
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_send_rng_seed(&m);
+#endif
+
+       if (ssh_msg_send(fd, 0, &m) == -1)
+               fatal("%s: ssh_msg_send failed", __func__);
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+static void
+recv_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+       char *cp;
+       u_int len;
+
+       debug3("%s: entering fd = %d", __func__, fd);
+
+       buffer_init(&m);
+
+       if (ssh_msg_recv(fd, &m) == -1)
+               fatal("%s: ssh_msg_recv failed", __func__);
+       if (buffer_get_char(&m) != 0)
+               fatal("%s: rexec version mismatch", __func__);
+
+       cp = buffer_get_string(&m, &len);
+       if (conf != NULL)
+               buffer_append(conf, cp, len + 1);
+       xfree(cp);
+
+       if (buffer_get_int(&m)) {
+               if (sensitive_data.server_key != NULL)
+                       key_free(sensitive_data.server_key);
+               sensitive_data.server_key = key_new_private(KEY_RSA1);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
+               rsa_generate_additional_parameters(
+                   sensitive_data.server_key->rsa);
+       }
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_recv_rng_seed(&m);
+#endif
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+/* Accept a connection from inetd */
+static void
+server_accept_inetd(int *sock_in, int *sock_out)
+{
+       int fd;
+
+       startup_pipe = -1;
+       if (rexeced_flag) {
+               close(REEXEC_CONFIG_PASS_FD);
+               *sock_in = *sock_out = dup(STDIN_FILENO);
+               if (!debug_flag) {
+                       startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+                       close(REEXEC_STARTUP_PIPE_FD);
+               }
+       } else {
+               *sock_in = dup(STDIN_FILENO);
+               *sock_out = dup(STDOUT_FILENO);
+       }
+       /*
+        * We intentionally do not close the descriptors 0, 1, and 2
+        * as our code for setting the descriptors won't work if
+        * ttyfd happens to be one of those.
+        */
+       if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+               dup2(fd, STDIN_FILENO);
+               dup2(fd, STDOUT_FILENO);
+               if (fd > STDOUT_FILENO)
+                       close(fd);
+       }
+       debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
+}
+
+/*
+ * Listen for TCP connections
+ */
+static void
+server_listen(void)
+{
+       int ret, listen_sock, on = 1;
+       struct addrinfo *ai;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+
+       for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                       continue;
+               if (num_listen_socks >= MAX_LISTEN_SOCKS)
+                       fatal("Too many listen sockets. "
+                           "Enlarge MAX_LISTEN_SOCKS");
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                   ntop, sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           ssh_gai_strerror(ret));
+                       continue;
+               }
+               /* Create socket for listening. */
+               listen_sock = socket(ai->ai_family, ai->ai_socktype,
+                   ai->ai_protocol);
+               if (listen_sock < 0) {
+                       /* kernel may not support ipv6 */
+                       verbose("socket: %.100s", strerror(errno));
+                       continue;
+               }
+               if (set_nonblock(listen_sock) == -1) {
+                       close(listen_sock);
+                       continue;
+               }
+               /*
+                * Set socket options.
+                * Allow local port reuse in TIME_WAIT.
+                */
+               if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
+                   &on, sizeof(on)) == -1)
+                       error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+
+               /* Only communicate in IPv6 over AF_INET6 sockets. */
+               if (ai->ai_family == AF_INET6)
+                       sock_set_v6only(listen_sock);
+
+               debug("Bind to port %s on %s.", strport, ntop);
+
+               /* Bind the socket to the desired port. */
+               if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       error("Bind to port %s on %s failed: %.200s.",
+                           strport, ntop, strerror(errno));
+                       close(listen_sock);
+                       continue;
+               }
+               listen_socks[num_listen_socks] = listen_sock;
+               num_listen_socks++;
+
+               /* Start listening on the port. */
+               if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
+                       fatal("listen on [%s]:%s: %.100s",
+                           ntop, strport, strerror(errno));
+               logit("Server listening on %s port %s.", ntop, strport);
+       }
+       freeaddrinfo(options.listen_addrs);
+
+       if (!num_listen_socks)
+               fatal("Cannot bind any address.");
+}
+
+/*
+ * The main TCP accept loop. Note that, for the non-debug case, returns
+ * from this function are in a forked subprocess.
+ */
+static void
+server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
+{
+       fd_set *fdset;
+       int i, j, ret, maxfd;
+       int key_used = 0, startups = 0;
+       int startup_p[2] = { -1 , -1 };
+       struct sockaddr_storage from;
+       socklen_t fromlen;
+       pid_t pid;
+
+       /* setup fd set for accept */
+       fdset = NULL;
+       maxfd = 0;
+       for (i = 0; i < num_listen_socks; i++)
+               if (listen_socks[i] > maxfd)
+                       maxfd = listen_socks[i];
+       /* pipes connected to unauthenticated childs */
+       startup_pipes = xcalloc(options.max_startups, sizeof(int));
+       for (i = 0; i < options.max_startups; i++)
+               startup_pipes[i] = -1;
+
+       /*
+        * Stay listening for connections until the system crashes or
+        * the daemon is killed with a signal.
+        */
+       for (;;) {
+               if (received_sighup)
+                       sighup_restart();
+               if (fdset != NULL)
+                       xfree(fdset);
+               fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),
+                   sizeof(fd_mask));
+
+               for (i = 0; i < num_listen_socks; i++)
+                       FD_SET(listen_socks[i], fdset);
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               FD_SET(startup_pipes[i], fdset);
+
+               /* Wait in select until there is a connection. */
+               ret = select(maxfd+1, fdset, NULL, NULL, NULL);
+               if (ret < 0 && errno != EINTR)
+                       error("select: %.100s", strerror(errno));
+               if (received_sigterm) {
+                       logit("Received signal %d; terminating.",
+                           (int) received_sigterm);
+                       close_listen_socks();
+                       unlink(options.pid_file);
+                       exit(received_sigterm == SIGTERM ? 0 : 255);
+               }
+               if (key_used && key_do_regen) {
+                       generate_ephemeral_server_key();
+                       key_used = 0;
+                       key_do_regen = 0;
+               }
+               if (ret < 0)
+                       continue;
+
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1 &&
+                           FD_ISSET(startup_pipes[i], fdset)) {
+                               /*
+                                * the read end of the pipe is ready
+                                * if the child has closed the pipe
+                                * after successful authentication
+                                * or if the child has died
+                                */
+                               close(startup_pipes[i]);
+                               startup_pipes[i] = -1;
+                               startups--;
+                       }
+               for (i = 0; i < num_listen_socks; i++) {
+                       if (!FD_ISSET(listen_socks[i], fdset))
+                               continue;
+                       fromlen = sizeof(from);
+                       *newsock = accept(listen_socks[i],
+                           (struct sockaddr *)&from, &fromlen);
+                       if (*newsock < 0) {
+                               if (errno != EINTR && errno != EAGAIN &&
+                                   errno != EWOULDBLOCK)
+                                       error("accept: %.100s", strerror(errno));
+                               continue;
+                       }
+                       if (unset_nonblock(*newsock) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+                       if (drop_connection(startups) == 1) {
+                               debug("drop connection #%d", startups);
+                               close(*newsock);
+                               continue;
+                       }
+                       if (pipe(startup_p) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+
+                       if (rexec_flag && socketpair(AF_UNIX,
+                           SOCK_STREAM, 0, config_s) == -1) {
+                               error("reexec socketpair: %s",
+                                   strerror(errno));
+                               close(*newsock);
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               continue;
+                       }
+
+                       for (j = 0; j < options.max_startups; j++)
+                               if (startup_pipes[j] == -1) {
+                                       startup_pipes[j] = startup_p[0];
+                                       if (maxfd < startup_p[0])
+                                               maxfd = startup_p[0];
+                                       startups++;
+                                       break;
+                               }
+
+                       /*
+                        * Got connection.  Fork a child to handle it, unless
+                        * we are in debugging mode.
+                        */
+                       if (debug_flag) {
+                               /*
+                                * In debugging mode.  Close the listening
+                                * socket, and start processing the
+                                * connection without forking.
+                                */
+                               debug("Server will not fork when running in debugging mode.");
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               startup_pipe = -1;
+                               pid = getpid();
+                               if (rexec_flag) {
+                                       send_rexec_state(config_s[0],
+                                           &cfg);
+                                       close(config_s[0]);
+                               }
+                               break;
+                       }
+
+                       /*
+                        * Normal production daemon.  Fork, and have
+                        * the child process the connection. The
+                        * parent continues listening.
+                        */
+                       platform_pre_fork();
+                       if ((pid = fork()) == 0) {
+                               /*
+                                * Child.  Close the listening and
+                                * max_startup sockets.  Start using
+                                * the accepted socket. Reinitialize
+                                * logging (since our pid has changed).
+                                * We break out of the loop to handle
+                                * the connection.
+                                */
+                               platform_post_fork_child();
+                               startup_pipe = startup_p[1];
+                               close_startup_pipes();
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               log_init(__progname,
+                                   options.log_level,
+                                   options.log_facility,
+                                   log_stderr);
+                               if (rexec_flag)
+                                       close(config_s[0]);
+                               break;
+                       }
+
+                       /* Parent.  Stay in the loop. */
+                       platform_post_fork_parent(pid);
+                       if (pid < 0)
+                               error("fork: %.100s", strerror(errno));
+                       else
+                               debug("Forked child %ld.", (long)pid);
+
+                       close(startup_p[1]);
+
+                       if (rexec_flag) {
+                               send_rexec_state(config_s[0], &cfg);
+                               close(config_s[0]);
+                               close(config_s[1]);
+                       }
+
+                       /*
+                        * Mark that the key has been used (it
+                        * was "given" to the child).
+                        */
+                       if ((options.protocol & SSH_PROTO_1) &&
+                           key_used == 0) {
+                               /* Schedule server key regeneration alarm. */
+                               signal(SIGALRM, key_regeneration_alarm);
+                               alarm(options.key_regeneration_time);
+                               key_used = 1;
+                       }
+
+                       close(*newsock);
+
+                       /*
+                        * Ensure that our random state differs
+                        * from that of the child
+                        */
+                       arc4random_stir();
+               }
+
+               /* child process check (or debug mode) */
+               if (num_listen_socks < 0)
+                       break;
+       }
+}
+
+
+/*
+ * Main program for the daemon.
+ */
+int
+main(int ac, char **av)
+{
+       extern char *optarg;
+       extern int optind;
+       int opt, i, j, on = 1;
+       int sock_in = -1, sock_out = -1, newsock = -1;
+       const char *remote_ip;
+       char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
+       int remote_port;
+       char *line, *p, *cp;
+       int config_s[2] = { -1 , -1 };
+       u_int64_t ibytes, obytes;
+       mode_t new_umask;
+       Key *key;
+       Authctxt *authctxt;
+
+#ifdef HAVE_SECUREWARE
+       (void)set_auth_parameters(ac, av);
+#endif
+       __progname = ssh_get_progname(av[0]);
+
+       /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
+       saved_argc = ac;
+       rexec_argc = ac;
+       saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
+       for (i = 0; i < ac; i++)
+               saved_argv[i] = xstrdup(av[i]);
+       saved_argv[i] = NULL;
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       compat_init_setproctitle(ac, av);
+       av = saved_argv;
+#endif
+
+       if (geteuid() == 0 && setgroups(0, NULL) == -1)
+               debug("setgroups(): %.200s", strerror(errno));
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       /* Initialize configuration options to their default values. */
+       initialize_server_options(&options);
+
+       /* Parse command-line arguments. */
+       while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) {
+               switch (opt) {
+               case '4':
+                       options.address_family = AF_INET;
+                       break;
+               case '6':
+                       options.address_family = AF_INET6;
+                       break;
+               case 'f':
+                       config_file_name = optarg;
+                       break;
+               case 'c':
+                       if (options.num_host_cert_files >= MAX_HOSTCERTS) {
+                               fprintf(stderr, "too many host certificates.\n");
+                               exit(1);
+                       }
+                       options.host_cert_files[options.num_host_cert_files++] =
+                          derelativise_path(optarg);
+                       break;
+               case 'd':
+                       if (debug_flag == 0) {
+                               debug_flag = 1;
+                               options.log_level = SYSLOG_LEVEL_DEBUG1;
+                       } else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                               options.log_level++;
+                       break;
+               case 'D':
+                       no_daemon_flag = 1;
+                       break;
+               case 'e':
+                       log_stderr = 1;
+                       break;
+               case 'i':
+                       inetd_flag = 1;
+                       break;
+               case 'r':
+                       rexec_flag = 0;
+                       break;
+               case 'R':
+                       rexeced_flag = 1;
+                       inetd_flag = 1;
+                       break;
+               case 'Q':
+                       /* ignored */
+                       break;
+               case 'q':
+                       options.log_level = SYSLOG_LEVEL_QUIET;
+                       break;
+               case 'b':
+                       options.server_key_bits = (int)strtonum(optarg, 256,
+                           32768, NULL);
+                       break;
+               case 'p':
+                       options.ports_from_cmdline = 1;
+                       if (options.num_ports >= MAX_PORTS) {
+                               fprintf(stderr, "too many ports.\n");
+                               exit(1);
+                       }
+                       options.ports[options.num_ports++] = a2port(optarg);
+                       if (options.ports[options.num_ports-1] <= 0) {
+                               fprintf(stderr, "Bad port number.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'g':
+                       if ((options.login_grace_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid login grace time.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'k':
+                       if ((options.key_regeneration_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid key regeneration interval.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'h':
+                       if (options.num_host_key_files >= MAX_HOSTKEYS) {
+                               fprintf(stderr, "too many host keys.\n");
+                               exit(1);
+                       }
+                       options.host_key_files[options.num_host_key_files++] = 
+                          derelativise_path(optarg);
+                       break;
+               case 't':
+                       test_flag = 1;
+                       break;
+               case 'T':
+                       test_flag = 2;
+                       break;
+               case 'C':
+                       cp = optarg;
+                       while ((p = strsep(&cp, ",")) && *p != '\0') {
+                               if (strncmp(p, "addr=", 5) == 0)
+                                       test_addr = xstrdup(p + 5);
+                               else if (strncmp(p, "host=", 5) == 0)
+                                       test_host = xstrdup(p + 5);
+                               else if (strncmp(p, "user=", 5) == 0)
+                                       test_user = xstrdup(p + 5);
+                               else {
+                                       fprintf(stderr, "Invalid test "
+                                           "mode specification %s\n", p);
+                                       exit(1);
+                               }
+                       }
+                       break;
+               case 'u':
+                       utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
+                       if (utmp_len > MAXHOSTNAMELEN) {
+                               fprintf(stderr, "Invalid utmp length.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'o':
+                       line = xstrdup(optarg);
+                       if (process_server_config_line(&options, line,
+                           "command-line", 0, NULL, NULL, NULL, NULL) != 0)
+                               exit(1);
+                       xfree(line);
+                       break;
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+       }
+       if (rexeced_flag || inetd_flag)
+               rexec_flag = 0;
+       if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
+               fatal("sshd re-exec requires execution with an absolute path");
+       if (rexeced_flag)
+               closefrom(REEXEC_MIN_FREE_FD);
+       else
+               closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
+
+       OpenSSL_add_all_algorithms();
+
+       /*
+        * Force logging to stderr until we have loaded the private host
+        * key (unless started from inetd)
+        */
+       log_init(__progname,
+           options.log_level == SYSLOG_LEVEL_NOT_SET ?
+           SYSLOG_LEVEL_INFO : options.log_level,
+           options.log_facility == SYSLOG_FACILITY_NOT_SET ?
+           SYSLOG_FACILITY_AUTH : options.log_facility,
+           log_stderr || !inetd_flag);
+
+       /*
+        * Unset KRB5CCNAME, otherwise the user's session may inherit it from
+        * root's environment
+        */
+       if (getenv("KRB5CCNAME") != NULL)
+               unsetenv("KRB5CCNAME");
+
+#ifdef _UNICOS
+       /* Cray can define user privs drop all privs now!
+        * Not needed on PRIV_SU systems!
+        */
+       drop_cray_privs();
+#endif
+
+       sensitive_data.server_key = NULL;
+       sensitive_data.ssh1_host_key = NULL;
+       sensitive_data.have_ssh1_key = 0;
+       sensitive_data.have_ssh2_key = 0;
+
+       /*
+        * If we're doing an extended config test, make sure we have all of
+        * the parameters we need.  If we're not doing an extended test,
+        * do not silently ignore connection test params.
+        */
+       if (test_flag >= 2 &&
+          (test_user != NULL || test_host != NULL || test_addr != NULL)
+           && (test_user == NULL || test_host == NULL || test_addr == NULL))
+               fatal("user, host and addr are all required when testing "
+                  "Match configs");
+       if (test_flag < 2 && (test_user != NULL || test_host != NULL ||
+           test_addr != NULL))
+               fatal("Config test connection parameter (-C) provided without "
+                  "test mode (-T)");
+
+       /* Fetch our configuration */
+       buffer_init(&cfg);
+       if (rexeced_flag)
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
+       else
+               load_server_config(config_file_name, &cfg);
+
+       parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
+           &cfg, NULL, NULL, NULL);
+
+       seed_rng();
+
+       /* Fill in default values for those options not explicitly set. */
+       fill_default_server_options(&options);
+
+       /* challenge-response is implemented via keyboard interactive */
+       if (options.challenge_response_authentication)
+               options.kbd_interactive_authentication = 1;
+
+       /* set default channel AF */
+       channel_set_af(options.address_family);
+
+       /* Check that there are no remaining arguments. */
+       if (optind < ac) {
+               fprintf(stderr, "Extra argument %s.\n", av[optind]);
+               exit(1);
+       }
+
+       debug("sshd version %.100s", SSH_RELEASE);
+
+       /* Store privilege separation user for later use if required. */
+       if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
+               if (use_privsep || options.kerberos_authentication)
+                       fatal("Privilege separation user %s does not exist",
+                           SSH_PRIVSEP_USER);
+       } else {
+               memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd));
+               privsep_pw = pwcopy(privsep_pw);
+               xfree(privsep_pw->pw_passwd);
+               privsep_pw->pw_passwd = xstrdup("*");
+       }
+       endpwent();
+
+       /* load private host keys */
+       sensitive_data.host_keys = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_keys[i] = NULL;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = key_load_private(options.host_key_files[i], "", NULL);
+               sensitive_data.host_keys[i] = key;
+               if (key == NULL) {
+                       error("Could not load host key: %s",
+                           options.host_key_files[i]);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
+               switch (key->type) {
+               case KEY_RSA1:
+                       sensitive_data.ssh1_host_key = key;
+                       sensitive_data.have_ssh1_key = 1;
+                       break;
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       sensitive_data.have_ssh2_key = 1;
+                       break;
+               }
+               debug("private host key: #%d type %d %s", i, key->type,
+                   key_type(key));
+       }
+       if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
+               logit("Disabling protocol version 1. Could not load host key");
+               options.protocol &= ~SSH_PROTO_1;
+       }
+       if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
+               logit("Disabling protocol version 2. Could not load host key");
+               options.protocol &= ~SSH_PROTO_2;
+       }
+       if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+               logit("sshd: no hostkeys available -- exiting.");
+               exit(1);
+       }
+
+       /*
+        * Load certificates. They are stored in an array at identical
+        * indices to the public keys that they relate to.
+        */
+       sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_certificates[i] = NULL;
+
+       for (i = 0; i < options.num_host_cert_files; i++) {
+               key = key_load_public(options.host_cert_files[i], NULL);
+               if (key == NULL) {
+                       error("Could not load host certificate: %s",
+                           options.host_cert_files[i]);
+                       continue;
+               }
+               if (!key_is_cert(key)) {
+                       error("Certificate file is not a certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               /* Find matching private key */
+               for (j = 0; j < options.num_host_key_files; j++) {
+                       if (key_equal_public(key,
+                           sensitive_data.host_keys[j])) {
+                               sensitive_data.host_certificates[j] = key;
+                               break;
+                       }
+               }
+               if (j >= options.num_host_key_files) {
+                       error("No matching private key for certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               sensitive_data.host_certificates[j] = key;
+               debug("host certificate: #%d type %d %s", j, key->type,
+                   key_type(key));
+       }
+       /* Check certain values for sanity. */
+       if (options.protocol & SSH_PROTO_1) {
+               if (options.server_key_bits < 512 ||
+                   options.server_key_bits > 32768) {
+                       fprintf(stderr, "Bad server key size.\n");
+                       exit(1);
+               }
+               /*
+                * Check that server and host key lengths differ sufficiently. This
+                * is necessary to make double encryption work with rsaref. Oh, I
+                * hate software patents. I dont know if this can go? Niels
+                */
+               if (options.server_key_bits >
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -
+                   SSH_KEY_BITS_RESERVED && options.server_key_bits <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       options.server_key_bits =
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                           SSH_KEY_BITS_RESERVED;
+                       debug("Forcing server key to %d bits to make it differ from host key.",
+                           options.server_key_bits);
+               }
+       }
+
+       if (use_privsep) {
+               struct stat st;
+
+               if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
+                   (S_ISDIR(st.st_mode) == 0))
+                       fatal("Missing privilege separation directory: %s",
+                           _PATH_PRIVSEP_CHROOT_DIR);
+
+#ifdef HAVE_CYGWIN
+               if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) &&
+                   (st.st_uid != getuid () ||
+                   (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
+#else
+               if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
+#endif
+                       fatal("%s must be owned by root and not group or "
+                           "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
+       }
+
+       if (test_flag > 1) {
+               if (test_user != NULL && test_addr != NULL && test_host != NULL)
+                       parse_server_match_config(&options, test_user,
+                           test_host, test_addr);
+               dump_config(&options);
+       }
+
+       /* Configuration looks good, so exit if in test mode. */
+       if (test_flag)
+               exit(0);
+
+       /*
+        * Clear out any supplemental groups we may have inherited.  This
+        * prevents inadvertent creation of files with bad modes (in the
+        * portable version at least, it's certainly possible for PAM
+        * to create a file, and we can't control the code in every
+        * module which might be used).
+        */
+       if (setgroups(0, NULL) < 0)
+               debug("setgroups() failed: %.200s", strerror(errno));
+
+       if (rexec_flag) {
+               rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *));
+               for (i = 0; i < rexec_argc; i++) {
+                       debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
+                       rexec_argv[i] = saved_argv[i];
+               }
+               rexec_argv[rexec_argc] = "-R";
+               rexec_argv[rexec_argc + 1] = NULL;
+       }
+
+       /* Ensure that umask disallows at least group and world write */
+       new_umask = umask(0077) | 0022;
+       (void) umask(new_umask);
+
+       /* Initialize the log (it is reinitialized below in case we forked). */
+       if (debug_flag && (!inetd_flag || rexeced_flag))
+               log_stderr = 1;
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /*
+        * If not in debugging mode, and not started from inetd, disconnect
+        * from the controlling terminal, and fork.  The original process
+        * exits.
+        */
+       if (!(debug_flag || inetd_flag || no_daemon_flag)) {
+#ifdef TIOCNOTTY
+               int fd;
+#endif /* TIOCNOTTY */
+               if (daemon(0, 0) < 0)
+                       fatal("daemon() failed: %.200s", strerror(errno));
+
+               /* Disconnect from the controlling tty. */
+#ifdef TIOCNOTTY
+               fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
+               if (fd >= 0) {
+                       (void) ioctl(fd, TIOCNOTTY, NULL);
+                       close(fd);
+               }
+#endif /* TIOCNOTTY */
+       }
+       /* Reinitialize the log (because of the fork above). */
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /* Initialize the random number generator. */
+       arc4random_stir();
+
+       /* Chdir to the root directory so that the current disk can be
+          unmounted if desired. */
+       chdir("/");
+
+       /* ignore SIGPIPE */
+       signal(SIGPIPE, SIG_IGN);
+
+       /* Get a connection, either from inetd or a listening TCP socket */
+       if (inetd_flag) {
+               server_accept_inetd(&sock_in, &sock_out);
+       } else {
+               platform_pre_listen();
+               server_listen();
+
+               if (options.protocol & SSH_PROTO_1)
+                       generate_ephemeral_server_key();
+
+               signal(SIGHUP, sighup_handler);
+               signal(SIGCHLD, main_sigchld_handler);
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+
+               /*
+                * Write out the pid file after the sigterm handler
+                * is setup and the listen sockets are bound
+                */
+               if (!debug_flag) {
+                       FILE *f = fopen(options.pid_file, "w");
+
+                       if (f == NULL) {
+                               error("Couldn't create pid file \"%s\": %s",
+                                   options.pid_file, strerror(errno));
+                       } else {
+                               fprintf(f, "%ld\n", (long) getpid());
+                               fclose(f);
+                       }
+               }
+
+               /* Accept a connection and return in a forked child */
+               server_accept_loop(&sock_in, &sock_out,
+                   &newsock, config_s);
+       }
+
+       /* This is the child processing a new connection. */
+       setproctitle("%s", "[accepted]");
+
+       /*
+        * Create a new session and process group since the 4.4BSD
+        * setlogin() affects the entire process group.  We don't
+        * want the child to be able to affect the parent.
+        */
+#if !defined(SSHD_ACQUIRES_CTTY)
+       /*
+        * If setsid is called, on some platforms sshd will later acquire a
+        * controlling terminal which will result in "could not set
+        * controlling tty" errors.
+        */
+       if (!debug_flag && !inetd_flag && setsid() < 0)
+               error("setsid: %.100s", strerror(errno));
+#endif
+
+       if (rexec_flag) {
+               int fd;
+
+               debug("rexec start in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+               dup2(newsock, STDIN_FILENO);
+               dup2(STDIN_FILENO, STDOUT_FILENO);
+               if (startup_pipe == -1)
+                       close(REEXEC_STARTUP_PIPE_FD);
+               else
+                       dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
+
+               dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
+               close(config_s[1]);
+               if (startup_pipe != -1)
+                       close(startup_pipe);
+
+               execv(rexec_argv[0], rexec_argv);
+
+               /* Reexec has failed, fall back and continue */
+               error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
+
+               /* Clean up fds */
+               startup_pipe = REEXEC_STARTUP_PIPE_FD;
+               close(config_s[1]);
+               close(REEXEC_CONFIG_PASS_FD);
+               newsock = sock_out = sock_in = dup(STDIN_FILENO);
+               if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       if (fd > STDERR_FILENO)
+                               close(fd);
+               }
+               debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+       }
+
+       /* Executed child processes don't need these. */
+       fcntl(sock_out, F_SETFD, FD_CLOEXEC);
+       fcntl(sock_in, F_SETFD, FD_CLOEXEC);
+
+       /*
+        * Disable the key regeneration alarm.  We will not regenerate the
+        * key since we are no longer in a position to give it to anyone. We
+        * will not restart on SIGHUP since it no longer makes sense.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGQUIT, SIG_DFL);
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGINT, SIG_DFL);
+
+       /*
+        * Register our connection.  This turns encryption off because we do
+        * not have a key.
+        */
+       packet_set_connection(sock_in, sock_out);
+       packet_set_server();
+
+       /* Set SO_KEEPALIVE if requested. */
+       if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
+           setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
+       if ((remote_port = get_remote_port()) < 0) {
+               debug("get_remote_port failed");
+               cleanup_exit(255);
+       }
+
+       /*
+        * We use get_canonical_hostname with usedns = 0 instead of
+        * get_remote_ipaddr here so IP options will be checked.
+        */
+       (void) get_canonical_hostname(0);
+       /*
+        * The rest of the code depends on the fact that
+        * get_remote_ipaddr() caches the remote ip, even if
+        * the socket goes away.
+        */
+       remote_ip = get_remote_ipaddr();
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_connection_from(remote_ip, remote_port);
+#endif
+#ifdef LIBWRAP
+       allow_severity = options.log_facility|LOG_INFO;
+       deny_severity = options.log_facility|LOG_WARNING;
+       /* Check whether logins are denied from this host. */
+       if (packet_connection_is_on_socket()) {
+               struct request_info req;
+
+               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
+               fromhost(&req);
+
+               if (!hosts_access(&req)) {
+                       debug("Connection refused by tcp wrapper");
+                       refuse(&req);
+                       /* NOTREACHED */
+                       fatal("libwrap refuse returns");
+               }
+       }
+#endif /* LIBWRAP */
+
+       /* Log the connection. */
+       verbose("Connection from %.500s port %d", remote_ip, remote_port);
+
+       /*
+        * We don't want to listen forever unless the other side
+        * successfully authenticates itself.  So we set up an alarm which is
+        * cleared after successful authentication.  A limit of zero
+        * indicates no limit. Note that we don't set the alarm in debugging
+        * mode; it is just annoying to have the server exit just when you
+        * are about to discover the bug.
+        */
+       signal(SIGALRM, grace_alarm_handler);
+       if (!debug_flag)
+               alarm(options.login_grace_time);
+
+       sshd_exchange_identification(sock_in, sock_out);
+
+       /* In inetd mode, generate ephemeral key only for proto 1 connections */
+       if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
+               generate_ephemeral_server_key();
+
+       packet_set_nonblocking();
+
+       /* allocate authentication context */
+       authctxt = xcalloc(1, sizeof(*authctxt));
+
+       authctxt->loginmsg = &loginmsg;
+
+       /* XXX global for cleanup, access from other modules */
+       the_authctxt = authctxt;
+
+       /* prepare buffer to collect messages to display to user after login */
+       buffer_init(&loginmsg);
+       auth_debug_reset();
+
+       if (use_privsep)
+               if (privsep_preauth(authctxt) == 1)
+                       goto authenticated;
+
+       /* perform the key exchange */
+       /* authenticate user and start session */
+       if (compat20) {
+               do_ssh2_kex();
+               do_authentication2(authctxt);
+       } else {
+               do_ssh1_kex();
+               do_authentication(authctxt);
+       }
+       /*
+        * If we use privilege separation, the unprivileged child transfers
+        * the current keystate and exits
+        */
+       if (use_privsep) {
+               mm_send_keystate(pmonitor);
+               exit(0);
+       }
+
+ authenticated:
+       /*
+        * Cancel the alarm we set to limit the time taken for
+        * authentication.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       authctxt->authenticated = 1;
+       if (startup_pipe != -1) {
+               close(startup_pipe);
+               startup_pipe = -1;
+       }
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_event(SSH_AUTH_SUCCESS);
+#endif
+
+#ifdef GSSAPI
+       if (options.gss_authentication) {
+               temporarily_use_uid(authctxt->pw);
+               ssh_gssapi_storecreds();
+               restore_uid();
+       }
+#endif
+#ifdef USE_PAM
+       if (options.use_pam) {
+               do_pam_setcred(1);
+               do_pam_session();
+       }
+#endif
+
+       /*
+        * In privilege separation, we fork another child and prepare
+        * file descriptor passing.
+        */
+       if (use_privsep) {
+               privsep_postauth(authctxt);
+               /* the monitor process [priv] will not return */
+               if (!compat20)
+                       destroy_sensitive_data();
+       }
+
+       packet_set_timeout(options.client_alive_interval,
+           options.client_alive_count_max);
+
+       /* Start session. */
+       do_authenticated(authctxt);
+
+       /* The connection has been terminated. */
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes",
+           (unsigned long long)obytes, (unsigned long long)ibytes);
+
+       verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               finish_pam();
+#endif /* USE_PAM */
+
+#ifdef SSH_AUDIT_EVENTS
+       PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));
+#endif
+
+       packet_close();
+
+       if (use_privsep)
+               mm_terminate();
+
+       exit(0);
+}
+
+/*
+ * Decrypt session_key_int using our private server key and private host key
+ * (key with larger modulus first).
+ */
+int
+ssh1_session_key(BIGNUM *session_key_int)
+{
+       int rsafail = 0;
+
+       if (BN_cmp(sensitive_data.server_key->rsa->n,
+           sensitive_data.ssh1_host_key->rsa->n) > 0) {
+               /* Server key has bigger modulus. */
+               if (BN_num_bits(sensitive_data.server_key->rsa->n) <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) <= 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) <= 0)
+                       rsafail++;
+       } else {
+               /* Host key has bigger modulus (or they are equal). */
+               if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
+                   BN_num_bits(sensitive_data.server_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) < 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) < 0)
+                       rsafail++;
+       }
+       return (rsafail);
+}
+/*
+ * SSH1 key exchange
+ */
+static void
+do_ssh1_kex(void)
+{
+       int i, len;
+       int rsafail = 0;
+       BIGNUM *session_key_int;
+       u_char session_key[SSH_SESSION_KEY_LENGTH];
+       u_char cookie[8];
+       u_int cipher_type, auth_mask, protocol_flags;
+
+       /*
+        * Generate check bytes that the client must send back in the user
+        * packet in order for it to be accepted; this is used to defy ip
+        * spoofing attacks.  Note that this only works against somebody
+        * doing IP spoofing from a remote machine; any machine on the local
+        * network can still see outgoing packets and catch the random
+        * cookie.  This only affects rhosts authentication, and this is one
+        * of the reasons why it is inherently insecure.
+        */
+       arc4random_buf(cookie, sizeof(cookie));
+
+       /*
+        * Send our public key.  We include in the packet 64 bits of random
+        * data that must be matched in the reply in order to prevent IP
+        * spoofing.
+        */
+       packet_start(SSH_SMSG_PUBLIC_KEY);
+       for (i = 0; i < 8; i++)
+               packet_put_char(cookie[i]);
+
+       /* Store our public server RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
+       packet_put_bignum(sensitive_data.server_key->rsa->e);
+       packet_put_bignum(sensitive_data.server_key->rsa->n);
+
+       /* Store our public host RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
+
+       /* Put protocol flags. */
+       packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
+
+       /* Declare which ciphers we support. */
+       packet_put_int(cipher_mask_ssh1(0));
+
+       /* Declare supported authentication types. */
+       auth_mask = 0;
+       if (options.rhosts_rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
+       if (options.rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RSA;
+       if (options.challenge_response_authentication == 1)
+               auth_mask |= 1 << SSH_AUTH_TIS;
+       if (options.password_authentication)
+               auth_mask |= 1 << SSH_AUTH_PASSWORD;
+       packet_put_int(auth_mask);
+
+       /* Send the packet and wait for it to be sent. */
+       packet_send();
+       packet_write_wait();
+
+       debug("Sent %d bit server key and %d bit host key.",
+           BN_num_bits(sensitive_data.server_key->rsa->n),
+           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+
+       /* Read clients reply (cipher type and session key). */
+       packet_read_expect(SSH_CMSG_SESSION_KEY);
+
+       /* Get cipher type and check whether we accept this. */
+       cipher_type = packet_get_char();
+
+       if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
+               packet_disconnect("Warning: client selects unsupported cipher.");
+
+       /* Get check bytes from the packet.  These must match those we
+          sent earlier with the public key packet. */
+       for (i = 0; i < 8; i++)
+               if (cookie[i] != packet_get_char())
+                       packet_disconnect("IP Spoofing check bytes do not match.");
+
+       debug("Encryption type: %.200s", cipher_name(cipher_type));
+
+       /* Get the encrypted integer. */
+       if ((session_key_int = BN_new()) == NULL)
+               fatal("do_ssh1_kex: BN_new failed");
+       packet_get_bignum(session_key_int);
+
+       protocol_flags = packet_get_int();
+       packet_set_protocol_flags(protocol_flags);
+       packet_check_eom();
+
+       /* Decrypt session_key_int using host/server keys */
+       rsafail = PRIVSEP(ssh1_session_key(session_key_int));
+
+       /*
+        * Extract session key from the decrypted integer.  The key is in the
+        * least significant 256 bits of the integer; the first byte of the
+        * key is in the highest bits.
+        */
+       if (!rsafail) {
+               (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
+               len = BN_num_bytes(session_key_int);
+               if (len < 0 || (u_int)len > sizeof(session_key)) {
+                       error("do_ssh1_kex: bad session key len from %s: "
+                           "session_key_int %d > sizeof(session_key) %lu",
+                           get_remote_ipaddr(), len, (u_long)sizeof(session_key));
+                       rsafail++;
+               } else {
+                       memset(session_key, 0, sizeof(session_key));
+                       BN_bn2bin(session_key_int,
+                           session_key + sizeof(session_key) - len);
+
+                       derive_ssh1_session_id(
+                           sensitive_data.ssh1_host_key->rsa->n,
+                           sensitive_data.server_key->rsa->n,
+                           cookie, session_id);
+                       /*
+                        * Xor the first 16 bytes of the session key with the
+                        * session id.
+                        */
+                       for (i = 0; i < 16; i++)
+                               session_key[i] ^= session_id[i];
+               }
+       }
+       if (rsafail) {
+               int bytes = BN_num_bytes(session_key_int);
+               u_char *buf = xmalloc(bytes);
+               MD5_CTX md;
+
+               logit("do_connection: generating a fake encryption key");
+               BN_bn2bin(session_key_int, buf);
+               MD5_Init(&md);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key, &md);
+               MD5_Init(&md);
+               MD5_Update(&md, session_key, 16);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key + 16, &md);
+               memset(buf, 0, bytes);
+               xfree(buf);
+               for (i = 0; i < 16; i++)
+                       session_id[i] = session_key[i] ^ session_key[i + 16];
+       }
+       /* Destroy the private and public keys. No longer. */
+       destroy_sensitive_data();
+
+       if (use_privsep)
+               mm_ssh1_session_id(session_id);
+
+       /* Destroy the decrypted integer.  It is no longer needed. */
+       BN_clear_free(session_key_int);
+
+       /* Set the session key.  From this on all communications will be encrypted. */
+       packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);
+
+       /* Destroy our copy of the session key.  It is no longer needed. */
+       memset(session_key, 0, sizeof(session_key));
+
+       debug("Received session key; encryption turned on.");
+
+       /* Send an acknowledgment packet.  Note that this packet is sent encrypted. */
+       packet_start(SSH_SMSG_SUCCESS);
+       packet_send();
+       packet_write_wait();
+}
+
+/*
+ * SSH2 key exchange: diffie-hellman-group1-sha1
+ */
+static void
+do_ssh2_kex(void)
+{
+       Kex *kex;
+
+       if (options.ciphers != NULL) {
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       myproposal[PROPOSAL_ENC_ALGS_STOC] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
+
+       if (options.macs != NULL) {
+               myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+               myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+       }
+       if (options.compression == COMP_NONE) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
+       } else if (options.compression == COMP_DELAYED) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";
+       }
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+
+       myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->load_host_public_key=&get_hostkey_public_by_type;
+       kex->load_host_private_key=&get_hostkey_private_by_type;
+       kex->host_key_index=&get_hostkey_index;
+
+       xxx_kex = kex;
+
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
+
+#ifdef DEBUG_KEXDH
+       /* send 1st encrypted/maced/compressed message */
+       packet_start(SSH2_MSG_IGNORE);
+       packet_put_cstring("markus");
+       packet_send();
+       packet_write_wait();
+#endif
+       debug("KEX done");
+}
+
+/* server specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       if (the_authctxt)
+               do_cleanup(the_authctxt);
+#ifdef SSH_AUDIT_EVENTS
+       /* done after do_cleanup so it can cancel the PAM auth 'thread' */
+       if (!use_privsep || mm_is_monitor())
+               audit_event(SSH_CONNECTION_ABANDON);
+#endif
+       _exit(i);
+}
diff --git a/.pc/gssapi.patch/sshd_config b/.pc/gssapi.patch/sshd_config
new file mode 100644 (file)
index 0000000..473e866
--- /dev/null
@@ -0,0 +1,121 @@
+#      $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
+
+# This is the sshd server system-wide configuration file.  See
+# sshd_config(5) for more information.
+
+# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+
+# The strategy used for options in the default sshd_config shipped with
+# OpenSSH is to specify options with their default value where
+# possible, but leave them commented.  Uncommented options override the
+# default value.
+
+#Port 22
+#AddressFamily any
+#ListenAddress 0.0.0.0
+#ListenAddress ::
+
+# The default requires explicit activation of protocol 1
+#Protocol 2
+
+# HostKey for protocol version 1
+#HostKey /etc/ssh/ssh_host_key
+# HostKeys for protocol version 2
+#HostKey /etc/ssh/ssh_host_rsa_key
+#HostKey /etc/ssh/ssh_host_dsa_key
+#HostKey /etc/ssh/ssh_host_ecdsa_key
+
+# Lifetime and size of ephemeral version 1 server key
+#KeyRegenerationInterval 1h
+#ServerKeyBits 1024
+
+# Logging
+# obsoletes QuietMode and FascistLogging
+#SyslogFacility AUTH
+#LogLevel INFO
+
+# Authentication:
+
+#LoginGraceTime 2m
+#PermitRootLogin yes
+#StrictModes yes
+#MaxAuthTries 6
+#MaxSessions 10
+
+#RSAAuthentication yes
+#PubkeyAuthentication yes
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile     .ssh/authorized_keys
+
+# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+#RhostsRSAAuthentication no
+# similar for protocol version 2
+#HostbasedAuthentication no
+# Change to yes if you don't trust ~/.ssh/known_hosts for
+# RhostsRSAAuthentication and HostbasedAuthentication
+#IgnoreUserKnownHosts no
+# Don't read the user's ~/.rhosts and ~/.shosts files
+#IgnoreRhosts yes
+
+# To disable tunneled clear text passwords, change to no here!
+#PasswordAuthentication yes
+#PermitEmptyPasswords no
+
+# Change to no to disable s/key passwords
+#ChallengeResponseAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+#KerberosGetAFSToken no
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+# Set this to 'yes' to enable PAM authentication, account processing, 
+# and session processing. If this is enabled, PAM authentication will 
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication.  Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+#UsePAM no
+
+#AllowAgentForwarding yes
+#AllowTcpForwarding yes
+#GatewayPorts no
+#X11Forwarding no
+#X11DisplayOffset 10
+#X11UseLocalhost yes
+#PrintMotd yes
+#PrintLastLog yes
+#TCPKeepAlive yes
+#UseLogin no
+#UsePrivilegeSeparation yes
+#PermitUserEnvironment no
+#Compression delayed
+#ClientAliveInterval 0
+#ClientAliveCountMax 3
+#UseDNS yes
+#PidFile /var/run/sshd.pid
+#MaxStartups 10
+#PermitTunnel no
+#ChrootDirectory none
+
+# no default banner path
+#Banner none
+
+# override default of no subsystems
+Subsystem      sftp    /usr/libexec/sftp-server
+
+# Example of overriding settings on a per-user basis
+#Match User anoncvs
+#      X11Forwarding no
+#      AllowTcpForwarding no
+#      ForceCommand cvs server
diff --git a/.pc/gssapi.patch/sshd_config.5 b/.pc/gssapi.patch/sshd_config.5
new file mode 100644 (file)
index 0000000..a6c3787
--- /dev/null
@@ -0,0 +1,1215 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd_config.5,v 1.135 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD_CONFIG 5
+.Os
+.Sh NAME
+.Nm sshd_config
+.Nd OpenSSH SSH daemon configuration file
+.Sh SYNOPSIS
+.Nm /etc/ssh/sshd_config
+.Sh DESCRIPTION
+.Xr sshd 8
+reads configuration data from
+.Pa /etc/ssh/sshd_config
+(or the file specified with
+.Fl f
+on the command line).
+The file contains keyword-argument pairs, one per line.
+Lines starting with
+.Ql #
+and empty lines are interpreted as comments.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm AcceptEnv
+Specifies what environment variables sent by the client will be copied into
+the session's
+.Xr environ 7 .
+See
+.Cm SendEnv
+in
+.Xr ssh_config 5
+for how to configure the client.
+Note that environment passing is only supported for protocol 2.
+Variables are specified by name, which may contain the wildcard characters
+.Ql *
+and
+.Ql \&? .
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm AcceptEnv
+directives.
+Be warned that some environment variables could be used to bypass restricted
+user environments.
+For this reason, care should be taken in the use of this directive.
+The default is not to accept any environment variables.
+.It Cm AddressFamily
+Specifies which address family should be used by
+.Xr sshd 8 .
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+The default is
+.Dq any .
+.It Cm AllowAgentForwarding
+Specifies whether
+.Xr ssh-agent 1
+forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling agent forwarding does not improve security
+unless users are also denied shell access, as they can always install
+their own forwarders.
+.It Cm AllowGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+If specified, login is allowed only for users whose primary
+group or supplementary group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling TCP forwarding does not improve security unless
+users are also denied shell access, as they can always install their
+own forwarders.
+.It Cm AllowUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+If specified, login is allowed only for user names that
+match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AuthorizedKeysFile
+Specifies the file that contains the public keys that can be used
+for user authentication.
+The format is described in the
+.Sx AUTHORIZED_KEYS FILE FORMAT
+section of
+.Xr sshd 8 .
+.Cm AuthorizedKeysFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedKeysFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+Multiple files may be listed, separated by whitespace.
+The default is
+.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
+.It Cm AuthorizedPrincipalsFile
+Specifies a file that lists principal names that are accepted for
+certificate authentication.
+When using certificates signed by a key listed in
+.Cm TrustedUserCAKeys ,
+this file lists names, one of which must appear in the certificate for it
+to be accepted for authentication.
+Names are listed one per line preceded by key options (as described
+in
+.Sx AUTHORIZED_KEYS FILE FORMAT
+in
+.Xr sshd 8 ) .
+Empty lines and comments starting with
+.Ql #
+are ignored.
+.Pp
+.Cm AuthorizedPrincipalsFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedPrincipalsFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+.Pp
+The default is not to use a principals file \(en in this case, the username
+of the user must appear in a certificate's principals list for it to be
+accepted.
+Note that
+.Cm AuthorizedPrincipalsFile
+is only used when authentication proceeds using a CA listed in
+.Cm TrustedUserCAKeys
+and is not consulted for certification authorities trusted via
+.Pa ~/.ssh/authorized_keys ,
+though the
+.Cm principals=
+key option offers a similar facility (see
+.Xr sshd 8
+for details).
+.It Cm Banner
+The contents of the specified file are sent to the remote user before
+authentication is allowed.
+If the argument is
+.Dq none
+then no banner is displayed.
+This option is only available for protocol version 2.
+By default, no banner is displayed.
+.It Cm ChallengeResponseAuthentication
+Specifies whether challenge-response authentication is allowed (e.g. via
+PAM or though authentication styles supported in
+.Xr login.conf 5 )
+The default is
+.Dq yes .
+.It Cm ChrootDirectory
+Specifies the pathname of a directory to
+.Xr chroot 2
+to after authentication.
+All components of the pathname must be root-owned directories that are
+not writable by any other user or group.
+After the chroot,
+.Xr sshd 8
+changes the working directory to the user's home directory.
+.Pp
+The pathname may contain the following tokens that are expanded at runtime once
+the connecting user has been authenticated: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+.Pp
+The
+.Cm ChrootDirectory
+must contain the necessary files and directories to support the
+user's session.
+For an interactive session this requires at least a shell, typically
+.Xr sh 1 ,
+and basic
+.Pa /dev
+nodes such as
+.Xr null 4 ,
+.Xr zero 4 ,
+.Xr stdin 4 ,
+.Xr stdout 4 ,
+.Xr stderr 4 ,
+.Xr arandom 4
+and
+.Xr tty 4
+devices.
+For file transfer sessions using
+.Dq sftp ,
+no additional configuration of the environment is necessary if the
+in-process sftp server is used,
+though sessions which use logging do require
+.Pa /dev/log
+inside the chroot directory (see
+.Xr sftp-server 8
+for details).
+.Pp
+The default is not to
+.Xr chroot 2 .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClientAliveCountMax
+Sets the number of client alive messages (see below) which may be
+sent without
+.Xr sshd 8
+receiving any messages back from the client.
+If this threshold is reached while client alive messages are being sent,
+sshd will disconnect the client, terminating the session.
+It is important to note that the use of client alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The client alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The client alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If
+.Cm ClientAliveInterval
+(see below) is set to 15, and
+.Cm ClientAliveCountMax
+is left at the default, unresponsive SSH clients
+will be disconnected after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ClientAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the client,
+.Xr sshd 8
+will send a message through the encrypted
+channel to request a response from the client.
+The default
+is 0, indicating that these messages will not be sent to the client.
+This option applies to protocol version 2 only.
+.It Cm Compression
+Specifies whether compression is allowed, or delayed until
+the user has authenticated successfully.
+The argument must be
+.Dq yes ,
+.Dq delayed ,
+or
+.Dq no .
+The default is
+.Dq delayed .
+.It Cm DenyGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+Login is disallowed for users whose primary group or supplementary
+group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm DenyUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+Login is disallowed for user names that match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm ForceCommand
+Forces the execution of the command specified by
+.Cm ForceCommand ,
+ignoring any command supplied by the client and
+.Pa ~/.ssh/rc
+if present.
+The command is invoked by using the user's login shell with the -c option.
+This applies to shell, command, or subsystem execution.
+It is most useful inside a
+.Cm Match
+block.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Specifying a command of
+.Dq internal-sftp
+will force the use of an in-process sftp server that requires no support
+files when used with
+.Cm ChrootDirectory .
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to ports
+forwarded for the client.
+By default,
+.Xr sshd 8
+binds remote port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that sshd
+should allow remote port forwardings to bind to non-loopback addresses, thus
+allowing other hosts to connect.
+The argument may be
+.Dq no
+to force remote port forwardings to be available to the local host only,
+.Dq yes
+to force remote port forwardings to bind to the wildcard address, or
+.Dq clientspecified
+to allow the client to select the address to which the forwarding is bound.
+The default is
+.Dq no .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICleanupCredentials
+Specifies whether to automatically destroy the user's credentials cache
+on logout.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm HostbasedAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful public key client host authentication is allowed
+(host-based authentication).
+This option is similar to
+.Cm RhostsRSAAuthentication
+and applies to protocol version 2 only.
+The default is
+.Dq no .
+.It Cm HostbasedUsesNameFromPacketOnly
+Specifies whether or not the server will attempt to perform a reverse
+name lookup when matching the name in the
+.Pa ~/.shosts ,
+.Pa ~/.rhosts ,
+and
+.Pa /etc/hosts.equiv
+files during
+.Cm HostbasedAuthentication .
+A setting of
+.Dq yes
+means that
+.Xr sshd 8
+uses the name supplied by the client rather than
+attempting to resolve the name from the TCP connection itself.
+The default is
+.Dq no .
+.It Cm HostCertificate
+Specifies a file containing a public host certificate.
+The certificate's public key must match a private host key already specified
+by
+.Cm HostKey .
+The default behaviour of
+.Xr sshd 8
+is not to load any certificates.
+.It Cm HostKey
+Specifies a file containing a private host key
+used by SSH.
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+Note that
+.Xr sshd 8
+will refuse to use a file if it is group/world-accessible.
+It is possible to have multiple host key files.
+.Dq rsa1
+keys are used for version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+are used for version 2 of the SSH protocol.
+.It Cm IgnoreRhosts
+Specifies that
+.Pa .rhosts
+and
+.Pa .shosts
+files will not be used in
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+.Pp
+.Pa /etc/hosts.equiv
+and
+.Pa /etc/shosts.equiv
+are still used.
+The default is
+.Dq yes .
+.It Cm IgnoreUserKnownHosts
+Specifies whether
+.Xr sshd 8
+should ignore the user's
+.Pa ~/.ssh/known_hosts
+during
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+The default is
+.Dq no .
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for the connection.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KerberosAuthentication
+Specifies whether the password provided by the user for
+.Cm PasswordAuthentication
+will be validated through the Kerberos KDC.
+To use this option, the server needs a
+Kerberos servtab which allows the verification of the KDC's identity.
+The default is
+.Dq no .
+.It Cm KerberosGetAFSToken
+If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
+an AFS token before accessing the user's home directory.
+The default is
+.Dq no .
+.It Cm KerberosOrLocalPasswd
+If password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as
+.Pa /etc/passwd .
+The default is
+.Dq yes .
+.It Cm KerberosTicketCleanup
+Specifies whether to automatically destroy the user's ticket cache
+file on logout.
+The default is
+.Dq yes .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq ecdh-sha2-nistp256 ,
+.Dq ecdh-sha2-nistp384 ,
+.Dq ecdh-sha2-nistp521 ,
+.Dq diffie-hellman-group-exchange-sha256 ,
+.Dq diffie-hellman-group-exchange-sha1 ,
+.Dq diffie-hellman-group14-sha1 ,
+.Dq diffie-hellman-group1-sha1 .
+.It Cm KeyRegenerationInterval
+In protocol version 1, the ephemeral server key is automatically regenerated
+after this many seconds (if it has been used).
+The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys.
+The key is never stored anywhere.
+If the value is 0, the key is never regenerated.
+The default is 3600 (seconds).
+.It Cm ListenAddress
+Specifies the local addresses
+.Xr sshd 8
+should listen on.
+The following forms may be used:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No : Ar port
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Oo
+.Ar host No | Ar IPv6_addr Oc : Ar port
+.Sm on
+.El
+.Pp
+If
+.Ar port
+is not specified,
+sshd will listen on the address and all prior
+.Cm Port
+options specified.
+The default is to listen on all local addresses.
+Multiple
+.Cm ListenAddress
+options are permitted.
+Additionally, any
+.Cm Port
+options must precede this option for non-port qualified addresses.
+.It Cm LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in.
+If the value is 0, there is no time limit.
+The default is 120 seconds.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr sshd 8 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of debugging output.
+Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm MACs
+Specifies the available MAC (message authentication code) algorithms.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm Match
+Introduces a conditional block.
+If all of the criteria on the
+.Cm Match
+line are satisfied, the keywords on the following lines override those
+set in the global section of the config file, until either another
+.Cm Match
+line or the end of the file.
+.Pp
+The arguments to
+.Cm Match
+are one or more criteria-pattern pairs.
+The available criteria are
+.Cm User ,
+.Cm Group ,
+.Cm Host ,
+and
+.Cm Address .
+The match patterns may consist of single entries or comma-separated
+lists and may use the wildcard and negation operators described in the
+.Sx PATTERNS
+section of
+.Xr ssh_config 5 .
+.Pp
+The patterns in an
+.Cm Address
+criteria may additionally contain addresses to match in CIDR
+address/masklen format, e.g.\&
+.Dq 192.0.2.0/24
+or
+.Dq 3ffe:ffff::/32 .
+Note that the mask length provided must be consistent with the address -
+it is an error to specify a mask length that is too long for the address
+or one with bits set in this host portion of the address.
+For example,
+.Dq 192.0.2.0/33
+and
+.Dq 192.0.2.0/8
+respectively.
+.Pp
+Only a subset of keywords may be used on the lines following a
+.Cm Match
+keyword.
+Available keywords are
+.Cm AllowAgentForwarding ,
+.Cm AllowTcpForwarding ,
+.Cm AuthorizedKeysFile ,
+.Cm AuthorizedPrincipalsFile ,
+.Cm Banner ,
+.Cm ChrootDirectory ,
+.Cm ForceCommand ,
+.Cm GatewayPorts ,
+.Cm GSSAPIAuthentication ,
+.Cm HostbasedAuthentication ,
+.Cm HostbasedUsesNameFromPacketOnly ,
+.Cm KbdInteractiveAuthentication ,
+.Cm KerberosAuthentication ,
+.Cm MaxAuthTries ,
+.Cm MaxSessions ,
+.Cm PasswordAuthentication ,
+.Cm PermitEmptyPasswords ,
+.Cm PermitOpen ,
+.Cm PermitRootLogin ,
+.Cm PermitTunnel ,
+.Cm PubkeyAuthentication ,
+.Cm RhostsRSAAuthentication ,
+.Cm RSAAuthentication ,
+.Cm X11DisplayOffset ,
+.Cm X11Forwarding
+and
+.Cm X11UseLocalHost .
+.It Cm MaxAuthTries
+Specifies the maximum number of authentication attempts permitted per
+connection.
+Once the number of failures reaches half this value,
+additional failures are logged.
+The default is 6.
+.It Cm MaxSessions
+Specifies the maximum number of open sessions permitted per network connection.
+The default is 10.
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+SSH daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g. "10:30:60").
+.Xr sshd 8
+will refuse connection attempts with a probability of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probability increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
+.It Cm PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is
+.Dq yes .
+.It Cm PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings.
+The default is
+.Dq no .
+.It Cm PermitOpen
+Specifies the destinations to which TCP port forwarding is permitted.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Dq any
+can be used to remove all restrictions and permit any forwarding requests.
+By default all port forwarding requests are permitted.
+.It Cm PermitRootLogin
+Specifies whether root can log in using
+.Xr ssh 1 .
+The argument must be
+.Dq yes ,
+.Dq without-password ,
+.Dq forced-commands-only ,
+or
+.Dq no .
+The default is
+.Dq yes .
+.Pp
+If this option is set to
+.Dq without-password ,
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only ,
+root login with public key authentication will be allowed,
+but only if the
+.Ar command
+option has been specified
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+All other authentication methods are disabled for root.
+.Pp
+If this option is set to
+.Dq no ,
+root is not allowed to log in.
+.It Cm PermitTunnel
+Specifies whether
+.Xr tun 4
+device forwarding is allowed.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2), or
+.Dq no .
+Specifying
+.Dq yes
+permits both
+.Dq point-to-point
+and
+.Dq ethernet .
+The default is
+.Dq no .
+.It Cm PermitUserEnvironment
+Specifies whether
+.Pa ~/.ssh/environment
+and
+.Cm environment=
+options in
+.Pa ~/.ssh/authorized_keys
+are processed by
+.Xr sshd 8 .
+The default is
+.Dq no .
+Enabling environment processing may enable users to bypass access
+restrictions in some configurations using mechanisms such as
+.Ev LD_PRELOAD .
+.It Cm PidFile
+Specifies the file that contains the process ID of the
+SSH daemon.
+The default is
+.Pa /var/run/sshd.pid .
+.It Cm Port
+Specifies the port number that
+.Xr sshd 8
+listens on.
+The default is 22.
+Multiple options of this type are permitted.
+See also
+.Cm ListenAddress .
+.It Cm PrintLastLog
+Specifies whether
+.Xr sshd 8
+should print the date and time of the last user login when a user logs
+in interactively.
+The default is
+.Dq yes .
+.It Cm PrintMotd
+Specifies whether
+.Xr sshd 8
+should print
+.Pa /etc/motd
+when a user logs in interactively.
+(On some systems it is also printed by the shell,
+.Pa /etc/profile ,
+or equivalent.)
+The default is
+.Dq yes .
+.It Cm Protocol
+Specifies the protocol versions
+.Xr sshd 8
+supports.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Sq 2 .
+Note that the order of the protocol list does not indicate preference,
+because the client selects among multiple protocol versions offered
+by the server.
+Specifying
+.Dq 2,1
+is identical to
+.Dq 1,2 .
+.It Cm PubkeyAuthentication
+Specifies whether public key authentication is allowed.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm RevokedKeys
+Specifies a list of revoked public keys.
+Keys listed in this file will be refused for public key authentication.
+Note that if this file is not readable, then public key authentication will
+be refused for all users.
+.It Cm RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RSAAuthentication
+Specifies whether pure RSA authentication is allowed.
+The default is
+.Dq yes .
+This option applies to protocol version 1 only.
+.It Cm ServerKeyBits
+Defines the number of bits in the ephemeral protocol version 1 server key.
+The minimum value is 512, and the default is 1024.
+.It Cm StrictModes
+Specifies whether
+.Xr sshd 8
+should check file modes and ownership of the
+user's files and home directory before accepting login.
+This is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable.
+The default is
+.Dq yes .
+Note that this does not apply to
+.Cm ChrootDirectory ,
+whose permissions and ownership are checked unconditionally.
+.It Cm Subsystem
+Configures an external subsystem (e.g. file transfer daemon).
+Arguments should be a subsystem name and a command (with optional arguments)
+to execute upon subsystem request.
+.Pp
+The command
+.Xr sftp-server 8
+implements the
+.Dq sftp
+file transfer subsystem.
+.Pp
+Alternately the name
+.Dq internal-sftp
+implements an in-process
+.Dq sftp
+server.
+This may simplify configurations using
+.Cm ChrootDirectory
+to force a different filesystem root on clients.
+.Pp
+By default no subsystems are defined.
+Note that this option applies to protocol version 2 only.
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Xr sshd 8 .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is AUTH.
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+On the other hand, if TCP keepalives are not sent,
+sessions may hang indefinitely on the server, leaving
+.Dq ghost
+users and consuming server resources.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the server will notice
+if the network goes down or the client host crashes.
+This avoids infinitely hanging sessions.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm TrustedUserCAKeys
+Specifies a file containing public keys of certificate authorities that are
+trusted to sign user certificates for authentication.
+Keys are listed one per line; empty lines and comments starting with
+.Ql #
+are allowed.
+If a certificate is presented for authentication and has its signing CA key
+listed in this file, then it may be used for authentication for any user
+listed in the certificate's principals list.
+Note that certificates that lack a list of principals will not be permitted
+for authentication using
+.Cm TrustedUserCAKeys .
+For more details on certificates, see the
+.Sx CERTIFICATES
+section in
+.Xr ssh-keygen 1 .
+.It Cm UseDNS
+Specifies whether
+.Xr sshd 8
+should look up the remote host name and check that
+the resolved host name for the remote IP address maps back to the
+very same IP address.
+The default is
+.Dq yes .
+.It Cm UseLogin
+Specifies whether
+.Xr login 1
+is used for interactive login sessions.
+The default is
+.Dq no .
+Note that
+.Xr login 1
+is never used for remote command execution.
+Note also, that if this is enabled,
+.Cm X11Forwarding
+will be disabled because
+.Xr login 1
+does not know how to handle
+.Xr xauth 1
+cookies.
+If
+.Cm UsePrivilegeSeparation
+is specified, it will be disabled after authentication.
+.It Cm UsePAM
+Enables the Pluggable Authentication Module interface.
+If set to
+.Dq yes
+this will enable PAM authentication using
+.Cm ChallengeResponseAuthentication
+and
+.Cm PasswordAuthentication
+in addition to PAM account and session module processing for all
+authentication types.
+.Pp
+Because PAM challenge-response authentication usually serves an equivalent
+role to password authentication, you should disable either
+.Cm PasswordAuthentication
+or
+.Cm ChallengeResponseAuthentication.
+.Pp
+If
+.Cm UsePAM
+is enabled, you will not be able to run
+.Xr sshd 8
+as a non-root user.
+The default is
+.Dq no .
+.It Cm UsePrivilegeSeparation
+Specifies whether
+.Xr sshd 8
+separates privileges by creating an unprivileged child process
+to deal with incoming network traffic.
+After successful authentication, another process will be created that has
+the privilege of the authenticated user.
+The goal of privilege separation is to prevent privilege
+escalation by containing any corruption within the unprivileged processes.
+The default is
+.Dq yes .
+If
+.Cm UsePrivilegeSeparation
+is set to
+.Dq sandbox
+then the pre-authentication unprivileged process is subject to additional
+restrictions.
+.It Cm X11DisplayOffset
+Specifies the first display number available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from interfering with real X11 servers.
+The default is 10.
+.It Cm X11Forwarding
+Specifies whether X11 forwarding is permitted.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+When X11 forwarding is enabled, there may be additional exposure to
+the server and to client displays if the
+.Xr sshd 8
+proxy display is configured to listen on the wildcard address (see
+.Cm X11UseLocalhost
+below), though this is not the default.
+Additionally, the authentication spoofing and authentication data
+verification and substitution occur on the client side.
+The security risk of using X11 forwarding is that the client's X11
+display server may be exposed to attack when the SSH client requests
+forwarding (see the warnings for
+.Cm ForwardX11
+in
+.Xr ssh_config 5 ) .
+A system administrator may have a stance in which they want to
+protect clients that may expose themselves to attack by unwittingly
+requesting X11 forwarding, which can warrant a
+.Dq no
+setting.
+.Pp
+Note that disabling X11 forwarding does not prevent users from
+forwarding X11 traffic, as users can always install their own forwarders.
+X11 forwarding is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm X11UseLocalhost
+Specifies whether
+.Xr sshd 8
+should bind the X11 forwarding server to the loopback address or to
+the wildcard address.
+By default,
+sshd binds the forwarding server to the loopback address and sets the
+hostname part of the
+.Ev DISPLAY
+environment variable to
+.Dq localhost .
+This prevents remote hosts from connecting to the proxy display.
+However, some older X11 clients may not function with this
+configuration.
+.Cm X11UseLocalhost
+may be set to
+.Dq no
+to specify that the forwarding server should be bound to the wildcard
+address.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh TIME FORMATS
+.Xr sshd 8
+command-line arguments and configuration file options that specify time
+may be expressed using a sequence of the form:
+.Sm off
+.Ar time Op Ar qualifier ,
+.Sm on
+where
+.Ar time
+is a positive integer value and
+.Ar qualifier
+is one of the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Aq Cm none
+seconds
+.It Cm s | Cm S
+seconds
+.It Cm m | Cm M
+minutes
+.It Cm h | Cm H
+hours
+.It Cm d | Cm D
+days
+.It Cm w | Cm W
+weeks
+.El
+.Pp
+Each member of the sequence is added together to calculate
+the total time value.
+.Pp
+Time format examples:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It 600
+600 seconds (10 minutes)
+.It 10m
+10 minutes
+.It 1h30m
+1 hour 30 minutes (90 minutes)
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Xr sshd 8 .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.El
+.Sh SEE ALSO
+.Xr sshd 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
diff --git a/.pc/helpful-wait-terminate.patch/serverloop.c b/.pc/helpful-wait-terminate.patch/serverloop.c
new file mode 100644 (file)
index 0000000..19b84ff
--- /dev/null
@@ -0,0 +1,1254 @@
+/* $OpenBSD: serverloop.c,v 1.160 2011/05/15 08:09:01 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Server main loop for handling the interactive session.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 support by Markus Friedl.
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <signal.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "canohost.h"
+#include "sshpty.h"
+#include "channels.h"
+#include "compat.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "session.h"
+#include "dispatch.h"
+#include "auth-options.h"
+#include "serverloop.h"
+#include "misc.h"
+#include "roaming.h"
+
+extern ServerOptions options;
+
+/* XXX */
+extern Kex *xxx_kex;
+extern Authctxt *the_authctxt;
+extern int use_privsep;
+
+static Buffer stdin_buffer;    /* Buffer for stdin data. */
+static Buffer stdout_buffer;   /* Buffer for stdout data. */
+static Buffer stderr_buffer;   /* Buffer for stderr data. */
+static int fdin;               /* Descriptor for stdin (for writing) */
+static int fdout;              /* Descriptor for stdout (for reading);
+                                  May be same number as fdin. */
+static int fderr;              /* Descriptor for stderr.  May be -1. */
+static long stdin_bytes = 0;   /* Number of bytes written to stdin. */
+static long stdout_bytes = 0;  /* Number of stdout bytes sent to client. */
+static long stderr_bytes = 0;  /* Number of stderr bytes sent to client. */
+static long fdout_bytes = 0;   /* Number of stdout bytes read from program. */
+static int stdin_eof = 0;      /* EOF message received from client. */
+static int fdout_eof = 0;      /* EOF encountered reading from fdout. */
+static int fderr_eof = 0;      /* EOF encountered readung from fderr. */
+static int fdin_is_tty = 0;    /* fdin points to a tty. */
+static int connection_in;      /* Connection to client (input). */
+static int connection_out;     /* Connection to client (output). */
+static int connection_closed = 0;      /* Connection to client closed. */
+static u_int buffer_high;      /* "Soft" max buffer size. */
+static int no_more_sessions = 0; /* Disallow further sessions. */
+
+/*
+ * This SIGCHLD kludge is used to detect when the child exits.  The server
+ * will exit after that, as soon as forwarded connections have terminated.
+ */
+
+static volatile sig_atomic_t child_terminated = 0;     /* The child has terminated. */
+
+/* Cleanup on signals (!use_privsep case only) */
+static volatile sig_atomic_t received_sigterm = 0;
+
+/* prototypes */
+static void server_init_dispatch(void);
+
+/*
+ * we write to this pipe if a SIGCHLD is caught in order to avoid
+ * the race between select() and child_terminated
+ */
+static int notify_pipe[2];
+static void
+notify_setup(void)
+{
+       if (pipe(notify_pipe) < 0) {
+               error("pipe(notify_pipe) failed %s", strerror(errno));
+       } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
+           (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
+               error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
+               close(notify_pipe[0]);
+               close(notify_pipe[1]);
+       } else {
+               set_nonblock(notify_pipe[0]);
+               set_nonblock(notify_pipe[1]);
+               return;
+       }
+       notify_pipe[0] = -1;    /* read end */
+       notify_pipe[1] = -1;    /* write end */
+}
+static void
+notify_parent(void)
+{
+       if (notify_pipe[1] != -1)
+               write(notify_pipe[1], "", 1);
+}
+static void
+notify_prepare(fd_set *readset)
+{
+       if (notify_pipe[0] != -1)
+               FD_SET(notify_pipe[0], readset);
+}
+static void
+notify_done(fd_set *readset)
+{
+       char c;
+
+       if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
+               while (read(notify_pipe[0], &c, 1) != -1)
+                       debug2("notify_done: reading");
+}
+
+/*ARGSUSED*/
+static void
+sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       child_terminated = 1;
+#ifndef _UNICOS
+       mysignal(SIGCHLD, sigchld_handler);
+#endif
+       notify_parent();
+       errno = save_errno;
+}
+
+/*ARGSUSED*/
+static void
+sigterm_handler(int sig)
+{
+       received_sigterm = sig;
+}
+
+/*
+ * Make packets from buffered stderr data, and buffer it for sending
+ * to the client.
+ */
+static void
+make_packets_from_stderr_data(void)
+{
+       u_int len;
+
+       /* Send buffered stderr data to the client. */
+       while (buffer_len(&stderr_buffer) > 0 &&
+           packet_not_very_much_data_to_write()) {
+               len = buffer_len(&stderr_buffer);
+               if (packet_is_interactive()) {
+                       if (len > 512)
+                               len = 512;
+               } else {
+                       /* Keep the packets at reasonable size. */
+                       if (len > packet_get_maxsize())
+                               len = packet_get_maxsize();
+               }
+               packet_start(SSH_SMSG_STDERR_DATA);
+               packet_put_string(buffer_ptr(&stderr_buffer), len);
+               packet_send();
+               buffer_consume(&stderr_buffer, len);
+               stderr_bytes += len;
+       }
+}
+
+/*
+ * Make packets from buffered stdout data, and buffer it for sending to the
+ * client.
+ */
+static void
+make_packets_from_stdout_data(void)
+{
+       u_int len;
+
+       /* Send buffered stdout data to the client. */
+       while (buffer_len(&stdout_buffer) > 0 &&
+           packet_not_very_much_data_to_write()) {
+               len = buffer_len(&stdout_buffer);
+               if (packet_is_interactive()) {
+                       if (len > 512)
+                               len = 512;
+               } else {
+                       /* Keep the packets at reasonable size. */
+                       if (len > packet_get_maxsize())
+                               len = packet_get_maxsize();
+               }
+               packet_start(SSH_SMSG_STDOUT_DATA);
+               packet_put_string(buffer_ptr(&stdout_buffer), len);
+               packet_send();
+               buffer_consume(&stdout_buffer, len);
+               stdout_bytes += len;
+       }
+}
+
+static void
+client_alive_check(void)
+{
+       int channel_id;
+
+       /* timeout, check to see how many we have had */
+       if (packet_inc_alive_timeouts() > options.client_alive_count_max) {
+               logit("Timeout, client not responding.");
+               cleanup_exit(255);
+       }
+
+       /*
+        * send a bogus global/channel request with "wantreply",
+        * we should get back a failure
+        */
+       if ((channel_id = channel_find_open()) == -1) {
+               packet_start(SSH2_MSG_GLOBAL_REQUEST);
+               packet_put_cstring("keepalive@openssh.com");
+               packet_put_char(1);     /* boolean: want reply */
+       } else {
+               channel_request_start(channel_id, "keepalive@openssh.com", 1);
+       }
+       packet_send();
+}
+
+/*
+ * Sleep in select() until we can do something.  This will initialize the
+ * select masks.  Upon return, the masks will indicate which descriptors
+ * have data or can accept data.  Optionally, a maximum time can be specified
+ * for the duration of the wait (0 = infinite).
+ */
+static void
+wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
+    u_int *nallocp, u_int max_time_milliseconds)
+{
+       struct timeval tv, *tvp;
+       int ret;
+       int client_alive_scheduled = 0;
+       int program_alive_scheduled = 0;
+
+       /*
+        * if using client_alive, set the max timeout accordingly,
+        * and indicate that this particular timeout was for client
+        * alive by setting the client_alive_scheduled flag.
+        *
+        * this could be randomized somewhat to make traffic
+        * analysis more difficult, but we're not doing it yet.
+        */
+       if (compat20 &&
+           max_time_milliseconds == 0 && options.client_alive_interval) {
+               client_alive_scheduled = 1;
+               max_time_milliseconds = options.client_alive_interval * 1000;
+       }
+
+       /* Allocate and update select() masks for channel descriptors. */
+       channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, 0);
+
+       if (compat20) {
+#if 0
+               /* wrong: bad condition XXX */
+               if (channel_not_very_much_buffered_data())
+#endif
+               FD_SET(connection_in, *readsetp);
+       } else {
+               /*
+                * Read packets from the client unless we have too much
+                * buffered stdin or channel data.
+                */
+               if (buffer_len(&stdin_buffer) < buffer_high &&
+                   channel_not_very_much_buffered_data())
+                       FD_SET(connection_in, *readsetp);
+               /*
+                * If there is not too much data already buffered going to
+                * the client, try to get some more data from the program.
+                */
+               if (packet_not_very_much_data_to_write()) {
+                       program_alive_scheduled = child_terminated;
+                       if (!fdout_eof)
+                               FD_SET(fdout, *readsetp);
+                       if (!fderr_eof)
+                               FD_SET(fderr, *readsetp);
+               }
+               /*
+                * If we have buffered data, try to write some of that data
+                * to the program.
+                */
+               if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
+                       FD_SET(fdin, *writesetp);
+       }
+       notify_prepare(*readsetp);
+
+       /*
+        * If we have buffered packet data going to the client, mark that
+        * descriptor.
+        */
+       if (packet_have_data_to_write())
+               FD_SET(connection_out, *writesetp);
+
+       /*
+        * If child has terminated and there is enough buffer space to read
+        * from it, then read as much as is available and exit.
+        */
+       if (child_terminated && packet_not_very_much_data_to_write())
+               if (max_time_milliseconds == 0 || client_alive_scheduled)
+                       max_time_milliseconds = 100;
+
+       if (max_time_milliseconds == 0)
+               tvp = NULL;
+       else {
+               tv.tv_sec = max_time_milliseconds / 1000;
+               tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
+               tvp = &tv;
+       }
+
+       /* Wait for something to happen, or the timeout to expire. */
+       ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+
+       if (ret == -1) {
+               memset(*readsetp, 0, *nallocp);
+               memset(*writesetp, 0, *nallocp);
+               if (errno != EINTR)
+                       error("select: %.100s", strerror(errno));
+       } else {
+               if (ret == 0 && client_alive_scheduled)
+                       client_alive_check();
+               if (!compat20 && program_alive_scheduled && fdin_is_tty) {
+                       if (!fdout_eof)
+                               FD_SET(fdout, *readsetp);
+                       if (!fderr_eof)
+                               FD_SET(fderr, *readsetp);
+               }
+       }
+
+       notify_done(*readsetp);
+}
+
+/*
+ * Processes input from the client and the program.  Input data is stored
+ * in buffers and processed later.
+ */
+static void
+process_input(fd_set *readset)
+{
+       int len;
+       char buf[16384];
+
+       /* Read and buffer any input data from the client. */
+       if (FD_ISSET(connection_in, readset)) {
+               int cont = 0;
+               len = roaming_read(connection_in, buf, sizeof(buf), &cont);
+               if (len == 0) {
+                       if (cont)
+                               return;
+                       verbose("Connection closed by %.100s",
+                           get_remote_ipaddr());
+                       connection_closed = 1;
+                       if (compat20)
+                               return;
+                       cleanup_exit(255);
+               } else if (len < 0) {
+                       if (errno != EINTR && errno != EAGAIN &&
+                           errno != EWOULDBLOCK) {
+                               verbose("Read error from remote host "
+                                   "%.100s: %.100s",
+                                   get_remote_ipaddr(), strerror(errno));
+                               cleanup_exit(255);
+                       }
+               } else {
+                       /* Buffer any received data. */
+                       packet_process_incoming(buf, len);
+               }
+       }
+       if (compat20)
+               return;
+
+       /* Read and buffer any available stdout data from the program. */
+       if (!fdout_eof && FD_ISSET(fdout, readset)) {
+               errno = 0;
+               len = read(fdout, buf, sizeof(buf));
+               if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
+                   errno == EWOULDBLOCK) && !child_terminated))) {
+                       /* do nothing */
+#ifndef PTY_ZEROREAD
+               } else if (len <= 0) {
+#else
+               } else if ((!isatty(fdout) && len <= 0) ||
+                   (isatty(fdout) && (len < 0 || (len == 0 && errno != 0)))) {
+#endif
+                       fdout_eof = 1;
+               } else {
+                       buffer_append(&stdout_buffer, buf, len);
+                       fdout_bytes += len;
+               }
+       }
+       /* Read and buffer any available stderr data from the program. */
+       if (!fderr_eof && FD_ISSET(fderr, readset)) {
+               errno = 0;
+               len = read(fderr, buf, sizeof(buf));
+               if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
+                   errno == EWOULDBLOCK) && !child_terminated))) {
+                       /* do nothing */
+#ifndef PTY_ZEROREAD
+               } else if (len <= 0) {
+#else
+               } else if ((!isatty(fderr) && len <= 0) ||
+                   (isatty(fderr) && (len < 0 || (len == 0 && errno != 0)))) {
+#endif
+                       fderr_eof = 1;
+               } else {
+                       buffer_append(&stderr_buffer, buf, len);
+               }
+       }
+}
+
+/*
+ * Sends data from internal buffers to client program stdin.
+ */
+static void
+process_output(fd_set *writeset)
+{
+       struct termios tio;
+       u_char *data;
+       u_int dlen;
+       int len;
+
+       /* Write buffered data to program stdin. */
+       if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
+               data = buffer_ptr(&stdin_buffer);
+               dlen = buffer_len(&stdin_buffer);
+               len = write(fdin, data, dlen);
+               if (len < 0 &&
+                   (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
+                       /* do nothing */
+               } else if (len <= 0) {
+                       if (fdin != fdout)
+                               close(fdin);
+                       else
+                               shutdown(fdin, SHUT_WR); /* We will no longer send. */
+                       fdin = -1;
+               } else {
+                       /* Successful write. */
+                       if (fdin_is_tty && dlen >= 1 && data[0] != '\r' &&
+                           tcgetattr(fdin, &tio) == 0 &&
+                           !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
+                               /*
+                                * Simulate echo to reduce the impact of
+                                * traffic analysis
+                                */
+                               packet_send_ignore(len);
+                               packet_send();
+                       }
+                       /* Consume the data from the buffer. */
+                       buffer_consume(&stdin_buffer, len);
+                       /* Update the count of bytes written to the program. */
+                       stdin_bytes += len;
+               }
+       }
+       /* Send any buffered packet data to the client. */
+       if (FD_ISSET(connection_out, writeset))
+               packet_write_poll();
+}
+
+/*
+ * Wait until all buffered output has been sent to the client.
+ * This is used when the program terminates.
+ */
+static void
+drain_output(void)
+{
+       /* Send any buffered stdout data to the client. */
+       if (buffer_len(&stdout_buffer) > 0) {
+               packet_start(SSH_SMSG_STDOUT_DATA);
+               packet_put_string(buffer_ptr(&stdout_buffer),
+                                 buffer_len(&stdout_buffer));
+               packet_send();
+               /* Update the count of sent bytes. */
+               stdout_bytes += buffer_len(&stdout_buffer);
+       }
+       /* Send any buffered stderr data to the client. */
+       if (buffer_len(&stderr_buffer) > 0) {
+               packet_start(SSH_SMSG_STDERR_DATA);
+               packet_put_string(buffer_ptr(&stderr_buffer),
+                                 buffer_len(&stderr_buffer));
+               packet_send();
+               /* Update the count of sent bytes. */
+               stderr_bytes += buffer_len(&stderr_buffer);
+       }
+       /* Wait until all buffered data has been written to the client. */
+       packet_write_wait();
+}
+
+static void
+process_buffered_input_packets(void)
+{
+       dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL);
+}
+
+/*
+ * Performs the interactive session.  This handles data transmission between
+ * the client and the program.  Note that the notion of stdin, stdout, and
+ * stderr in this function is sort of reversed: this function writes to
+ * stdin (of the child program), and reads from stdout and stderr (of the
+ * child program).
+ */
+void
+server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
+{
+       fd_set *readset = NULL, *writeset = NULL;
+       int max_fd = 0;
+       u_int nalloc = 0;
+       int wait_status;        /* Status returned by wait(). */
+       pid_t wait_pid;         /* pid returned by wait(). */
+       int waiting_termination = 0;    /* Have displayed waiting close message. */
+       u_int max_time_milliseconds;
+       u_int previous_stdout_buffer_bytes;
+       u_int stdout_buffer_bytes;
+       int type;
+
+       debug("Entering interactive session.");
+
+       /* Initialize the SIGCHLD kludge. */
+       child_terminated = 0;
+       mysignal(SIGCHLD, sigchld_handler);
+
+       if (!use_privsep) {
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGINT, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+       }
+
+       /* Initialize our global variables. */
+       fdin = fdin_arg;
+       fdout = fdout_arg;
+       fderr = fderr_arg;
+
+       /* nonblocking IO */
+       set_nonblock(fdin);
+       set_nonblock(fdout);
+       /* we don't have stderr for interactive terminal sessions, see below */
+       if (fderr != -1)
+               set_nonblock(fderr);
+
+       if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin))
+               fdin_is_tty = 1;
+
+       connection_in = packet_get_connection_in();
+       connection_out = packet_get_connection_out();
+
+       notify_setup();
+
+       previous_stdout_buffer_bytes = 0;
+
+       /* Set approximate I/O buffer size. */
+       if (packet_is_interactive())
+               buffer_high = 4096;
+       else
+               buffer_high = 64 * 1024;
+
+#if 0
+       /* Initialize max_fd to the maximum of the known file descriptors. */
+       max_fd = MAX(connection_in, connection_out);
+       max_fd = MAX(max_fd, fdin);
+       max_fd = MAX(max_fd, fdout);
+       if (fderr != -1)
+               max_fd = MAX(max_fd, fderr);
+#endif
+
+       /* Initialize Initialize buffers. */
+       buffer_init(&stdin_buffer);
+       buffer_init(&stdout_buffer);
+       buffer_init(&stderr_buffer);
+
+       /*
+        * If we have no separate fderr (which is the case when we have a pty
+        * - there we cannot make difference between data sent to stdout and
+        * stderr), indicate that we have seen an EOF from stderr.  This way
+        * we don't need to check the descriptor everywhere.
+        */
+       if (fderr == -1)
+               fderr_eof = 1;
+
+       server_init_dispatch();
+
+       /* Main loop of the server for the interactive session mode. */
+       for (;;) {
+
+               /* Process buffered packets from the client. */
+               process_buffered_input_packets();
+
+               /*
+                * If we have received eof, and there is no more pending
+                * input data, cause a real eof by closing fdin.
+                */
+               if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
+                       if (fdin != fdout)
+                               close(fdin);
+                       else
+                               shutdown(fdin, SHUT_WR); /* We will no longer send. */
+                       fdin = -1;
+               }
+               /* Make packets from buffered stderr data to send to the client. */
+               make_packets_from_stderr_data();
+
+               /*
+                * Make packets from buffered stdout data to send to the
+                * client. If there is very little to send, this arranges to
+                * not send them now, but to wait a short while to see if we
+                * are getting more data. This is necessary, as some systems
+                * wake up readers from a pty after each separate character.
+                */
+               max_time_milliseconds = 0;
+               stdout_buffer_bytes = buffer_len(&stdout_buffer);
+               if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
+                   stdout_buffer_bytes != previous_stdout_buffer_bytes) {
+                       /* try again after a while */
+                       max_time_milliseconds = 10;
+               } else {
+                       /* Send it now. */
+                       make_packets_from_stdout_data();
+               }
+               previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
+
+               /* Send channel data to the client. */
+               if (packet_not_very_much_data_to_write())
+                       channel_output_poll();
+
+               /*
+                * Bail out of the loop if the program has closed its output
+                * descriptors, and we have no more data to send to the
+                * client, and there is no pending buffered data.
+                */
+               if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
+                   buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
+                       if (!channel_still_open())
+                               break;
+                       if (!waiting_termination) {
+                               const char *s = "Waiting for forwarded connections to terminate...\r\n";
+                               char *cp;
+                               waiting_termination = 1;
+                               buffer_append(&stderr_buffer, s, strlen(s));
+
+                               /* Display list of open channels. */
+                               cp = channel_open_message();
+                               buffer_append(&stderr_buffer, cp, strlen(cp));
+                               xfree(cp);
+                       }
+               }
+               max_fd = MAX(connection_in, connection_out);
+               max_fd = MAX(max_fd, fdin);
+               max_fd = MAX(max_fd, fdout);
+               max_fd = MAX(max_fd, fderr);
+               max_fd = MAX(max_fd, notify_pipe[0]);
+
+               /* Sleep in select() until we can do something. */
+               wait_until_can_do_something(&readset, &writeset, &max_fd,
+                   &nalloc, max_time_milliseconds);
+
+               if (received_sigterm) {
+                       logit("Exiting on signal %d", received_sigterm);
+                       /* Clean up sessions, utmp, etc. */
+                       cleanup_exit(255);
+               }
+
+               /* Process any channel events. */
+               channel_after_select(readset, writeset);
+
+               /* Process input from the client and from program stdout/stderr. */
+               process_input(readset);
+
+               /* Process output to the client and to program stdin. */
+               process_output(writeset);
+       }
+       if (readset)
+               xfree(readset);
+       if (writeset)
+               xfree(writeset);
+
+       /* Cleanup and termination code. */
+
+       /* Wait until all output has been sent to the client. */
+       drain_output();
+
+       debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
+           stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
+
+       /* Free and clear the buffers. */
+       buffer_free(&stdin_buffer);
+       buffer_free(&stdout_buffer);
+       buffer_free(&stderr_buffer);
+
+       /* Close the file descriptors. */
+       if (fdout != -1)
+               close(fdout);
+       fdout = -1;
+       fdout_eof = 1;
+       if (fderr != -1)
+               close(fderr);
+       fderr = -1;
+       fderr_eof = 1;
+       if (fdin != -1)
+               close(fdin);
+       fdin = -1;
+
+       channel_free_all();
+
+       /* We no longer want our SIGCHLD handler to be called. */
+       mysignal(SIGCHLD, SIG_DFL);
+
+       while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
+               if (errno != EINTR)
+                       packet_disconnect("wait: %.100s", strerror(errno));
+       if (wait_pid != pid)
+               error("Strange, wait returned pid %ld, expected %ld",
+                   (long)wait_pid, (long)pid);
+
+       /* Check if it exited normally. */
+       if (WIFEXITED(wait_status)) {
+               /* Yes, normal exit.  Get exit status and send it to the client. */
+               debug("Command exited with status %d.", WEXITSTATUS(wait_status));
+               packet_start(SSH_SMSG_EXITSTATUS);
+               packet_put_int(WEXITSTATUS(wait_status));
+               packet_send();
+               packet_write_wait();
+
+               /*
+                * Wait for exit confirmation.  Note that there might be
+                * other packets coming before it; however, the program has
+                * already died so we just ignore them.  The client is
+                * supposed to respond with the confirmation when it receives
+                * the exit status.
+                */
+               do {
+                       type = packet_read();
+               }
+               while (type != SSH_CMSG_EXIT_CONFIRMATION);
+
+               debug("Received exit confirmation.");
+               return;
+       }
+       /* Check if the program terminated due to a signal. */
+       if (WIFSIGNALED(wait_status))
+               packet_disconnect("Command terminated on signal %d.",
+                                 WTERMSIG(wait_status));
+
+       /* Some weird exit cause.  Just exit. */
+       packet_disconnect("wait returned status %04x.", wait_status);
+       /* NOTREACHED */
+}
+
+static void
+collect_children(void)
+{
+       pid_t pid;
+       sigset_t oset, nset;
+       int status;
+
+       /* block SIGCHLD while we check for dead children */
+       sigemptyset(&nset);
+       sigaddset(&nset, SIGCHLD);
+       sigprocmask(SIG_BLOCK, &nset, &oset);
+       if (child_terminated) {
+               debug("Received SIGCHLD.");
+               while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+                   (pid < 0 && errno == EINTR))
+                       if (pid > 0)
+                               session_close_by_pid(pid, status);
+               child_terminated = 0;
+       }
+       sigprocmask(SIG_SETMASK, &oset, NULL);
+}
+
+void
+server_loop2(Authctxt *authctxt)
+{
+       fd_set *readset = NULL, *writeset = NULL;
+       int rekeying = 0, max_fd, nalloc = 0;
+
+       debug("Entering interactive session for SSH2.");
+
+       mysignal(SIGCHLD, sigchld_handler);
+       child_terminated = 0;
+       connection_in = packet_get_connection_in();
+       connection_out = packet_get_connection_out();
+
+       if (!use_privsep) {
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGINT, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+       }
+
+       notify_setup();
+
+       max_fd = MAX(connection_in, connection_out);
+       max_fd = MAX(max_fd, notify_pipe[0]);
+
+       server_init_dispatch();
+
+       for (;;) {
+               process_buffered_input_packets();
+
+               rekeying = (xxx_kex != NULL && !xxx_kex->done);
+
+               if (!rekeying && packet_not_very_much_data_to_write())
+                       channel_output_poll();
+               wait_until_can_do_something(&readset, &writeset, &max_fd,
+                   &nalloc, 0);
+
+               if (received_sigterm) {
+                       logit("Exiting on signal %d", received_sigterm);
+                       /* Clean up sessions, utmp, etc. */
+                       cleanup_exit(255);
+               }
+
+               collect_children();
+               if (!rekeying) {
+                       channel_after_select(readset, writeset);
+                       if (packet_need_rekeying()) {
+                               debug("need rekeying");
+                               xxx_kex->done = 0;
+                               kex_send_kexinit(xxx_kex);
+                       }
+               }
+               process_input(readset);
+               if (connection_closed)
+                       break;
+               process_output(writeset);
+       }
+       collect_children();
+
+       if (readset)
+               xfree(readset);
+       if (writeset)
+               xfree(writeset);
+
+       /* free all channels, no more reads and writes */
+       channel_free_all();
+
+       /* free remaining sessions, e.g. remove wtmp entries */
+       session_destroy_all(NULL);
+}
+
+static void
+server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
+{
+       debug("Got %d/%u for keepalive", type, seq);
+       /*
+        * reset timeout, since we got a sane answer from the client.
+        * even if this was generated by something other than
+        * the bogus CHANNEL_REQUEST we send for keepalives.
+        */
+       packet_set_alive_timeouts(0);
+}
+
+static void
+server_input_stdin_data(int type, u_int32_t seq, void *ctxt)
+{
+       char *data;
+       u_int data_len;
+
+       /* Stdin data from the client.  Append it to the buffer. */
+       /* Ignore any data if the client has closed stdin. */
+       if (fdin == -1)
+               return;
+       data = packet_get_string(&data_len);
+       packet_check_eom();
+       buffer_append(&stdin_buffer, data, data_len);
+       memset(data, 0, data_len);
+       xfree(data);
+}
+
+static void
+server_input_eof(int type, u_int32_t seq, void *ctxt)
+{
+       /*
+        * Eof from the client.  The stdin descriptor to the
+        * program will be closed when all buffered data has
+        * drained.
+        */
+       debug("EOF received for stdin.");
+       packet_check_eom();
+       stdin_eof = 1;
+}
+
+static void
+server_input_window_size(int type, u_int32_t seq, void *ctxt)
+{
+       u_int row = packet_get_int();
+       u_int col = packet_get_int();
+       u_int xpixel = packet_get_int();
+       u_int ypixel = packet_get_int();
+
+       debug("Window change received.");
+       packet_check_eom();
+       if (fdin != -1)
+               pty_change_window_size(fdin, row, col, xpixel, ypixel);
+}
+
+static Channel *
+server_request_direct_tcpip(void)
+{
+       Channel *c;
+       char *target, *originator;
+       u_short target_port, originator_port;
+
+       target = packet_get_string(NULL);
+       target_port = packet_get_int();
+       originator = packet_get_string(NULL);
+       originator_port = packet_get_int();
+       packet_check_eom();
+
+       debug("server_request_direct_tcpip: originator %s port %d, target %s "
+           "port %d", originator, originator_port, target, target_port);
+
+       /* XXX check permission */
+       c = channel_connect_to(target, target_port,
+           "direct-tcpip", "direct-tcpip");
+
+       xfree(originator);
+       xfree(target);
+
+       return c;
+}
+
+static Channel *
+server_request_tun(void)
+{
+       Channel *c = NULL;
+       int mode, tun;
+       int sock;
+
+       mode = packet_get_int();
+       switch (mode) {
+       case SSH_TUNMODE_POINTOPOINT:
+       case SSH_TUNMODE_ETHERNET:
+               break;
+       default:
+               packet_send_debug("Unsupported tunnel device mode.");
+               return NULL;
+       }
+       if ((options.permit_tun & mode) == 0) {
+               packet_send_debug("Server has rejected tunnel device "
+                   "forwarding");
+               return NULL;
+       }
+
+       tun = packet_get_int();
+       if (forced_tun_device != -1) {
+               if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
+                       goto done;
+               tun = forced_tun_device;
+       }
+       sock = tun_open(tun, mode);
+       if (sock < 0)
+               goto done;
+       c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
+           CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+       c->datagram = 1;
+#if defined(SSH_TUN_FILTER)
+       if (mode == SSH_TUNMODE_POINTOPOINT)
+               channel_register_filter(c->self, sys_tun_infilter,
+                   sys_tun_outfilter, NULL, NULL);
+#endif
+
+ done:
+       if (c == NULL)
+               packet_send_debug("Failed to open the tunnel device.");
+       return c;
+}
+
+static Channel *
+server_request_session(void)
+{
+       Channel *c;
+
+       debug("input_session_request");
+       packet_check_eom();
+
+       if (no_more_sessions) {
+               packet_disconnect("Possible attack: attempt to open a session "
+                   "after additional sessions disabled");
+       }
+
+       /*
+        * A server session has no fd to read or write until a
+        * CHANNEL_REQUEST for a shell is made, so we set the type to
+        * SSH_CHANNEL_LARVAL.  Additionally, a callback for handling all
+        * CHANNEL_REQUEST messages is registered.
+        */
+       c = channel_new("session", SSH_CHANNEL_LARVAL,
+           -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
+           0, "server-session", 1);
+       if (session_open(the_authctxt, c->self) != 1) {
+               debug("session open failed, free channel %d", c->self);
+               channel_free(c);
+               return NULL;
+       }
+       channel_register_cleanup(c->self, session_close_by_channel, 0);
+       return c;
+}
+
+static void
+server_input_channel_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       char *ctype;
+       int rchan;
+       u_int rmaxpack, rwindow, len;
+
+       ctype = packet_get_string(&len);
+       rchan = packet_get_int();
+       rwindow = packet_get_int();
+       rmaxpack = packet_get_int();
+
+       debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
+           ctype, rchan, rwindow, rmaxpack);
+
+       if (strcmp(ctype, "session") == 0) {
+               c = server_request_session();
+       } else if (strcmp(ctype, "direct-tcpip") == 0) {
+               c = server_request_direct_tcpip();
+       } else if (strcmp(ctype, "tun@openssh.com") == 0) {
+               c = server_request_tun();
+       }
+       if (c != NULL) {
+               debug("server_input_channel_open: confirm %s", ctype);
+               c->remote_id = rchan;
+               c->remote_window = rwindow;
+               c->remote_maxpacket = rmaxpack;
+               if (c->type != SSH_CHANNEL_CONNECTING) {
+                       packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
+                       packet_put_int(c->remote_id);
+                       packet_put_int(c->self);
+                       packet_put_int(c->local_window);
+                       packet_put_int(c->local_maxpacket);
+                       packet_send();
+               }
+       } else {
+               debug("server_input_channel_open: failure %s", ctype);
+               packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(rchan);
+               packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
+               if (!(datafellows & SSH_BUG_OPENFAILURE)) {
+                       packet_put_cstring("open failed");
+                       packet_put_cstring("");
+               }
+               packet_send();
+       }
+       xfree(ctype);
+}
+
+static void
+server_input_global_request(int type, u_int32_t seq, void *ctxt)
+{
+       char *rtype;
+       int want_reply;
+       int success = 0, allocated_listen_port = 0;
+
+       rtype = packet_get_string(NULL);
+       want_reply = packet_get_char();
+       debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
+
+       /* -R style forwarding */
+       if (strcmp(rtype, "tcpip-forward") == 0) {
+               struct passwd *pw;
+               char *listen_address;
+               u_short listen_port;
+
+               pw = the_authctxt->pw;
+               if (pw == NULL || !the_authctxt->valid)
+                       fatal("server_input_global_request: no/invalid user");
+               listen_address = packet_get_string(NULL);
+               listen_port = (u_short)packet_get_int();
+               debug("server_input_global_request: tcpip-forward listen %s port %d",
+                   listen_address, listen_port);
+
+               /* check permissions */
+               if (!options.allow_tcp_forwarding ||
+                   no_port_forwarding_flag ||
+                   (!want_reply && listen_port == 0)
+#ifndef NO_IPPORT_RESERVED_CONCEPT
+                   || (listen_port != 0 && listen_port < IPPORT_RESERVED &&
+                    pw->pw_uid != 0)
+#endif
+                   ) {
+                       success = 0;
+                       packet_send_debug("Server has disabled port forwarding.");
+               } else {
+                       /* Start listening on the port */
+                       success = channel_setup_remote_fwd_listener(
+                           listen_address, listen_port,
+                           &allocated_listen_port, options.gateway_ports);
+               }
+               xfree(listen_address);
+       } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
+               char *cancel_address;
+               u_short cancel_port;
+
+               cancel_address = packet_get_string(NULL);
+               cancel_port = (u_short)packet_get_int();
+               debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
+                   cancel_address, cancel_port);
+
+               success = channel_cancel_rport_listener(cancel_address,
+                   cancel_port);
+               xfree(cancel_address);
+       } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
+               no_more_sessions = 1;
+               success = 1;
+       }
+       if (want_reply) {
+               packet_start(success ?
+                   SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
+               if (success && allocated_listen_port > 0)
+                       packet_put_int(allocated_listen_port);
+               packet_send();
+               packet_write_wait();
+       }
+       xfree(rtype);
+}
+
+static void
+server_input_channel_req(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c;
+       int id, reply, success = 0;
+       char *rtype;
+
+       id = packet_get_int();
+       rtype = packet_get_string(NULL);
+       reply = packet_get_char();
+
+       debug("server_input_channel_req: channel %d request %s reply %d",
+           id, rtype, reply);
+
+       if ((c = channel_lookup(id)) == NULL)
+               packet_disconnect("server_input_channel_req: "
+                   "unknown channel %d", id);
+       if (!strcmp(rtype, "eow@openssh.com")) {
+               packet_check_eom();
+               chan_rcvd_eow(c);
+       } else if ((c->type == SSH_CHANNEL_LARVAL ||
+           c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
+               success = session_input_channel_req(c, rtype);
+       if (reply) {
+               packet_start(success ?
+                   SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
+               packet_put_int(c->remote_id);
+               packet_send();
+       }
+       xfree(rtype);
+}
+
+static void
+server_init_dispatch_20(void)
+{
+       debug("server_init_dispatch_20");
+       dispatch_init(&dispatch_protocol_error);
+       dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+       dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+       dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
+       dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+       dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
+       /* client_alive */
+       dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
+       dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
+       dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
+       dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
+       /* rekeying */
+       dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+}
+static void
+server_init_dispatch_13(void)
+{
+       debug("server_init_dispatch_13");
+       dispatch_init(NULL);
+       dispatch_set(SSH_CMSG_EOF, &server_input_eof);
+       dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
+       dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
+}
+static void
+server_init_dispatch_15(void)
+{
+       server_init_dispatch_13();
+       debug("server_init_dispatch_15");
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
+}
+static void
+server_init_dispatch(void)
+{
+       if (compat20)
+               server_init_dispatch_20();
+       else if (compat13)
+               server_init_dispatch_13();
+       else
+               server_init_dispatch_15();
+}
diff --git a/.pc/keepalive-extensions.patch/readconf.c b/.pc/keepalive-extensions.patch/readconf.c
new file mode 100644 (file)
index 0000000..6c59c4d
--- /dev/null
@@ -0,0 +1,1524 @@
+/* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for reading the configuration files.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "compat.h"
+#include "cipher.h"
+#include "pathnames.h"
+#include "log.h"
+#include "key.h"
+#include "readconf.h"
+#include "match.h"
+#include "misc.h"
+#include "buffer.h"
+#include "kex.h"
+#include "mac.h"
+
+/* Format of the configuration file:
+
+   # Configuration data is parsed as follows:
+   #  1. command line options
+   #  2. user-specific file
+   #  3. system-wide file
+   # Any configuration value is only changed the first time it is set.
+   # Thus, host-specific definitions should be at the beginning of the
+   # configuration file, and defaults at the end.
+
+   # Host-specific declarations.  These may override anything above.  A single
+   # host may match multiple declarations; these are processed in the order
+   # that they are given in.
+
+   Host *.ngs.fi ngs.fi
+     User foo
+
+   Host fake.com
+     HostName another.host.name.real.org
+     User blaah
+     Port 34289
+     ForwardX11 no
+     ForwardAgent no
+
+   Host books.com
+     RemoteForward 9999 shadows.cs.hut.fi:9999
+     Cipher 3des
+
+   Host fascist.blob.com
+     Port 23123
+     User tylonen
+     PasswordAuthentication no
+
+   Host puukko.hut.fi
+     User t35124p
+     ProxyCommand ssh-proxy %h %p
+
+   Host *.fr
+     PublicKeyAuthentication no
+
+   Host *.su
+     Cipher none
+     PasswordAuthentication no
+
+   Host vpn.fake.com
+     Tunnel yes
+     TunnelDevice 3
+
+   # Defaults for various options
+   Host *
+     ForwardAgent no
+     ForwardX11 no
+     PasswordAuthentication yes
+     RSAAuthentication yes
+     RhostsRSAAuthentication yes
+     StrictHostKeyChecking yes
+     TcpKeepAlive no
+     IdentityFile ~/.ssh/identity
+     Port 22
+     EscapeChar ~
+
+*/
+
+/* Keyword tokens. */
+
+typedef enum {
+       oBadOption,
+       oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
+       oGatewayPorts, oExitOnForwardFailure,
+       oPasswordAuthentication, oRSAAuthentication,
+       oChallengeResponseAuthentication, oXAuthLocation,
+       oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
+       oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+       oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
+       oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
+       oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
+       oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
+       oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
+       oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
+       oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
+       oUseBlacklistedKeys,
+       oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
+       oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+       oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
+       oGssServerIdentity, 
+       oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+       oSendEnv, oControlPath, oControlMaster, oControlPersist,
+       oHashKnownHosts,
+       oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
+       oKexAlgorithms, oIPQoS, oRequestTTY,
+       oDeprecated, oUnsupported
+} OpCodes;
+
+/* Textual representations of the tokens. */
+
+static struct {
+       const char *name;
+       OpCodes opcode;
+} keywords[] = {
+       { "forwardagent", oForwardAgent },
+       { "forwardx11", oForwardX11 },
+       { "forwardx11trusted", oForwardX11Trusted },
+       { "forwardx11timeout", oForwardX11Timeout },
+       { "exitonforwardfailure", oExitOnForwardFailure },
+       { "xauthlocation", oXAuthLocation },
+       { "gatewayports", oGatewayPorts },
+       { "useprivilegedport", oUsePrivilegedPort },
+       { "rhostsauthentication", oDeprecated },
+       { "passwordauthentication", oPasswordAuthentication },
+       { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
+       { "kbdinteractivedevices", oKbdInteractiveDevices },
+       { "useblacklistedkeys", oUseBlacklistedKeys },
+       { "rsaauthentication", oRSAAuthentication },
+       { "pubkeyauthentication", oPubkeyAuthentication },
+       { "dsaauthentication", oPubkeyAuthentication },             /* alias */
+       { "rhostsrsaauthentication", oRhostsRSAAuthentication },
+       { "hostbasedauthentication", oHostbasedAuthentication },
+       { "challengeresponseauthentication", oChallengeResponseAuthentication },
+       { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
+       { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
+       { "kerberosauthentication", oUnsupported },
+       { "kerberostgtpassing", oUnsupported },
+       { "afstokenpassing", oUnsupported },
+#if defined(GSSAPI)
+       { "gssapiauthentication", oGssAuthentication },
+       { "gssapikeyexchange", oGssKeyEx },
+       { "gssapidelegatecredentials", oGssDelegateCreds },
+       { "gssapitrustdns", oGssTrustDns },
+       { "gssapiclientidentity", oGssClientIdentity },
+       { "gssapiserveridentity", oGssServerIdentity },
+       { "gssapirenewalforcesrekey", oGssRenewalRekey },
+#else
+       { "gssapiauthentication", oUnsupported },
+       { "gssapikeyexchange", oUnsupported },
+       { "gssapidelegatecredentials", oUnsupported },
+       { "gssapitrustdns", oUnsupported },
+       { "gssapiclientidentity", oUnsupported },
+       { "gssapirenewalforcesrekey", oUnsupported },
+#endif
+       { "fallbacktorsh", oDeprecated },
+       { "usersh", oDeprecated },
+       { "identityfile", oIdentityFile },
+       { "identityfile2", oIdentityFile },                     /* obsolete */
+       { "identitiesonly", oIdentitiesOnly },
+       { "hostname", oHostName },
+       { "hostkeyalias", oHostKeyAlias },
+       { "proxycommand", oProxyCommand },
+       { "port", oPort },
+       { "cipher", oCipher },
+       { "ciphers", oCiphers },
+       { "macs", oMacs },
+       { "protocol", oProtocol },
+       { "remoteforward", oRemoteForward },
+       { "localforward", oLocalForward },
+       { "user", oUser },
+       { "host", oHost },
+       { "escapechar", oEscapeChar },
+       { "globalknownhostsfile", oGlobalKnownHostsFile },
+       { "globalknownhostsfile2", oDeprecated },
+       { "userknownhostsfile", oUserKnownHostsFile },
+       { "userknownhostsfile2", oDeprecated }, 
+       { "connectionattempts", oConnectionAttempts },
+       { "batchmode", oBatchMode },
+       { "checkhostip", oCheckHostIP },
+       { "stricthostkeychecking", oStrictHostKeyChecking },
+       { "compression", oCompression },
+       { "compressionlevel", oCompressionLevel },
+       { "tcpkeepalive", oTCPKeepAlive },
+       { "keepalive", oTCPKeepAlive },                         /* obsolete */
+       { "numberofpasswordprompts", oNumberOfPasswordPrompts },
+       { "loglevel", oLogLevel },
+       { "dynamicforward", oDynamicForward },
+       { "preferredauthentications", oPreferredAuthentications },
+       { "hostkeyalgorithms", oHostKeyAlgorithms },
+       { "bindaddress", oBindAddress },
+#ifdef ENABLE_PKCS11
+       { "smartcarddevice", oPKCS11Provider },
+       { "pkcs11provider", oPKCS11Provider },
+#else
+       { "smartcarddevice", oUnsupported },
+       { "pkcs11provider", oUnsupported },
+#endif
+       { "clearallforwardings", oClearAllForwardings },
+       { "enablesshkeysign", oEnableSSHKeysign },
+       { "verifyhostkeydns", oVerifyHostKeyDNS },
+       { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
+       { "rekeylimit", oRekeyLimit },
+       { "connecttimeout", oConnectTimeout },
+       { "addressfamily", oAddressFamily },
+       { "serveraliveinterval", oServerAliveInterval },
+       { "serveralivecountmax", oServerAliveCountMax },
+       { "sendenv", oSendEnv },
+       { "controlpath", oControlPath },
+       { "controlmaster", oControlMaster },
+       { "controlpersist", oControlPersist },
+       { "hashknownhosts", oHashKnownHosts },
+       { "tunnel", oTunnel },
+       { "tunneldevice", oTunnelDevice },
+       { "localcommand", oLocalCommand },
+       { "permitlocalcommand", oPermitLocalCommand },
+       { "visualhostkey", oVisualHostKey },
+       { "useroaming", oUseRoaming },
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication",
+           oZeroKnowledgePasswordAuthentication },
+#else
+       { "zeroknowledgepasswordauthentication", oUnsupported },
+#endif
+       { "kexalgorithms", oKexAlgorithms },
+       { "ipqos", oIPQoS },
+       { "requesttty", oRequestTTY },
+
+       { NULL, oBadOption }
+};
+
+/*
+ * Adds a local TCP/IP port forward to options.  Never returns if there is an
+ * error.
+ */
+
+void
+add_local_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+#ifndef NO_IPPORT_RESERVED_CONCEPT
+       extern uid_t original_real_uid;
+       if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
+               fatal("Privileged ports can only be forwarded by root.");
+#endif
+       options->local_forwards = xrealloc(options->local_forwards,
+           options->num_local_forwards + 1,
+           sizeof(*options->local_forwards));
+       fwd = &options->local_forwards[options->num_local_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+}
+
+/*
+ * Adds a remote TCP/IP port forward to options.  Never returns if there is
+ * an error.
+ */
+
+void
+add_remote_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+
+       options->remote_forwards = xrealloc(options->remote_forwards,
+           options->num_remote_forwards + 1,
+           sizeof(*options->remote_forwards));
+       fwd = &options->remote_forwards[options->num_remote_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+       fwd->allocated_port = 0;
+}
+
+static void
+clear_forwardings(Options *options)
+{
+       int i;
+
+       for (i = 0; i < options->num_local_forwards; i++) {
+               if (options->local_forwards[i].listen_host != NULL)
+                       xfree(options->local_forwards[i].listen_host);
+               xfree(options->local_forwards[i].connect_host);
+       }
+       if (options->num_local_forwards > 0) {
+               xfree(options->local_forwards);
+               options->local_forwards = NULL;
+       }
+       options->num_local_forwards = 0;
+       for (i = 0; i < options->num_remote_forwards; i++) {
+               if (options->remote_forwards[i].listen_host != NULL)
+                       xfree(options->remote_forwards[i].listen_host);
+               xfree(options->remote_forwards[i].connect_host);
+       }
+       if (options->num_remote_forwards > 0) {
+               xfree(options->remote_forwards);
+               options->remote_forwards = NULL;
+       }
+       options->num_remote_forwards = 0;
+       options->tun_open = SSH_TUNMODE_NO;
+}
+
+/*
+ * Returns the number of the token pointed to by cp or oBadOption.
+ */
+
+static OpCodes
+parse_token(const char *cp, const char *filename, int linenum)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0)
+                       return keywords[i].opcode;
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return oBadOption;
+}
+
+/*
+ * Processes a single option line as used in the configuration files. This
+ * only sets those values that have not already been set.
+ */
+#define WHITESPACE " \t\r\n"
+
+int
+process_config_line(Options *options, const char *host,
+                   char *line, const char *filename, int linenum,
+                   int *activep)
+{
+       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+       char **cpptr, fwdarg[256];
+       u_int *uintptr, max_entries = 0;
+       int negated, opcode, *intptr, value, value2, scale;
+       LogLevel *log_level_ptr;
+       long long orig, val64;
+       size_t len;
+       Forward fwd;
+
+       /* Strip trailing whitespace */
+       for (len = strlen(line) - 1; len > 0; len--) {
+               if (strchr(WHITESPACE, line[len]) == NULL)
+                       break;
+               line[len] = '\0';
+       }
+
+       s = line;
+       /* Get the keyword. (Each line is supposed to begin with a keyword). */
+       if ((keyword = strdelim(&s)) == NULL)
+               return 0;
+       /* Ignore leading whitespace. */
+       if (*keyword == '\0')
+               keyword = strdelim(&s);
+       if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
+               return 0;
+
+       opcode = parse_token(keyword, filename, linenum);
+
+       switch (opcode) {
+       case oBadOption:
+               /* don't panic, but count bad options */
+               return -1;
+               /* NOTREACHED */
+       case oConnectTimeout:
+               intptr = &options->connection_timeout;
+parse_time:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardAgent:
+               intptr = &options->forward_agent;
+parse_flag:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else
+                       fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardX11:
+               intptr = &options->forward_x11;
+               goto parse_flag;
+
+       case oForwardX11Trusted:
+               intptr = &options->forward_x11_trusted;
+               goto parse_flag;
+       
+       case oForwardX11Timeout:
+               intptr = &options->forward_x11_timeout;
+               goto parse_time;
+
+       case oGatewayPorts:
+               intptr = &options->gateway_ports;
+               goto parse_flag;
+
+       case oExitOnForwardFailure:
+               intptr = &options->exit_on_forward_failure;
+               goto parse_flag;
+
+       case oUsePrivilegedPort:
+               intptr = &options->use_privileged_port;
+               goto parse_flag;
+
+       case oPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case oZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveDevices:
+               charptr = &options->kbd_interactive_devices;
+               goto parse_string;
+
+       case oPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case oRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case oRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case oHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case oChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case oUseBlacklistedKeys:
+               intptr = &options->use_blacklisted_keys;
+               goto parse_flag;
+
+       case oGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case oGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
+       case oGssDelegateCreds:
+               intptr = &options->gss_deleg_creds;
+               goto parse_flag;
+
+       case oGssTrustDns:
+               intptr = &options->gss_trust_dns;
+               goto parse_flag;
+
+       case oGssClientIdentity:
+               charptr = &options->gss_client_identity;
+               goto parse_string;
+
+       case oGssServerIdentity:
+               charptr = &options->gss_server_identity;
+               goto parse_string;
+
+       case oGssRenewalRekey:
+               intptr = &options->gss_renewal_rekey;
+               goto parse_flag;
+
+       case oBatchMode:
+               intptr = &options->batch_mode;
+               goto parse_flag;
+
+       case oCheckHostIP:
+               intptr = &options->check_host_ip;
+               goto parse_flag;
+
+       case oVerifyHostKeyDNS:
+               intptr = &options->verify_host_key_dns;
+               goto parse_yesnoask;
+
+       case oStrictHostKeyChecking:
+               intptr = &options->strict_host_key_checking;
+parse_yesnoask:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no/ask argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "ask") == 0)
+                       value = 2;
+               else
+                       fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCompression:
+               intptr = &options->compression;
+               goto parse_flag;
+
+       case oTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case oNoHostAuthenticationForLocalhost:
+               intptr = &options->no_host_authentication_for_localhost;
+               goto parse_flag;
+
+       case oNumberOfPasswordPrompts:
+               intptr = &options->number_of_password_prompts;
+               goto parse_int;
+
+       case oCompressionLevel:
+               intptr = &options->compression_level;
+               goto parse_int;
+
+       case oRekeyLimit:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               orig = val64 = strtoll(arg, &endofnumber, 10);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               switch (toupper(*endofnumber)) {
+               case '\0':
+                       scale = 1;
+                       break;
+               case 'K':
+                       scale = 1<<10;
+                       break;
+               case 'M':
+                       scale = 1<<20;
+                       break;
+               case 'G':
+                       scale = 1<<30;
+                       break;
+               default:
+                       fatal("%.200s line %d: Invalid RekeyLimit suffix",
+                           filename, linenum);
+               }
+               val64 *= scale;
+               /* detect integer wrap and too-large limits */
+               if ((val64 / scale) != orig || val64 > UINT_MAX)
+                       fatal("%.200s line %d: RekeyLimit too large",
+                           filename, linenum);
+               if (val64 < 16)
+                       fatal("%.200s line %d: RekeyLimit too small",
+                           filename, linenum);
+               if (*activep && options->rekey_limit == -1)
+                       options->rekey_limit = (u_int32_t)val64;
+               break;
+
+       case oIdentityFile:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (*activep) {
+                       intptr = &options->num_identity_files;
+                       if (*intptr >= SSH_MAX_IDENTITY_FILES)
+                               fatal("%.200s line %d: Too many identity files specified (max %d).",
+                                   filename, linenum, SSH_MAX_IDENTITY_FILES);
+                       charptr = &options->identity_files[*intptr];
+                       *charptr = xstrdup(arg);
+                       *intptr = *intptr + 1;
+               }
+               break;
+
+       case oXAuthLocation:
+               charptr=&options->xauth_location;
+               goto parse_string;
+
+       case oUser:
+               charptr = &options->user;
+parse_string:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case oGlobalKnownHostsFile:
+               cpptr = (char **)&options->system_hostfiles;
+               uintptr = &options->num_system_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+parse_char_array:
+               if (*activep && *uintptr == 0) {
+                       while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                               if ((*uintptr) >= max_entries)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               cpptr[(*uintptr)++] = xstrdup(arg);
+                       }
+               }
+               return 0;
+
+       case oUserKnownHostsFile:
+               cpptr = (char **)&options->user_hostfiles;
+               uintptr = &options->num_user_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+               goto parse_char_array;
+
+       case oHostName:
+               charptr = &options->hostname;
+               goto parse_string;
+
+       case oHostKeyAlias:
+               charptr = &options->host_key_alias;
+               goto parse_string;
+
+       case oPreferredAuthentications:
+               charptr = &options->preferred_authentications;
+               goto parse_string;
+
+       case oBindAddress:
+               charptr = &options->bind_address;
+               goto parse_string;
+
+       case oPKCS11Provider:
+               charptr = &options->pkcs11_provider;
+               goto parse_string;
+
+       case oProxyCommand:
+               charptr = &options->proxy_command;
+parse_command:
+               if (s == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               len = strspn(s, WHITESPACE "=");
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(s + len);
+               return 0;
+
+       case oPort:
+               intptr = &options->port;
+parse_int:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+
+               /* Octal, decimal, or hex format? */
+               value = strtol(arg, &endofnumber, 0);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oConnectionAttempts:
+               intptr = &options->connection_attempts;
+               goto parse_int;
+
+       case oCipher:
+               intptr = &options->cipher;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = cipher_number(arg);
+               if (value == -1)
+                       fatal("%.200s line %d: Bad cipher '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCiphers:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case oMacs:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case oKexAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case oHostKeyAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!key_names_valid2(arg))
+                       fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->hostkeyalgorithms == NULL)
+                       options->hostkeyalgorithms = xstrdup(arg);
+               break;
+
+       case oProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%.200s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case oLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&s);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case oLocalForward:
+       case oRemoteForward:
+       case oDynamicForward:
+               arg = strdelim(&s);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%.200s line %d: Missing port argument.",
+                           filename, linenum);
+
+               if (opcode == oLocalForward ||
+                   opcode == oRemoteForward) {
+                       arg2 = strdelim(&s);
+                       if (arg2 == NULL || *arg2 == '\0')
+                               fatal("%.200s line %d: Missing target argument.",
+                                   filename, linenum);
+
+                       /* construct a string for parse_forward */
+                       snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
+               } else if (opcode == oDynamicForward) {
+                       strlcpy(fwdarg, arg, sizeof(fwdarg));
+               }
+
+               if (parse_forward(&fwd, fwdarg,
+                   opcode == oDynamicForward ? 1 : 0,
+                   opcode == oRemoteForward ? 1 : 0) == 0)
+                       fatal("%.200s line %d: Bad forwarding specification.",
+                           filename, linenum);
+
+               if (*activep) {
+                       if (opcode == oLocalForward ||
+                           opcode == oDynamicForward)
+                               add_local_forward(options, &fwd);
+                       else if (opcode == oRemoteForward)
+                               add_remote_forward(options, &fwd);
+               }
+               break;
+
+       case oClearAllForwardings:
+               intptr = &options->clear_forwardings;
+               goto parse_flag;
+
+       case oHost:
+               *activep = 0;
+               arg2 = NULL;
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       negated = *arg == '!';
+                       if (negated)
+                               arg++;
+                       if (match_pattern(host, arg)) {
+                               if (negated) {
+                                       debug("%.200s line %d: Skipping Host "
+                                           "block because of negated match "
+                                           "for %.100s", filename, linenum,
+                                           arg);
+                                       *activep = 0;
+                                       break;
+                               }
+                               if (!*activep)
+                                       arg2 = arg; /* logged below */
+                               *activep = 1;
+                       }
+               }
+               if (*activep)
+                       debug("%.200s line %d: Applying options for %.100s",
+                           filename, linenum, arg2);
+               /* Avoid garbage check below, as strdelim is done. */
+               return 0;
+
+       case oEscapeChar:
+               intptr = &options->escape_char;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] == '^' && arg[2] == 0 &&
+                   (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
+                       value = (u_char) arg[1] & 31;
+               else if (strlen(arg) == 1)
+                       value = (u_char) arg[0];
+               else if (strcmp(arg, "none") == 0)
+                       value = SSH_ESCAPECHAR_NONE;
+               else {
+                       fatal("%.200s line %d: Bad escape character.",
+                           filename, linenum);
+                       /* NOTREACHED */
+                       value = 0;      /* Avoid compiler warning. */
+               }
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oAddressFamily:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing address family.",
+                           filename, linenum);
+               intptr = &options->address_family;
+               if (strcasecmp(arg, "inet") == 0)
+                       value = AF_INET;
+               else if (strcasecmp(arg, "inet6") == 0)
+                       value = AF_INET6;
+               else if (strcasecmp(arg, "any") == 0)
+                       value = AF_UNSPEC;
+               else
+                       fatal("Unsupported AddressFamily \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oEnableSSHKeysign:
+               intptr = &options->enable_ssh_keysign;
+               goto parse_flag;
+
+       case oIdentitiesOnly:
+               intptr = &options->identities_only;
+               goto parse_flag;
+
+       case oServerAliveInterval:
+               intptr = &options->server_alive_interval;
+               goto parse_time;
+
+       case oServerAliveCountMax:
+               intptr = &options->server_alive_count_max;
+               goto parse_int;
+
+       case oSendEnv:
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (!*activep)
+                               continue;
+                       if (options->num_send_env >= MAX_SEND_ENV)
+                               fatal("%s line %d: too many send env.",
+                                   filename, linenum);
+                       options->send_env[options->num_send_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case oControlPath:
+               charptr = &options->control_path;
+               goto parse_string;
+
+       case oControlMaster:
+               intptr = &options->control_master;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlMaster argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = SSHCTL_MASTER_YES;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = SSHCTL_MASTER_NO;
+               else if (strcmp(arg, "auto") == 0)
+                       value = SSHCTL_MASTER_AUTO;
+               else if (strcmp(arg, "ask") == 0)
+                       value = SSHCTL_MASTER_ASK;
+               else if (strcmp(arg, "autoask") == 0)
+                       value = SSHCTL_MASTER_AUTO_ASK;
+               else
+                       fatal("%.200s line %d: Bad ControlMaster argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oControlPersist:
+               /* no/false/yes/true, or a time spec */
+               intptr = &options->control_persist;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlPersist"
+                           " argument.", filename, linenum);
+               value = 0;
+               value2 = 0;     /* timeout */
+               if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if ((value2 = convtime(arg)) >= 0)
+                       value = 1;
+               else
+                       fatal("%.200s line %d: Bad ControlPersist argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1) {
+                       *intptr = value;
+                       options->control_persist_timeout = value2;
+               }
+               break;
+
+       case oHashKnownHosts:
+               intptr = &options->hash_known_hosts;
+               goto parse_flag;
+
+       case oTunnel:
+               intptr = &options->tun_open;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcasecmp(arg, "ethernet") == 0)
+                       value = SSH_TUNMODE_ETHERNET;
+               else if (strcasecmp(arg, "point-to-point") == 0)
+                       value = SSH_TUNMODE_POINTOPOINT;
+               else if (strcasecmp(arg, "yes") == 0)
+                       value = SSH_TUNMODE_DEFAULT;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = SSH_TUNMODE_NO;
+               else
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*activep)
+                       *intptr = value;
+               break;
+
+       case oTunnelDevice:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = a2tun(arg, &value2);
+               if (value == SSH_TUNID_ERR)
+                       fatal("%.200s line %d: Bad tun device.", filename, linenum);
+               if (*activep) {
+                       options->tun_local = value;
+                       options->tun_remote = value2;
+               }
+               break;
+
+       case oLocalCommand:
+               charptr = &options->local_command;
+               goto parse_command;
+
+       case oPermitLocalCommand:
+               intptr = &options->permit_local_command;
+               goto parse_flag;
+
+       case oVisualHostKey:
+               intptr = &options->visual_host_key;
+               goto parse_flag;
+
+       case oIPQoS:
+               arg = strdelim(&s);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&s);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case oUseRoaming:
+               intptr = &options->use_roaming;
+               goto parse_flag;
+
+       case oRequestTTY:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               intptr = &options->request_tty;
+               if (strcasecmp(arg, "yes") == 0)
+                       value = REQUEST_TTY_YES;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = REQUEST_TTY_NO;
+               else if (strcasecmp(arg, "force") == 0)
+                       value = REQUEST_TTY_FORCE;
+               else if (strcasecmp(arg, "auto") == 0)
+                       value = REQUEST_TTY_AUTO;
+               else
+                       fatal("Unsupported RequestTTY \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oDeprecated:
+               debug("%s line %d: Deprecated option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       case oUnsupported:
+               error("%s line %d: Unsupported option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       default:
+               fatal("process_config_line: Unimplemented opcode %d", opcode);
+       }
+
+       /* Check that there is no garbage at end of line. */
+       if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+               fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       }
+       return 0;
+}
+
+
+/*
+ * Reads the config file and modifies the options accordingly.  Options
+ * should already be initialized before this call.  This never returns if
+ * there is an error.  If the file does not exist, this returns 0.
+ */
+
+int
+read_config_file(const char *filename, const char *host, Options *options,
+    int checkperm)
+{
+       FILE *f;
+       char line[1024];
+       int active, linenum;
+       int bad_options = 0;
+
+       if ((f = fopen(filename, "r")) == NULL)
+               return 0;
+
+       if (checkperm) {
+               struct stat sb;
+
+               if (fstat(fileno(f), &sb) == -1)
+                       fatal("fstat %s: %s", filename, strerror(errno));
+               if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
+                   (sb.st_mode & 022) != 0))
+                       fatal("Bad owner or permissions on %s", filename);
+       }
+
+       debug("Reading configuration data %.200s", filename);
+
+       /*
+        * Mark that we are now processing the options.  This flag is turned
+        * on/off by Host specifications.
+        */
+       active = 1;
+       linenum = 0;
+       while (fgets(line, sizeof(line), f)) {
+               /* Update line number counter. */
+               linenum++;
+               if (process_config_line(options, host, line, filename, linenum, &active) != 0)
+                       bad_options++;
+       }
+       fclose(f);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+       return 1;
+}
+
+/*
+ * Initializes options to special values that indicate that they have not yet
+ * been set.  Read_config_file will only set options with this value. Options
+ * are processed in the following order: command line, user config file,
+ * system config file.  Last, fill_default_options is called.
+ */
+
+void
+initialize_options(Options * options)
+{
+       memset(options, 'X', sizeof(*options));
+       options->forward_agent = -1;
+       options->forward_x11 = -1;
+       options->forward_x11_trusted = -1;
+       options->forward_x11_timeout = -1;
+       options->exit_on_forward_failure = -1;
+       options->xauth_location = NULL;
+       options->gateway_ports = -1;
+       options->use_privileged_port = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->gss_authentication = -1;
+       options->gss_keyex = -1;
+       options->gss_deleg_creds = -1;
+       options->gss_trust_dns = -1;
+       options->gss_renewal_rekey = -1;
+       options->gss_client_identity = NULL;
+       options->gss_server_identity = NULL;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->kbd_interactive_devices = NULL;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->use_blacklisted_keys = -1;
+       options->batch_mode = -1;
+       options->check_host_ip = -1;
+       options->strict_host_key_checking = -1;
+       options->compression = -1;
+       options->tcp_keep_alive = -1;
+       options->compression_level = -1;
+       options->port = -1;
+       options->address_family = -1;
+       options->connection_attempts = -1;
+       options->connection_timeout = -1;
+       options->number_of_password_prompts = -1;
+       options->cipher = -1;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->hostkeyalgorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->num_identity_files = 0;
+       options->hostname = NULL;
+       options->host_key_alias = NULL;
+       options->proxy_command = NULL;
+       options->user = NULL;
+       options->escape_char = -1;
+       options->num_system_hostfiles = 0;
+       options->num_user_hostfiles = 0;
+       options->local_forwards = NULL;
+       options->num_local_forwards = 0;
+       options->remote_forwards = NULL;
+       options->num_remote_forwards = 0;
+       options->clear_forwardings = -1;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->preferred_authentications = NULL;
+       options->bind_address = NULL;
+       options->pkcs11_provider = NULL;
+       options->enable_ssh_keysign = - 1;
+       options->no_host_authentication_for_localhost = - 1;
+       options->identities_only = - 1;
+       options->rekey_limit = - 1;
+       options->verify_host_key_dns = -1;
+       options->server_alive_interval = -1;
+       options->server_alive_count_max = -1;
+       options->num_send_env = 0;
+       options->control_path = NULL;
+       options->control_master = -1;
+       options->control_persist = -1;
+       options->control_persist_timeout = 0;
+       options->hash_known_hosts = -1;
+       options->tun_open = -1;
+       options->tun_local = -1;
+       options->tun_remote = -1;
+       options->local_command = NULL;
+       options->permit_local_command = -1;
+       options->use_roaming = -1;
+       options->visual_host_key = -1;
+       options->zero_knowledge_password_authentication = -1;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+       options->request_tty = -1;
+}
+
+/*
+ * Called after processing other sources of option data, this fills those
+ * options for which no value has been specified with their default values.
+ */
+
+void
+fill_default_options(Options * options)
+{
+       int len;
+
+       if (options->forward_agent == -1)
+               options->forward_agent = 0;
+       if (options->forward_x11 == -1)
+               options->forward_x11 = 0;
+       if (options->forward_x11_trusted == -1)
+               options->forward_x11_trusted = 0;
+       if (options->forward_x11_timeout == -1)
+               options->forward_x11_timeout = 1200;
+       if (options->exit_on_forward_failure == -1)
+               options->exit_on_forward_failure = 0;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->use_privileged_port == -1)
+               options->use_privileged_port = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
+       if (options->gss_deleg_creds == -1)
+               options->gss_deleg_creds = 0;
+       if (options->gss_trust_dns == -1)
+               options->gss_trust_dns = 0;
+       if (options->gss_renewal_rekey == -1)
+               options->gss_renewal_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 1;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->use_blacklisted_keys == -1)
+               options->use_blacklisted_keys = 0;
+       if (options->batch_mode == -1)
+               options->batch_mode = 0;
+       if (options->check_host_ip == -1)
+               options->check_host_ip = 1;
+       if (options->strict_host_key_checking == -1)
+               options->strict_host_key_checking = 2;  /* 2 is default */
+       if (options->compression == -1)
+               options->compression = 0;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->compression_level == -1)
+               options->compression_level = 6;
+       if (options->port == -1)
+               options->port = 0;      /* Filled in ssh_connect. */
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (options->connection_attempts == -1)
+               options->connection_attempts = 1;
+       if (options->number_of_password_prompts == -1)
+               options->number_of_password_prompts = 3;
+       /* Selected in ssh_login(). */
+       if (options->cipher == -1)
+               options->cipher = SSH_CIPHER_NOT_SET;
+       /* options->ciphers, default set in myproposals.h */
+       /* options->macs, default set in myproposals.h */
+       /* options->kex_algorithms, default set in myproposals.h */
+       /* options->hostkeyalgorithms, default set in myproposals.h */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_identity_files == 0) {
+               if (options->protocol & SSH_PROTO_1) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
+               }
+               if (options->protocol & SSH_PROTO_2) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
+
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
+#ifdef OPENSSL_HAS_ECC
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
+#endif
+               }
+       }
+       if (options->escape_char == -1)
+               options->escape_char = '~';
+       if (options->num_system_hostfiles == 0) {
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
+       }
+       if (options->num_user_hostfiles == 0) {
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE);
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE2);
+       }
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->clear_forwardings == 1)
+               clear_forwardings(options);
+       if (options->no_host_authentication_for_localhost == - 1)
+               options->no_host_authentication_for_localhost = 0;
+       if (options->identities_only == -1)
+               options->identities_only = 0;
+       if (options->enable_ssh_keysign == -1)
+               options->enable_ssh_keysign = 0;
+       if (options->rekey_limit == -1)
+               options->rekey_limit = 0;
+       if (options->verify_host_key_dns == -1)
+               options->verify_host_key_dns = 0;
+       if (options->server_alive_interval == -1)
+               options->server_alive_interval = 0;
+       if (options->server_alive_count_max == -1)
+               options->server_alive_count_max = 3;
+       if (options->control_master == -1)
+               options->control_master = 0;
+       if (options->control_persist == -1) {
+               options->control_persist = 0;
+               options->control_persist_timeout = 0;
+       }
+       if (options->hash_known_hosts == -1)
+               options->hash_known_hosts = 0;
+       if (options->tun_open == -1)
+               options->tun_open = SSH_TUNMODE_NO;
+       if (options->tun_local == -1)
+               options->tun_local = SSH_TUNID_ANY;
+       if (options->tun_remote == -1)
+               options->tun_remote = SSH_TUNID_ANY;
+       if (options->permit_local_command == -1)
+               options->permit_local_command = 0;
+       if (options->use_roaming == -1)
+               options->use_roaming = 1;
+       if (options->visual_host_key == -1)
+               options->visual_host_key = 0;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+       if (options->request_tty == -1)
+               options->request_tty = REQUEST_TTY_AUTO;
+       /* options->local_command should not be set by default */
+       /* options->proxy_command should not be set by default */
+       /* options->user will be set in the main program if appropriate */
+       /* options->hostname will be set in the main program if appropriate */
+       /* options->host_key_alias should not be set by default */
+       /* options->preferred_authentications will be set in ssh */
+}
+
+/*
+ * parse_forward
+ * parses a string containing a port forwarding specification of the form:
+ *   dynamicfwd == 0
+ *     [listenhost:]listenport:connecthost:connectport
+ *   dynamicfwd == 1
+ *     [listenhost:]listenport
+ * returns number of arguments parsed or zero on error
+ */
+int
+parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
+{
+       int i;
+       char *p, *cp, *fwdarg[4];
+
+       memset(fwd, '\0', sizeof(*fwd));
+
+       cp = p = xstrdup(fwdspec);
+
+       /* skip leading spaces */
+       while (isspace(*cp))
+               cp++;
+
+       for (i = 0; i < 4; ++i)
+               if ((fwdarg[i] = hpdelim(&cp)) == NULL)
+                       break;
+
+       /* Check for trailing garbage */
+       if (cp != NULL)
+               i = 0;  /* failure */
+
+       switch (i) {
+       case 1:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 2:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 3:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
+               fwd->connect_port = a2port(fwdarg[2]);
+               break;
+
+       case 4:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
+               fwd->connect_port = a2port(fwdarg[3]);
+               break;
+       default:
+               i = 0; /* failure */
+       }
+
+       xfree(p);
+
+       if (dynamicfwd) {
+               if (!(i == 1 || i == 2))
+                       goto fail_free;
+       } else {
+               if (!(i == 3 || i == 4))
+                       goto fail_free;
+               if (fwd->connect_port <= 0)
+                       goto fail_free;
+       }
+
+       if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
+               goto fail_free;
+
+       if (fwd->connect_host != NULL &&
+           strlen(fwd->connect_host) >= NI_MAXHOST)
+               goto fail_free;
+       if (fwd->listen_host != NULL &&
+           strlen(fwd->listen_host) >= NI_MAXHOST)
+               goto fail_free;
+
+
+       return (i);
+
+ fail_free:
+       if (fwd->connect_host != NULL) {
+               xfree(fwd->connect_host);
+               fwd->connect_host = NULL;
+       }
+       if (fwd->listen_host != NULL) {
+               xfree(fwd->listen_host);
+               fwd->listen_host = NULL;
+       }
+       return (0);
+}
diff --git a/.pc/keepalive-extensions.patch/ssh_config.5 b/.pc/keepalive-extensions.patch/ssh_config.5
new file mode 100644 (file)
index 0000000..4f2db40
--- /dev/null
@@ -0,0 +1,1346 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Nm ~/.ssh/config
+.Nm /etc/ssh/ssh_config
+.Sh DESCRIPTION
+.Xr ssh 1
+obtains configuration data from the following sources in
+the following order:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+command-line options
+.It
+user's configuration file
+.Pq Pa ~/.ssh/config
+.It
+system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+.El
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections separated by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp ,
+and
+.Nm sftp
+.Fl o
+option.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+If more than one pattern is provided, they should be separated by whitespace.
+A single
+.Ql *
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e. the name is not converted to
+a canonicalized host name before matching).
+.Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm AddressFamily
+Specifies which address family to use when connecting.
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Use the specified address on the local machine as the source address of
+the connection.
+Only useful on systems with more than one address.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge-response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Xr ssh 1
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote, and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared.
+This option is primarily useful when used from the
+.Xr ssh 1
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout (in seconds) used when connecting to the
+SSH server, instead of using the default system TCP timeout.
+This value is used only when the target is down or really unreachable,
+not when it refuses the connection.
+.It Cm ControlMaster
+Enables the sharing of multiple sessions over a single network connection.
+When set to
+.Dq yes ,
+.Xr ssh 1
+will listen for connections on a control socket specified using the
+.Cm ControlPath
+argument.
+Additional sessions can connect to this socket using the same
+.Cm ControlPath
+with
+.Cm ControlMaster
+set to
+.Dq no
+(the default).
+These sessions will try to reuse the master instance's network connection
+rather than initiating new ones, but will fall back to connecting normally
+if the control socket does not exist, or is not listening.
+.Pp
+Setting this to
+.Dq ask
+will cause ssh
+to listen for control connections, but require confirmation using the
+.Ev SSH_ASKPASS
+program before they are accepted (see
+.Xr ssh-add 1
+for details).
+If the
+.Cm ControlPath
+cannot be opened,
+ssh will continue without connecting to a master instance.
+.Pp
+X11 and
+.Xr ssh-agent 1
+forwarding is supported over these multiplexed connections, however the
+display and agent forwarded will be the one belonging to the master
+connection i.e. it is not possible to forward multiple displays or agents.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
+.It Cm ControlPath
+Specify the path to the control socket used for connection sharing as described
+in the
+.Cm ControlMaster
+section above or the string
+.Dq none
+to disable connection sharing.
+In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
+.Ql %l
+will be substituted by the local host name (including any domain name),
+.Ql %h
+will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
+.Ql %p
+the port,
+.Ql %r
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+at least %h, %p, and %r.
+This ensures that shared connections are uniquely identified.
+.It Cm ControlPersist
+When used in conjunction with
+.Cm ControlMaster ,
+specifies that the master connection should remain open
+in the background (waiting for future client connections)
+after the initial client connection has been closed.
+If set to
+.Dq no ,
+then the master connection will not be placed into the background,
+and will close as soon as the initial client connection is closed.
+If set to
+.Dq yes ,
+then the master connection will remain in the background indefinitely
+(until killed or closed via a mechanism such as the
+.Xr ssh 1
+.Dq Fl O No exit
+option).
+If set to a time in seconds, or a time in any of the formats documented in
+.Xr sshd_config 5 ,
+then the backgrounded master connection will automatically terminate
+after it has remained idle (with no client connections) for the
+specified time.
+.It Cm DynamicForward
+Specifies that a TCP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+.Pp
+The argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port .
+.Sm on
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.Pp
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Xr ssh 1
+will act as a SOCKS server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm EnableSSHKeysign
+Setting this option to
+.Dq yes
+in the global client configuration file
+.Pa /etc/ssh/ssh_config
+enables the use of the helper program
+.Xr ssh-keysign 8
+during
+.Cm HostbasedAuthentication .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option should be placed in the non-hostspecific section.
+See
+.Xr ssh-keysign 8
+for more information.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ExitOnForwardFailure
+Specifies whether
+.Xr ssh 1
+should terminate the connection if it cannot set up all requested
+dynamic, tunnel, local, and remote port forwardings.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's Unix-domain socket)
+can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X11 authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring
+if the
+.Cm ForwardX11Trusted
+option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
+.It Cm ForwardX11Trusted
+If this option is set to
+.Dq yes ,
+remote X11 clients will have full access to the original X11 display.
+.Pp
+If this option is set to
+.Dq no ,
+remote X11 clients will be considered untrusted and prevented
+from stealing or tampering with data belonging to trusted X11
+clients.
+Furthermore, the
+.Xr xauth 1
+token used for the session will be set to expire after 20 minutes.
+Remote clients will be refused access after this time.
+.Pp
+The default is
+.Dq no .
+.Pp
+See the X11 SECURITY extension specification for full details on
+the restrictions imposed on untrusted clients.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Xr ssh 1
+binds local port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
+.It Cm GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when 
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
+.It Cm GSSAPIDelegateCredentials
+Forward (delegate) credentials to the server.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI.
+.It Cm HashKnownHosts
+Indicates that
+.Xr ssh 1
+should hash host names and addresses when they are added to
+.Pa ~/.ssh/known_hosts .
+These hashed names may be used normally by
+.Xr ssh 1
+and
+.Xr sshd 8 ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+The default is
+.Dq no .
+Note that existing names and addresses in known hosts files
+will not be converted automatically,
+but may be manually hashed using
+.Xr ssh-keygen 1 .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
+ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-rsa,ssh-dss
+.Ed
+.Pp
+If hostkeys are known for the destination host then this default is modified
+to prefer their algorithms.
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling SSH connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+If the hostname contains the character sequence
+.Ql %h ,
+then this will be replaced with the host name specified on the command line
+(this is useful for manipulating unqualified names).
+The default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentitiesOnly
+Specifies that
+.Xr ssh 1
+should only use the authentication identity files configured in the
+.Nm
+files,
+even if
+.Xr ssh-agent 1
+offers more identities.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option is intended for situations where ssh-agent
+offers many different identities.
+The default is
+.Dq no .
+.It Cm IdentityFile
+Specifies a file from which the user's DSA, ECDSA or DSA authentication
+identity is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+.Xr ssh 1
+will try to load certificate information from the filename obtained by
+appending
+.Pa -cert.pub
+to the path of a specified
+.Cm IdentityFile .
+.Pp
+The file name may use the tilde
+syntax to refer to a user's home directory or one of the following
+escape characters:
+.Ql %d
+(local user's home directory),
+.Ql %u
+(local user name),
+.Ql %l
+(local host name),
+.Ql %h
+(remote host name) or
+.Ql %r
+(remote user name).
+.Pp
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KbdInteractiveAuthentication
+Specifies whether to use keyboard-interactive authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm KbdInteractiveDevices
+Specifies the list of methods to use in keyboard-interactive authentication.
+Multiple method names must be comma-separated.
+The default is to use the server specified list.
+The methods available vary depending on what the server supports.
+For an OpenSSH server,
+it may be zero or more of:
+.Dq bsdauth ,
+.Dq pam ,
+and
+.Dq skey .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
+diffie-hellman-group-exchange-sha256,
+diffie-hellman-group-exchange-sha1,
+diffie-hellman-group14-sha1,
+diffie-hellman-group1-sha1
+.Ed
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+The following escape character substitutions will be performed:
+.Ql %d
+(local user's home directory),
+.Ql %h
+(remote host name),
+.Ql %l
+(local host name),
+.Ql %n
+(host name as provided on the command line),
+.Ql %p
+(remote port),
+.Ql %r
+(remote user name) or
+.Ql %u
+(local user name).
+.Pp
+The command is run synchronously and does not have access to the
+session of the
+.Xr ssh 1
+that spawned it.
+It should not be used for interactive commands.
+.Pp
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
+.It Cm LocalForward
+Specifies that a TCP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional forwardings can be
+given on the command line.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr ssh 1 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+The default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic !\& Ns Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm PKCS11Provider
+Specifies which PKCS#11 provider to use.
+The argument to this keyword is the PKCS#11 shared library
+.Xr ssh 1
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Cm Port
+Specifies the port number to connect on the remote host.
+The default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods.
+This allows a client to prefer one method (e.g.\&
+.Cm keyboard-interactive )
+over another method (e.g.\&
+.Cm password ) .
+The default is:
+.Bd -literal -offset indent
+gssapi-with-mic,hostbased,publickey,
+keyboard-interactive,password
+.Ed
+.It Cm Protocol
+Specifies the protocol versions
+.Xr ssh 1
+should support in order of preference.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+When this option is set to
+.Dq 2,1
+.Nm ssh
+will try version 2 and fall back to version 1
+if version 2 is not available.
+The default is
+.Sq 2 .
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+the user's shell.
+In the command string, any occurrence of
+.Ql %h
+will be substituted by the host name to
+connect,
+.Ql %p
+by the port, and
+.Ql %r
+by the remote user name.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Setting the command to
+.Dq none
+disables this option entirely.
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+This directive is useful in conjunction with
+.Xr nc 1
+and its proxy support.
+For example, the following directive would connect via an HTTP proxy at
+192.0.2.0:
+.Bd -literal -offset 3n
+ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
+.Ed
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RekeyLimit
+Specifies the maximum amount of data that may be transmitted before the
+session key is renegotiated.
+The argument is the number of bytes, with an optional suffix of
+.Sq K ,
+.Sq M ,
+or
+.Sq G
+to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
+The default is between
+.Sq 1G
+and
+.Sq 4G ,
+depending on the cipher.
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+.Pp
+If the
+.Ar bind_address
+is not specified, the default is to only bind to loopback addresses.
+If the
+.Ar bind_address
+is
+.Ql *
+or an empty string, then the forwarding is requested to listen on all
+interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Xr ssh 1
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SendEnv
+Specifies what variables from the local
+.Xr environ 7
+should be sent to the server.
+Note that environment passing is only supported for protocol 2.
+The server must also support it, and the server must be configured to
+accept these environment variables.
+Refer to
+.Cm AcceptEnv
+in
+.Xr sshd_config 5
+for how to configure the server.
+Variables are specified by name, which may contain wildcard characters.
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm SendEnv
+directives.
+The default is not to send any environment variables.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm ServerAliveCountMax
+Sets the number of server alive messages (see below) which may be
+sent without
+.Xr ssh 1
+receiving any messages back from the server.
+If this threshold is reached while server alive messages are being sent,
+ssh will disconnect from the server, terminating the session.
+It is important to note that the use of server alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The server alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The server alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If, for example,
+.Cm ServerAliveInterval
+(see below) is set to 15 and
+.Cm ServerAliveCountMax
+is left at the default, if the server becomes unresponsive,
+ssh will disconnect after approximately 45 seconds.
+This option applies to protocol version 2 only; in protocol version
+1 there is no mechanism to request a response from the server to the
+server alive messages, so disconnection is the responsibility of the TCP
+stack.
+.It Cm ServerAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the server,
+.Xr ssh 1
+will send a message through the encrypted
+channel to request a response from the server.
+The default
+is 0, indicating that these messages will not be sent to the server.
+This option applies to protocol version 2 only.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will never automatically add host keys to the
+.Pa ~/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+though it can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained or when connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+ssh will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+ssh will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm Tunnel
+Request
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2),
+or
+.Dq no .
+Specifying
+.Dq yes
+requests the default tunnel mode, which is
+.Dq point-to-point .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Specifies the
+.Xr tun 4
+devices to open on the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The argument must be
+.Sm off
+.Ar local_tun Op : Ar remote_tun .
+.Sm on
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+The default is
+.Dq any:any .
+.It Cm UseBlacklistedKeys
+Specifies whether
+.Xr ssh 1
+should use keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 )
+for authentication.
+If
+.Dq yes ,
+then attempts to use compromised keys for authentication will be logged but
+accepted.
+It is strongly recommended that this be used only to install new authorized
+keys on the remote system, and even then only with the utmost care.
+If
+.Dq no ,
+then attempts to use compromised keys for authentication will be prevented.
+The default is
+.Dq no .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+If set to
+.Dq yes ,
+.Xr ssh 1
+must be setuid root.
+Note that this option must be set to
+.Dq yes
+for
+.Cm RhostsRSAAuthentication
+with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
+.It Cm VerifyHostKeyDNS
+Specifies whether to verify the remote key using DNS and SSHFP resource
+records.
+If this option is set to
+.Dq yes ,
+the client will implicitly trust keys that match a secure fingerprint
+from DNS.
+Insecure fingerprints will be handled as if this option was set to
+.Dq ask .
+If this option is set to
+.Dq ask ,
+information on fingerprint match will be displayed, but the user will still
+need to confirm new host keys according to the
+.Cm StrictHostKeyChecking
+option.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.Pp
+See also
+.Sx VERIFYING HOST KEYS
+in
+.Xr ssh 1 .
+.It Cm VisualHostKey
+If this flag is set to
+.Dq yes ,
+an ASCII art representation of the remote host key fingerprint is
+printed in addition to the hex fingerprint string at login and
+for unknown host keys.
+If this flag is set to
+.Dq no ,
+no fingerprint strings are printed at login and
+only the hex fingerprint string will be printed for unknown host keys.
+The default is
+.Dq no .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh PATTERNS
+A
+.Em pattern
+consists of zero or more non-whitespace characters,
+.Sq *
+(a wildcard that matches zero or more characters),
+or
+.Sq ?\&
+(a wildcard that matches exactly one character).
+For example, to specify a set of declarations for any host in the
+.Dq .co.uk
+set of domains,
+the following pattern could be used:
+.Pp
+.Dl Host *.co.uk
+.Pp
+The following pattern
+would match any host in the 192.168.0.[0-9] network range:
+.Pp
+.Dl Host 192.168.0.?
+.Pp
+A
+.Em pattern-list
+is a comma-separated list of patterns.
+Patterns within pattern-lists may be negated
+by preceding them with an exclamation mark
+.Pq Sq !\& .
+For example,
+to allow a key to be used from anywhere within an organisation
+except from the
+.Dq dialup
+pool,
+the following entry (in authorized_keys) could be used:
+.Pp
+.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the SSH client.
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh SEE ALSO
+.Xr ssh 1
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/keepalive-extensions.patch/sshd_config.5 b/.pc/keepalive-extensions.patch/sshd_config.5
new file mode 100644 (file)
index 0000000..3979cd4
--- /dev/null
@@ -0,0 +1,1257 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd_config.5,v 1.135 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD_CONFIG 5
+.Os
+.Sh NAME
+.Nm sshd_config
+.Nd OpenSSH SSH daemon configuration file
+.Sh SYNOPSIS
+.Nm /etc/ssh/sshd_config
+.Sh DESCRIPTION
+.Xr sshd 8
+reads configuration data from
+.Pa /etc/ssh/sshd_config
+(or the file specified with
+.Fl f
+on the command line).
+The file contains keyword-argument pairs, one per line.
+Lines starting with
+.Ql #
+and empty lines are interpreted as comments.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm AcceptEnv
+Specifies what environment variables sent by the client will be copied into
+the session's
+.Xr environ 7 .
+See
+.Cm SendEnv
+in
+.Xr ssh_config 5
+for how to configure the client.
+Note that environment passing is only supported for protocol 2.
+Variables are specified by name, which may contain the wildcard characters
+.Ql *
+and
+.Ql \&? .
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm AcceptEnv
+directives.
+Be warned that some environment variables could be used to bypass restricted
+user environments.
+For this reason, care should be taken in the use of this directive.
+The default is not to accept any environment variables.
+.It Cm AddressFamily
+Specifies which address family should be used by
+.Xr sshd 8 .
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+The default is
+.Dq any .
+.It Cm AllowAgentForwarding
+Specifies whether
+.Xr ssh-agent 1
+forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling agent forwarding does not improve security
+unless users are also denied shell access, as they can always install
+their own forwarders.
+.It Cm AllowGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+If specified, login is allowed only for users whose primary
+group or supplementary group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling TCP forwarding does not improve security unless
+users are also denied shell access, as they can always install their
+own forwarders.
+.It Cm AllowUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+If specified, login is allowed only for user names that
+match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AuthorizedKeysFile
+Specifies the file that contains the public keys that can be used
+for user authentication.
+The format is described in the
+.Sx AUTHORIZED_KEYS FILE FORMAT
+section of
+.Xr sshd 8 .
+.Cm AuthorizedKeysFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedKeysFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+Multiple files may be listed, separated by whitespace.
+The default is
+.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
+.It Cm AuthorizedPrincipalsFile
+Specifies a file that lists principal names that are accepted for
+certificate authentication.
+When using certificates signed by a key listed in
+.Cm TrustedUserCAKeys ,
+this file lists names, one of which must appear in the certificate for it
+to be accepted for authentication.
+Names are listed one per line preceded by key options (as described
+in
+.Sx AUTHORIZED_KEYS FILE FORMAT
+in
+.Xr sshd 8 ) .
+Empty lines and comments starting with
+.Ql #
+are ignored.
+.Pp
+.Cm AuthorizedPrincipalsFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedPrincipalsFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+.Pp
+The default is not to use a principals file \(en in this case, the username
+of the user must appear in a certificate's principals list for it to be
+accepted.
+Note that
+.Cm AuthorizedPrincipalsFile
+is only used when authentication proceeds using a CA listed in
+.Cm TrustedUserCAKeys
+and is not consulted for certification authorities trusted via
+.Pa ~/.ssh/authorized_keys ,
+though the
+.Cm principals=
+key option offers a similar facility (see
+.Xr sshd 8
+for details).
+.It Cm Banner
+The contents of the specified file are sent to the remote user before
+authentication is allowed.
+If the argument is
+.Dq none
+then no banner is displayed.
+This option is only available for protocol version 2.
+By default, no banner is displayed.
+.It Cm ChallengeResponseAuthentication
+Specifies whether challenge-response authentication is allowed (e.g. via
+PAM or though authentication styles supported in
+.Xr login.conf 5 )
+The default is
+.Dq yes .
+.It Cm ChrootDirectory
+Specifies the pathname of a directory to
+.Xr chroot 2
+to after authentication.
+All components of the pathname must be root-owned directories that are
+not writable by any other user or group.
+After the chroot,
+.Xr sshd 8
+changes the working directory to the user's home directory.
+.Pp
+The pathname may contain the following tokens that are expanded at runtime once
+the connecting user has been authenticated: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+.Pp
+The
+.Cm ChrootDirectory
+must contain the necessary files and directories to support the
+user's session.
+For an interactive session this requires at least a shell, typically
+.Xr sh 1 ,
+and basic
+.Pa /dev
+nodes such as
+.Xr null 4 ,
+.Xr zero 4 ,
+.Xr stdin 4 ,
+.Xr stdout 4 ,
+.Xr stderr 4 ,
+.Xr arandom 4
+and
+.Xr tty 4
+devices.
+For file transfer sessions using
+.Dq sftp ,
+no additional configuration of the environment is necessary if the
+in-process sftp server is used,
+though sessions which use logging do require
+.Pa /dev/log
+inside the chroot directory (see
+.Xr sftp-server 8
+for details).
+.Pp
+The default is not to
+.Xr chroot 2 .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClientAliveCountMax
+Sets the number of client alive messages (see below) which may be
+sent without
+.Xr sshd 8
+receiving any messages back from the client.
+If this threshold is reached while client alive messages are being sent,
+sshd will disconnect the client, terminating the session.
+It is important to note that the use of client alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The client alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The client alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If
+.Cm ClientAliveInterval
+(see below) is set to 15, and
+.Cm ClientAliveCountMax
+is left at the default, unresponsive SSH clients
+will be disconnected after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ClientAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the client,
+.Xr sshd 8
+will send a message through the encrypted
+channel to request a response from the client.
+The default
+is 0, indicating that these messages will not be sent to the client.
+This option applies to protocol version 2 only.
+.It Cm Compression
+Specifies whether compression is allowed, or delayed until
+the user has authenticated successfully.
+The argument must be
+.Dq yes ,
+.Dq delayed ,
+or
+.Dq no .
+The default is
+.Dq delayed .
+.It Cm DenyGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+Login is disallowed for users whose primary group or supplementary
+group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm DenyUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+Login is disallowed for user names that match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm ForceCommand
+Forces the execution of the command specified by
+.Cm ForceCommand ,
+ignoring any command supplied by the client and
+.Pa ~/.ssh/rc
+if present.
+The command is invoked by using the user's login shell with the -c option.
+This applies to shell, command, or subsystem execution.
+It is most useful inside a
+.Cm Match
+block.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Specifying a command of
+.Dq internal-sftp
+will force the use of an in-process sftp server that requires no support
+files when used with
+.Cm ChrootDirectory .
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to ports
+forwarded for the client.
+By default,
+.Xr sshd 8
+binds remote port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that sshd
+should allow remote port forwardings to bind to non-loopback addresses, thus
+allowing other hosts to connect.
+The argument may be
+.Dq no
+to force remote port forwardings to be available to the local host only,
+.Dq yes
+to force remote port forwardings to bind to the wildcard address, or
+.Dq clientspecified
+to allow the client to select the address to which the forwarding is bound.
+The default is
+.Dq no .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICleanupCredentials
+Specifies whether to automatically destroy the user's credentials cache
+on logout.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor 
+a client authenticates against. If
+.Dq yes
+then the client must authenticate against the
+.Pa host
+service on the current hostname. If 
+.Dq no
+then the client may authenticate against any service key stored in the 
+machine's default store. This facility is provided to assist with operation 
+on multi homed machines. 
+The default is
+.Dq yes .
+Note that this option applies only to protocol version 2 GSSAPI connections,
+and setting it to 
+.Dq no
+may only work with recent Kerberos GSSAPI libraries.
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
+.Dq no .
+.It Cm HostbasedAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful public key client host authentication is allowed
+(host-based authentication).
+This option is similar to
+.Cm RhostsRSAAuthentication
+and applies to protocol version 2 only.
+The default is
+.Dq no .
+.It Cm HostbasedUsesNameFromPacketOnly
+Specifies whether or not the server will attempt to perform a reverse
+name lookup when matching the name in the
+.Pa ~/.shosts ,
+.Pa ~/.rhosts ,
+and
+.Pa /etc/hosts.equiv
+files during
+.Cm HostbasedAuthentication .
+A setting of
+.Dq yes
+means that
+.Xr sshd 8
+uses the name supplied by the client rather than
+attempting to resolve the name from the TCP connection itself.
+The default is
+.Dq no .
+.It Cm HostCertificate
+Specifies a file containing a public host certificate.
+The certificate's public key must match a private host key already specified
+by
+.Cm HostKey .
+The default behaviour of
+.Xr sshd 8
+is not to load any certificates.
+.It Cm HostKey
+Specifies a file containing a private host key
+used by SSH.
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+Note that
+.Xr sshd 8
+will refuse to use a file if it is group/world-accessible.
+It is possible to have multiple host key files.
+.Dq rsa1
+keys are used for version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+are used for version 2 of the SSH protocol.
+.It Cm IgnoreRhosts
+Specifies that
+.Pa .rhosts
+and
+.Pa .shosts
+files will not be used in
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+.Pp
+.Pa /etc/hosts.equiv
+and
+.Pa /etc/shosts.equiv
+are still used.
+The default is
+.Dq yes .
+.It Cm IgnoreUserKnownHosts
+Specifies whether
+.Xr sshd 8
+should ignore the user's
+.Pa ~/.ssh/known_hosts
+during
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+The default is
+.Dq no .
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for the connection.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KerberosAuthentication
+Specifies whether the password provided by the user for
+.Cm PasswordAuthentication
+will be validated through the Kerberos KDC.
+To use this option, the server needs a
+Kerberos servtab which allows the verification of the KDC's identity.
+The default is
+.Dq no .
+.It Cm KerberosGetAFSToken
+If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
+an AFS token before accessing the user's home directory.
+The default is
+.Dq no .
+.It Cm KerberosOrLocalPasswd
+If password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as
+.Pa /etc/passwd .
+The default is
+.Dq yes .
+.It Cm KerberosTicketCleanup
+Specifies whether to automatically destroy the user's ticket cache
+file on logout.
+The default is
+.Dq yes .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq ecdh-sha2-nistp256 ,
+.Dq ecdh-sha2-nistp384 ,
+.Dq ecdh-sha2-nistp521 ,
+.Dq diffie-hellman-group-exchange-sha256 ,
+.Dq diffie-hellman-group-exchange-sha1 ,
+.Dq diffie-hellman-group14-sha1 ,
+.Dq diffie-hellman-group1-sha1 .
+.It Cm KeyRegenerationInterval
+In protocol version 1, the ephemeral server key is automatically regenerated
+after this many seconds (if it has been used).
+The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys.
+The key is never stored anywhere.
+If the value is 0, the key is never regenerated.
+The default is 3600 (seconds).
+.It Cm ListenAddress
+Specifies the local addresses
+.Xr sshd 8
+should listen on.
+The following forms may be used:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No : Ar port
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Oo
+.Ar host No | Ar IPv6_addr Oc : Ar port
+.Sm on
+.El
+.Pp
+If
+.Ar port
+is not specified,
+sshd will listen on the address and all prior
+.Cm Port
+options specified.
+The default is to listen on all local addresses.
+Multiple
+.Cm ListenAddress
+options are permitted.
+Additionally, any
+.Cm Port
+options must precede this option for non-port qualified addresses.
+.It Cm LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in.
+If the value is 0, there is no time limit.
+The default is 120 seconds.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr sshd 8 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of debugging output.
+Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm MACs
+Specifies the available MAC (message authentication code) algorithms.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm Match
+Introduces a conditional block.
+If all of the criteria on the
+.Cm Match
+line are satisfied, the keywords on the following lines override those
+set in the global section of the config file, until either another
+.Cm Match
+line or the end of the file.
+.Pp
+The arguments to
+.Cm Match
+are one or more criteria-pattern pairs.
+The available criteria are
+.Cm User ,
+.Cm Group ,
+.Cm Host ,
+and
+.Cm Address .
+The match patterns may consist of single entries or comma-separated
+lists and may use the wildcard and negation operators described in the
+.Sx PATTERNS
+section of
+.Xr ssh_config 5 .
+.Pp
+The patterns in an
+.Cm Address
+criteria may additionally contain addresses to match in CIDR
+address/masklen format, e.g.\&
+.Dq 192.0.2.0/24
+or
+.Dq 3ffe:ffff::/32 .
+Note that the mask length provided must be consistent with the address -
+it is an error to specify a mask length that is too long for the address
+or one with bits set in this host portion of the address.
+For example,
+.Dq 192.0.2.0/33
+and
+.Dq 192.0.2.0/8
+respectively.
+.Pp
+Only a subset of keywords may be used on the lines following a
+.Cm Match
+keyword.
+Available keywords are
+.Cm AllowAgentForwarding ,
+.Cm AllowTcpForwarding ,
+.Cm AuthorizedKeysFile ,
+.Cm AuthorizedPrincipalsFile ,
+.Cm Banner ,
+.Cm ChrootDirectory ,
+.Cm ForceCommand ,
+.Cm GatewayPorts ,
+.Cm GSSAPIAuthentication ,
+.Cm HostbasedAuthentication ,
+.Cm HostbasedUsesNameFromPacketOnly ,
+.Cm KbdInteractiveAuthentication ,
+.Cm KerberosAuthentication ,
+.Cm MaxAuthTries ,
+.Cm MaxSessions ,
+.Cm PasswordAuthentication ,
+.Cm PermitEmptyPasswords ,
+.Cm PermitOpen ,
+.Cm PermitRootLogin ,
+.Cm PermitTunnel ,
+.Cm PubkeyAuthentication ,
+.Cm RhostsRSAAuthentication ,
+.Cm RSAAuthentication ,
+.Cm X11DisplayOffset ,
+.Cm X11Forwarding
+and
+.Cm X11UseLocalHost .
+.It Cm MaxAuthTries
+Specifies the maximum number of authentication attempts permitted per
+connection.
+Once the number of failures reaches half this value,
+additional failures are logged.
+The default is 6.
+.It Cm MaxSessions
+Specifies the maximum number of open sessions permitted per network connection.
+The default is 10.
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+SSH daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g. "10:30:60").
+.Xr sshd 8
+will refuse connection attempts with a probability of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probability increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
+.It Cm PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is
+.Dq yes .
+.It Cm PermitBlacklistedKeys
+Specifies whether
+.Xr sshd 8
+should allow keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 ) .
+If
+.Dq yes ,
+then attempts to authenticate with compromised keys will be logged but
+accepted.
+If
+.Dq no ,
+then attempts to authenticate with compromised keys will be rejected.
+The default is
+.Dq no .
+.It Cm PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings.
+The default is
+.Dq no .
+.It Cm PermitOpen
+Specifies the destinations to which TCP port forwarding is permitted.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Dq any
+can be used to remove all restrictions and permit any forwarding requests.
+By default all port forwarding requests are permitted.
+.It Cm PermitRootLogin
+Specifies whether root can log in using
+.Xr ssh 1 .
+The argument must be
+.Dq yes ,
+.Dq without-password ,
+.Dq forced-commands-only ,
+or
+.Dq no .
+The default is
+.Dq yes .
+.Pp
+If this option is set to
+.Dq without-password ,
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only ,
+root login with public key authentication will be allowed,
+but only if the
+.Ar command
+option has been specified
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+All other authentication methods are disabled for root.
+.Pp
+If this option is set to
+.Dq no ,
+root is not allowed to log in.
+.It Cm PermitTunnel
+Specifies whether
+.Xr tun 4
+device forwarding is allowed.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2), or
+.Dq no .
+Specifying
+.Dq yes
+permits both
+.Dq point-to-point
+and
+.Dq ethernet .
+The default is
+.Dq no .
+.It Cm PermitUserEnvironment
+Specifies whether
+.Pa ~/.ssh/environment
+and
+.Cm environment=
+options in
+.Pa ~/.ssh/authorized_keys
+are processed by
+.Xr sshd 8 .
+The default is
+.Dq no .
+Enabling environment processing may enable users to bypass access
+restrictions in some configurations using mechanisms such as
+.Ev LD_PRELOAD .
+.It Cm PidFile
+Specifies the file that contains the process ID of the
+SSH daemon.
+The default is
+.Pa /var/run/sshd.pid .
+.It Cm Port
+Specifies the port number that
+.Xr sshd 8
+listens on.
+The default is 22.
+Multiple options of this type are permitted.
+See also
+.Cm ListenAddress .
+.It Cm PrintLastLog
+Specifies whether
+.Xr sshd 8
+should print the date and time of the last user login when a user logs
+in interactively.
+The default is
+.Dq yes .
+.It Cm PrintMotd
+Specifies whether
+.Xr sshd 8
+should print
+.Pa /etc/motd
+when a user logs in interactively.
+(On some systems it is also printed by the shell,
+.Pa /etc/profile ,
+or equivalent.)
+The default is
+.Dq yes .
+.It Cm Protocol
+Specifies the protocol versions
+.Xr sshd 8
+supports.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Sq 2 .
+Note that the order of the protocol list does not indicate preference,
+because the client selects among multiple protocol versions offered
+by the server.
+Specifying
+.Dq 2,1
+is identical to
+.Dq 1,2 .
+.It Cm PubkeyAuthentication
+Specifies whether public key authentication is allowed.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm RevokedKeys
+Specifies a list of revoked public keys.
+Keys listed in this file will be refused for public key authentication.
+Note that if this file is not readable, then public key authentication will
+be refused for all users.
+.It Cm RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RSAAuthentication
+Specifies whether pure RSA authentication is allowed.
+The default is
+.Dq yes .
+This option applies to protocol version 1 only.
+.It Cm ServerKeyBits
+Defines the number of bits in the ephemeral protocol version 1 server key.
+The minimum value is 512, and the default is 1024.
+.It Cm StrictModes
+Specifies whether
+.Xr sshd 8
+should check file modes and ownership of the
+user's files and home directory before accepting login.
+This is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable.
+The default is
+.Dq yes .
+Note that this does not apply to
+.Cm ChrootDirectory ,
+whose permissions and ownership are checked unconditionally.
+.It Cm Subsystem
+Configures an external subsystem (e.g. file transfer daemon).
+Arguments should be a subsystem name and a command (with optional arguments)
+to execute upon subsystem request.
+.Pp
+The command
+.Xr sftp-server 8
+implements the
+.Dq sftp
+file transfer subsystem.
+.Pp
+Alternately the name
+.Dq internal-sftp
+implements an in-process
+.Dq sftp
+server.
+This may simplify configurations using
+.Cm ChrootDirectory
+to force a different filesystem root on clients.
+.Pp
+By default no subsystems are defined.
+Note that this option applies to protocol version 2 only.
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Xr sshd 8 .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is AUTH.
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+On the other hand, if TCP keepalives are not sent,
+sessions may hang indefinitely on the server, leaving
+.Dq ghost
+users and consuming server resources.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the server will notice
+if the network goes down or the client host crashes.
+This avoids infinitely hanging sessions.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm TrustedUserCAKeys
+Specifies a file containing public keys of certificate authorities that are
+trusted to sign user certificates for authentication.
+Keys are listed one per line; empty lines and comments starting with
+.Ql #
+are allowed.
+If a certificate is presented for authentication and has its signing CA key
+listed in this file, then it may be used for authentication for any user
+listed in the certificate's principals list.
+Note that certificates that lack a list of principals will not be permitted
+for authentication using
+.Cm TrustedUserCAKeys .
+For more details on certificates, see the
+.Sx CERTIFICATES
+section in
+.Xr ssh-keygen 1 .
+.It Cm UseDNS
+Specifies whether
+.Xr sshd 8
+should look up the remote host name and check that
+the resolved host name for the remote IP address maps back to the
+very same IP address.
+The default is
+.Dq yes .
+.It Cm UseLogin
+Specifies whether
+.Xr login 1
+is used for interactive login sessions.
+The default is
+.Dq no .
+Note that
+.Xr login 1
+is never used for remote command execution.
+Note also, that if this is enabled,
+.Cm X11Forwarding
+will be disabled because
+.Xr login 1
+does not know how to handle
+.Xr xauth 1
+cookies.
+If
+.Cm UsePrivilegeSeparation
+is specified, it will be disabled after authentication.
+.It Cm UsePAM
+Enables the Pluggable Authentication Module interface.
+If set to
+.Dq yes
+this will enable PAM authentication using
+.Cm ChallengeResponseAuthentication
+and
+.Cm PasswordAuthentication
+in addition to PAM account and session module processing for all
+authentication types.
+.Pp
+Because PAM challenge-response authentication usually serves an equivalent
+role to password authentication, you should disable either
+.Cm PasswordAuthentication
+or
+.Cm ChallengeResponseAuthentication.
+.Pp
+If
+.Cm UsePAM
+is enabled, you will not be able to run
+.Xr sshd 8
+as a non-root user.
+The default is
+.Dq no .
+.It Cm UsePrivilegeSeparation
+Specifies whether
+.Xr sshd 8
+separates privileges by creating an unprivileged child process
+to deal with incoming network traffic.
+After successful authentication, another process will be created that has
+the privilege of the authenticated user.
+The goal of privilege separation is to prevent privilege
+escalation by containing any corruption within the unprivileged processes.
+The default is
+.Dq yes .
+If
+.Cm UsePrivilegeSeparation
+is set to
+.Dq sandbox
+then the pre-authentication unprivileged process is subject to additional
+restrictions.
+.It Cm X11DisplayOffset
+Specifies the first display number available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from interfering with real X11 servers.
+The default is 10.
+.It Cm X11Forwarding
+Specifies whether X11 forwarding is permitted.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+When X11 forwarding is enabled, there may be additional exposure to
+the server and to client displays if the
+.Xr sshd 8
+proxy display is configured to listen on the wildcard address (see
+.Cm X11UseLocalhost
+below), though this is not the default.
+Additionally, the authentication spoofing and authentication data
+verification and substitution occur on the client side.
+The security risk of using X11 forwarding is that the client's X11
+display server may be exposed to attack when the SSH client requests
+forwarding (see the warnings for
+.Cm ForwardX11
+in
+.Xr ssh_config 5 ) .
+A system administrator may have a stance in which they want to
+protect clients that may expose themselves to attack by unwittingly
+requesting X11 forwarding, which can warrant a
+.Dq no
+setting.
+.Pp
+Note that disabling X11 forwarding does not prevent users from
+forwarding X11 traffic, as users can always install their own forwarders.
+X11 forwarding is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm X11UseLocalhost
+Specifies whether
+.Xr sshd 8
+should bind the X11 forwarding server to the loopback address or to
+the wildcard address.
+By default,
+sshd binds the forwarding server to the loopback address and sets the
+hostname part of the
+.Ev DISPLAY
+environment variable to
+.Dq localhost .
+This prevents remote hosts from connecting to the proxy display.
+However, some older X11 clients may not function with this
+configuration.
+.Cm X11UseLocalhost
+may be set to
+.Dq no
+to specify that the forwarding server should be bound to the wildcard
+address.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh TIME FORMATS
+.Xr sshd 8
+command-line arguments and configuration file options that specify time
+may be expressed using a sequence of the form:
+.Sm off
+.Ar time Op Ar qualifier ,
+.Sm on
+where
+.Ar time
+is a positive integer value and
+.Ar qualifier
+is one of the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Aq Cm none
+seconds
+.It Cm s | Cm S
+seconds
+.It Cm m | Cm M
+minutes
+.It Cm h | Cm H
+hours
+.It Cm d | Cm D
+days
+.It Cm w | Cm W
+weeks
+.El
+.Pp
+Each member of the sequence is added together to calculate
+the total time value.
+.Pp
+Time format examples:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It 600
+600 seconds (10 minutes)
+.It 10m
+10 minutes
+.It 1h30m
+1 hour 30 minutes (90 minutes)
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Xr sshd 8 .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.El
+.Sh SEE ALSO
+.Xr sshd 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
diff --git a/.pc/lintian-symlink-pickiness.patch/Makefile.in b/.pc/lintian-symlink-pickiness.patch/Makefile.in
new file mode 100644 (file)
index 0000000..f1621cd
--- /dev/null
@@ -0,0 +1,453 @@
+# $Id: Makefile.in,v 1.325 2011/08/05 20:15:18 djm Exp $
+
+# uncomment if you run a non bourne compatable shell. Ie. csh
+#SHELL = @SH@
+
+AUTORECONF=autoreconf
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+sbindir=@sbindir@
+libexecdir=@libexecdir@
+datadir=@datadir@
+datarootdir=@datarootdir@
+mandir=@mandir@
+mansubdir=@mansubdir@
+sysconfdir=@sysconfdir@
+piddir=@piddir@
+srcdir=@srcdir@
+top_srcdir=@top_srcdir@
+
+DESTDIR=
+VPATH=@srcdir@
+SSH_PROGRAM=@bindir@/ssh
+ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
+SFTP_SERVER=$(libexecdir)/sftp-server
+SSH_KEYSIGN=$(libexecdir)/ssh-keysign
+SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
+SSH_DATADIR=$(datadir)/ssh
+PRIVSEP_PATH=@PRIVSEP_PATH@
+SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
+STRIP_OPT=@STRIP_OPT@
+
+PATHS= -DSSHDIR=\"$(sysconfdir)\" \
+       -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
+       -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
+       -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
+       -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
+       -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
+       -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
+       -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
+       -D_PATH_SSH_DATADIR=\"$(SSH_DATADIR)\" \
+
+CC=@CC@
+LD=@LD@
+CFLAGS=@CFLAGS@
+CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+LIBS=@LIBS@
+SSHLIBS=@SSHLIBS@
+SSHDLIBS=@SSHDLIBS@
+LIBEDIT=@LIBEDIT@
+AR=@AR@
+AWK=@AWK@
+RANLIB=@RANLIB@
+INSTALL=@INSTALL@
+PERL=@PERL@
+SED=@SED@
+ENT=@ENT@
+XAUTH_PATH=@XAUTH_PATH@
+LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
+EXEEXT=@EXEEXT@
+MANFMT=@MANFMT@
+
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-vulnkey$(EXEEXT)
+
+LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
+       canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
+       cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
+       compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
+       log.o match.o md-sha256.o moduli.o nchan.o packet.o \
+       readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
+       atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
+       monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
+       kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
+       kexgssc.o \
+       msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
+       schnorr.o ssh-pkcs11.o
+
+SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
+       sshconnect.o sshconnect1.o sshconnect2.o mux.o \
+       roaming_common.o roaming_client.o
+
+SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
+       audit.o audit-bsm.o audit-linux.o platform.o \
+       sshpty.o sshlogin.o servconf.o serverloop.o \
+       auth.o auth1.o auth2.o auth-options.o session.o \
+       auth-chall.o auth2-chall.o groupaccess.o \
+       auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
+       auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
+       monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
+       auth-krb5.o \
+       auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
+       loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
+       sftp-server.o sftp-common.o \
+       roaming_common.o roaming_serv.o \
+       sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
+
+MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-vulnkey.1.out sshd_config.5.out ssh_config.5.out
+MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-vulnkey.1 sshd_config.5 ssh_config.5
+MANTYPE                = @MANTYPE@
+
+CONFIGFILES=sshd_config.out ssh_config.out moduli.out
+CONFIGFILES_IN=sshd_config ssh_config moduli
+
+PATHSUBS       = \
+       -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
+       -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
+       -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \
+       -e 's|/usr/libexec|$(libexecdir)|g' \
+       -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \
+       -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \
+       -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
+       -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
+       -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \
+       -e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \
+       -e 's|/var/empty|$(PRIVSEP_PATH)|g' \
+       -e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g'
+
+FIXPATHSCMD    = $(SED) $(PATHSUBS)
+
+all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+
+$(LIBSSH_OBJS): Makefile.in config.h
+$(SSHOBJS): Makefile.in config.h
+$(SSHDOBJS): Makefile.in config.h
+
+.c.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
+$(LIBCOMPAT): always
+       (cd openbsd-compat && $(MAKE))
+always:
+
+libssh.a: $(LIBSSH_OBJS)
+       $(AR) rv $@ $(LIBSSH_OBJS)
+       $(RANLIB) $@
+
+ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
+       $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
+
+sshd$(EXEEXT): libssh.a        $(LIBCOMPAT) $(SSHDOBJS)
+       $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
+
+scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
+       $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
+       $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
+       $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
+       $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o
+       $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
+       $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
+       $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
+       $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
+       $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
+
+ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o
+       $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+# test driver for the loginrec code - not built by default
+logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
+       $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
+
+$(MANPAGES): $(MANPAGES_IN)
+       if test "$(MANTYPE)" = "cat"; then \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \
+       else \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \
+       fi; \
+       if test "$(MANTYPE)" = "man"; then \
+               $(FIXPATHSCMD) $${manpage} | $(AWK) -f $(srcdir)/mdoc2man.awk > $@; \
+       else \
+               $(FIXPATHSCMD) $${manpage} > $@; \
+       fi
+
+$(CONFIGFILES): $(CONFIGFILES_IN)
+       conffile=`echo $@ | sed 's/.out$$//'`; \
+       $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@
+
+# fake rule to stop make trying to compile moduli.o into a binary "moduli.o"
+moduli:
+       echo
+
+clean: regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core survey
+       (cd openbsd-compat && $(MAKE) clean)
+
+distclean:     regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core opensshd.init openssh.xml
+       rm -f Makefile buildpkg.sh config.h config.status
+       rm -f survey.sh openbsd-compat/regress/Makefile *~ 
+       rm -rf autom4te.cache
+       (cd openbsd-compat && $(MAKE) distclean)
+       if test -d pkg ; then \
+               rm -fr pkg ; \
+       fi
+
+veryclean: distclean
+       rm -f configure config.h.in *.0
+
+cleandir: veryclean
+
+mrproper: veryclean
+
+realclean: veryclean
+
+catman-do:
+       @for f in $(MANPAGES_IN) ; do \
+               base=`echo $$f | sed 's/\..*$$//'` ; \
+               echo "$$f -> $$base.0" ; \
+               $(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \
+                       >$$base.0 ; \
+       done
+
+distprep: catman-do
+       $(AUTORECONF)
+       -rm -rf autom4te.cache
+
+install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
+install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf
+install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files
+
+check-config:
+       -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
+
+install-files:
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)5
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir)
+       (umask 022 ; $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH))
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey$(EXEEXT) $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
+       $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       $(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       $(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5
+       $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
+       $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
+       $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       ln -s ../$(mansubdir)8/sshd.8 $(DESTDIR)$(mandir)/$(mansubdir)5/authorized_keys.5
+       $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+       ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+install-sysconf:
+       if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
+               $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \
+               $(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \
+               $(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \
+               if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \
+                       echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \
+                       mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \
+               else \
+                       $(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \
+               fi ; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \
+       fi
+
+host-key: ssh-keygen$(EXEEXT)
+       @if [ -z "$(DESTDIR)" ] ; then \
+               if [ -f "$(sysconfdir)/ssh_host_key" ] ; then \
+                       echo "$(sysconfdir)/ssh_host_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa1 -f $(sysconfdir)/ssh_host_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_dsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t dsa -f $(sysconfdir)/ssh_host_dsa_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_rsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa -f $(sysconfdir)/ssh_host_rsa_key -N "" ; \
+               fi ; \
+               if [ -z "@COMMENT_OUT_ECC@" ] ; then \
+                   if [ -f $(sysconfdir)/ssh_host_ecdsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_ecdsa_key already exists, skipping." ; \
+                   else \
+                       ./ssh-keygen -t ecdsa -f $(sysconfdir)/ssh_host_ecdsa_key -N "" ; \
+                   fi ; \
+               fi ; \
+       fi ;
+
+host-key-force: ssh-keygen$(EXEEXT)
+       ./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
+       ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
+       ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
+       test -z "@COMMENT_OUT_ECC@" && ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""
+
+uninstallall:  uninstall
+       -rm -f $(DESTDIR)$(sysconfdir)/ssh_config
+       -rm -f $(DESTDIR)$(sysconfdir)/sshd_config
+       -rmdir $(DESTDIR)$(sysconfdir)
+       -rmdir $(DESTDIR)$(bindir)
+       -rmdir $(DESTDIR)$(sbindir)
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)1
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)8
+       -rmdir $(DESTDIR)$(mandir)
+       -rmdir $(DESTDIR)$(libexecdir)
+
+uninstall:
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+tests interop-tests:   $(TARGETS)
+       BUILDDIR=`pwd`; \
+       [ -d `pwd`/regress ]  ||  mkdir -p `pwd`/regress; \
+       [ -f `pwd`/regress/Makefile ]  || \
+           ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile ; \
+       TEST_SHELL="@TEST_SHELL@"; \
+       TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
+       TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
+       TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
+       TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
+       TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
+       TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
+       TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
+       TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
+       TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
+       TEST_SSH_PLINK="plink"; \
+       TEST_SSH_PUTTYGEN="puttygen"; \
+       TEST_SSH_CONCH="conch"; \
+       TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
+       TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
+       TEST_SSH_SHA256="@TEST_SSH_SHA256@" ; \
+       cd $(srcdir)/regress || exit $$?; \
+       $(MAKE) \
+               .OBJDIR="$${BUILDDIR}/regress" \
+               .CURDIR="`pwd`" \
+               BUILDDIR="$${BUILDDIR}" \
+               OBJ="$${BUILDDIR}/regress/" \
+               PATH="$${BUILDDIR}:$${PATH}" \
+               TEST_SHELL="$${TEST_SHELL}" \
+               TEST_SSH_SSH="$${TEST_SSH_SSH}" \
+               TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
+               TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
+               TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
+               TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
+               TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
+               TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
+               TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
+               TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
+               TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
+               TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
+               TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
+               TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
+               TEST_SSH_ECC="$${TEST_SSH_ECC}" \
+               TEST_SSH_SHA256="$${TEST_SSH_SHA256}" \
+               EXEEXT="$(EXEEXT)" \
+               $@ && echo all tests passed
+
+compat-tests: $(LIBCOMPAT)
+       (cd openbsd-compat/regress && $(MAKE))
+
+regressclean:
+       if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \
+               (cd regress && $(MAKE) clean) \
+       fi
+
+survey: survey.sh ssh
+       @$(SHELL) ./survey.sh > survey
+       @echo 'The survey results have been placed in the file "survey" in the'
+       @echo 'current directory.  Please review the file then send with'
+       @echo '"make send-survey".'
+
+send-survey:   survey
+       mail portable-survey@mindrot.org <survey
+
+package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+       if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
+               sh buildpkg.sh; \
+       fi
+
diff --git a/.pc/openbsd-docs.patch/moduli.5 b/.pc/openbsd-docs.patch/moduli.5
new file mode 100644 (file)
index 0000000..0e01b94
--- /dev/null
@@ -0,0 +1,122 @@
+.\"    $OpenBSD: moduli.5,v 1.15 2010/10/14 20:41:28 jmc Exp $
+.\"
+.\" Copyright (c) 2008 Damien Miller <djm@mindrot.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.Dd $Mdocdate: October 14 2010 $
+.Dt MODULI 5
+.Os
+.Sh NAME
+.Nm moduli
+.Nd Diffie-Hellman moduli
+.Sh DESCRIPTION
+The
+.Pa /etc/moduli
+file contains prime numbers and generators for use by
+.Xr sshd 8
+in the Diffie-Hellman Group Exchange key exchange method.
+.Pp
+New moduli may be generated with
+.Xr ssh-keygen 1
+using a two-step process.
+An initial
+.Em candidate generation
+pass, using
+.Ic ssh-keygen -G ,
+calculates numbers that are likely to be useful.
+A second
+.Em primality testing
+pass, using
+.Ic ssh-keygen -T ,
+provides a high degree of assurance that the numbers are prime and are
+safe for use in Diffie-Hellman operations by
+.Xr sshd 8 .
+This
+.Nm
+format is used as the output from each pass.
+.Pp
+The file consists of newline-separated records, one per modulus,
+containing seven space-separated fields.
+These fields are as follows:
+.Bl -tag -width Description -offset indent
+.It timestamp
+The time that the modulus was last processed as YYYYMMDDHHMMSS.
+.It type
+Decimal number specifying the internal structure of the prime modulus.
+Supported types are:
+.Pp
+.Bl -tag -width 0x00 -compact
+.It 0
+Unknown, not tested.
+.It 2
+"Safe" prime; (p-1)/2 is also prime.
+.It 4
+Sophie Germain; (p+1)*2 is also prime.
+.El
+.Pp
+Moduli candidates initially produced by
+.Xr ssh-keygen 1
+are Sophie Germain primes (type 4).
+Further primality testing with
+.Xr ssh-keygen 1
+produces safe prime moduli (type 2) that are ready for use in
+.Xr sshd 8 .
+Other types are not used by OpenSSH.
+.It tests
+Decimal number indicating the type of primality tests that the number
+has been subjected to represented as a bitmask of the following values:
+.Pp
+.Bl -tag -width 0x00 -compact
+.It 0x00
+Not tested.
+.It 0x01
+Composite number \(en not prime.
+.It 0x02
+Sieve of Eratosthenes.
+.It 0x04
+Probabilistic Miller-Rabin primality tests.
+.El
+.Pp
+The
+.Xr ssh-keygen 1
+moduli candidate generation uses the Sieve of Eratosthenes (flag 0x02).
+Subsequent
+.Xr ssh-keygen 1
+primality tests are Miller-Rabin tests (flag 0x04).
+.It trials
+Decimal number indicating the number of primality trials
+that have been performed on the modulus.
+.It size
+Decimal number indicating the size of the prime in bits.
+.It generator
+The recommended generator for use with this modulus (hexadecimal).
+.It modulus
+The modulus itself in hexadecimal.
+.El
+.Pp
+When performing Diffie-Hellman Group Exchange,
+.Xr sshd 8
+first estimates the size of the modulus required to produce enough
+Diffie-Hellman output to sufficiently key the selected symmetric cipher.
+.Xr sshd 8
+then randomly selects a modulus from
+.Fa /etc/moduli
+that best meets the size requirement.
+.Sh SEE ALSO
+.Xr ssh-keygen 1 ,
+.Xr sshd 8
+.Rs
+.%R RFC 4419
+.%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
diff --git a/.pc/openbsd-docs.patch/ssh-keygen.1 b/.pc/openbsd-docs.patch/ssh-keygen.1
new file mode 100644 (file)
index 0000000..afbd7f8
--- /dev/null
@@ -0,0 +1,689 @@
+.\"    $OpenBSD: ssh-keygen.1,v 1.106 2011/04/13 04:09:37 djm Exp $
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd $Mdocdate: April 13 2011 $
+.Dt SSH-KEYGEN 1
+.Os
+.Sh NAME
+.Nm ssh-keygen
+.Nd authentication key generation, management and conversion
+.Sh SYNOPSIS
+.Bk -words
+.Nm ssh-keygen
+.Op Fl q
+.Op Fl b Ar bits
+.Fl t Ar type
+.Op Fl N Ar new_passphrase
+.Op Fl C Ar comment
+.Op Fl f Ar output_keyfile
+.Nm ssh-keygen
+.Fl p
+.Op Fl P Ar old_passphrase
+.Op Fl N Ar new_passphrase
+.Op Fl f Ar keyfile
+.Nm ssh-keygen
+.Fl i
+.Op Fl m Ar key_format
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl e
+.Op Fl m Ar key_format
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl y
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl c
+.Op Fl P Ar passphrase
+.Op Fl C Ar comment
+.Op Fl f Ar keyfile
+.Nm ssh-keygen
+.Fl l
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl B
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl D Ar pkcs11
+.Nm ssh-keygen
+.Fl F Ar hostname
+.Op Fl f Ar known_hosts_file
+.Op Fl l
+.Nm ssh-keygen
+.Fl H
+.Op Fl f Ar known_hosts_file
+.Nm ssh-keygen
+.Fl R Ar hostname
+.Op Fl f Ar known_hosts_file
+.Nm ssh-keygen
+.Fl r Ar hostname
+.Op Fl f Ar input_keyfile
+.Op Fl g
+.Nm ssh-keygen
+.Fl G Ar output_file
+.Op Fl v
+.Op Fl b Ar bits
+.Op Fl M Ar memory
+.Op Fl S Ar start_point
+.Nm ssh-keygen
+.Fl T Ar output_file
+.Fl f Ar input_file
+.Op Fl v
+.Op Fl a Ar num_trials
+.Op Fl W Ar generator
+.Nm ssh-keygen
+.Fl s Ar ca_key
+.Fl I Ar certificate_identity
+.Op Fl h
+.Op Fl n Ar principals
+.Op Fl O Ar option
+.Op Fl V Ar validity_interval
+.Op Fl z Ar serial_number
+.Ar
+.Nm ssh-keygen
+.Fl L
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl A
+.Ek
+.Sh DESCRIPTION
+.Nm
+generates, manages and converts authentication keys for
+.Xr ssh 1 .
+.Nm
+can create RSA keys for use by SSH protocol version 1 and DSA, ECDSA or RSA
+keys for use by SSH protocol version 2.
+The type of key to be generated is specified with the
+.Fl t
+option.
+If invoked without any arguments,
+.Nm
+will generate an RSA key for use in SSH protocol 2 connections.
+.Pp
+.Nm
+is also used to generate groups for use in Diffie-Hellman group
+exchange (DH-GEX).
+See the
+.Sx MODULI GENERATION
+section for details.
+.Pp
+Normally each user wishing to use SSH
+with public key authentication runs this once to create the authentication
+key in
+.Pa ~/.ssh/identity ,
+.Pa ~/.ssh/id_ecdsa ,
+.Pa ~/.ssh/id_dsa
+or
+.Pa ~/.ssh/id_rsa .
+Additionally, the system administrator may use this to generate host keys,
+as seen in
+.Pa /etc/rc .
+.Pp
+Normally this program generates the key and asks for a file in which
+to store the private key.
+The public key is stored in a file with the same name but
+.Dq .pub
+appended.
+The program also asks for a passphrase.
+The passphrase may be empty to indicate no passphrase
+(host keys must have an empty passphrase), or it may be a string of
+arbitrary length.
+A passphrase is similar to a password, except it can be a phrase with a
+series of words, punctuation, numbers, whitespace, or any string of
+characters you want.
+Good passphrases are 10-30 characters long, are
+not simple sentences or otherwise easily guessable (English
+prose has only 1-2 bits of entropy per character, and provides very bad
+passphrases), and contain a mix of upper and lowercase letters,
+numbers, and non-alphanumeric characters.
+The passphrase can be changed later by using the
+.Fl p
+option.
+.Pp
+There is no way to recover a lost passphrase.
+If the passphrase is lost or forgotten, a new key must be generated
+and the corresponding public key copied to other machines.
+.Pp
+For RSA1 keys,
+there is also a comment field in the key file that is only for
+convenience to the user to help identify the key.
+The comment can tell what the key is for, or whatever is useful.
+The comment is initialized to
+.Dq user@host
+when the key is created, but can be changed using the
+.Fl c
+option.
+.Pp
+After a key is generated, instructions below detail where the keys
+should be placed to be activated.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl A
+For each of the key types (rsa1, rsa, dsa and ecdsa) for which host keys
+do not exist, generate the host keys with the default key file path,
+an empty passphrase, default bits for the key type, and default comment.
+This is used by
+.Pa /etc/rc
+to generate new host keys.
+.It Fl a Ar trials
+Specifies the number of primality tests to perform when screening DH-GEX
+candidates using the
+.Fl T
+command.
+.It Fl B
+Show the bubblebabble digest of specified private or public key file.
+.It Fl b Ar bits
+Specifies the number of bits in the key to create.
+For RSA keys, the minimum size is 768 bits and the default is 2048 bits.
+Generally, 2048 bits is considered sufficient.
+DSA keys must be exactly 1024 bits as specified by FIPS 186-2.
+For ECDSA keys, the
+.Fl b
+flag determines they key length by selecting from one of three elliptic
+curve sizes: 256, 384 or 521 bits.
+Attempting to use bit lengths other than these three values for ECDSA keys
+will fail.
+.It Fl C Ar comment
+Provides a new comment.
+.It Fl c
+Requests changing the comment in the private and public key files.
+This operation is only supported for RSA1 keys.
+The program will prompt for the file containing the private keys, for
+the passphrase if the key has one, and for the new comment.
+.It Fl D Ar pkcs11
+Download the RSA public keys provided by the PKCS#11 shared library
+.Ar pkcs11 .
+When used in combination with
+.Fl s ,
+this option indicates that a CA key resides in a PKCS#11 token (see the
+.Sx CERTIFICATES
+section for details).
+.It Fl e
+This option will read a private or public OpenSSH key file and
+print to stdout the key in one of the formats specified by the
+.Fl m
+option.
+The default export format is
+.Dq RFC4716 .
+This option allows exporting OpenSSH keys for use by other programs, including
+several commercial SSH implementations.
+.It Fl F Ar hostname
+Search for the specified
+.Ar hostname
+in a
+.Pa known_hosts
+file, listing any occurrences found.
+This option is useful to find hashed host names or addresses and may also be
+used in conjunction with the
+.Fl H
+option to print found keys in a hashed format.
+.It Fl f Ar filename
+Specifies the filename of the key file.
+.It Fl G Ar output_file
+Generate candidate primes for DH-GEX.
+These primes must be screened for
+safety (using the
+.Fl T
+option) before use.
+.It Fl g
+Use generic DNS format when printing fingerprint resource records using the
+.Fl r
+command.
+.It Fl H
+Hash a
+.Pa known_hosts
+file.
+This replaces all hostnames and addresses with hashed representations
+within the specified file; the original content is moved to a file with
+a .old suffix.
+These hashes may be used normally by
+.Nm ssh
+and
+.Nm sshd ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+This option will not modify existing hashed hostnames and is therefore safe
+to use on files that mix hashed and non-hashed names.
+.It Fl h
+When signing a key, create a host certificate instead of a user
+certificate.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl I Ar certificate_identity
+Specify the key identity when signing a public key.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl i
+This option will read an unencrypted private (or public) key file
+in the format specified by the
+.Fl m
+option and print an OpenSSH compatible private
+(or public) key to stdout.
+This option allows importing keys from other software, including several
+commercial SSH implementations.
+The default import format is
+.Dq RFC4716 .
+.It Fl L
+Prints the contents of a certificate.
+.It Fl l
+Show fingerprint of specified public key file.
+Private RSA1 keys are also supported.
+For RSA and DSA keys
+.Nm
+tries to find the matching public key file and prints its fingerprint.
+If combined with
+.Fl v ,
+an ASCII art representation of the key is supplied with the fingerprint.
+.It Fl M Ar memory
+Specify the amount of memory to use (in megabytes) when generating
+candidate moduli for DH-GEX.
+.It Fl m Ar key_format
+Specify a key format for the
+.Fl i
+(import) or
+.Fl e
+(export) conversion options.
+The supported key formats are:
+.Dq RFC4716
+(RFC 4716/SSH2 public or private key),
+.Dq PKCS8
+(PEM PKCS8 public key)
+or
+.Dq PEM
+(PEM public key).
+The default conversion format is
+.Dq RFC4716 .
+.It Fl N Ar new_passphrase
+Provides the new passphrase.
+.It Fl n Ar principals
+Specify one or more principals (user or host names) to be included in
+a certificate when signing a key.
+Multiple principals may be specified, separated by commas.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl O Ar option
+Specify a certificate option when signing a key.
+This option may be specified multiple times.
+Please see the
+.Sx CERTIFICATES
+section for details.
+The options that are valid for user certificates are:
+.Bl -tag -width Ds
+.It Ic clear
+Clear all enabled permissions.
+This is useful for clearing the default set of permissions so permissions may
+be added individually.
+.It Ic force-command Ns = Ns Ar command
+Forces the execution of
+.Ar command
+instead of any shell or command specified by the user when
+the certificate is used for authentication.
+.It Ic no-agent-forwarding
+Disable
+.Xr ssh-agent 1
+forwarding (permitted by default).
+.It Ic no-port-forwarding
+Disable port forwarding (permitted by default).
+.It Ic no-pty
+Disable PTY allocation (permitted by default).
+.It Ic no-user-rc
+Disable execution of
+.Pa ~/.ssh/rc
+by
+.Xr sshd 8
+(permitted by default).
+.It Ic no-x11-forwarding
+Disable X11 forwarding (permitted by default).
+.It Ic permit-agent-forwarding
+Allows
+.Xr ssh-agent 1
+forwarding.
+.It Ic permit-port-forwarding
+Allows port forwarding.
+.It Ic permit-pty
+Allows PTY allocation.
+.It Ic permit-user-rc
+Allows execution of
+.Pa ~/.ssh/rc
+by
+.Xr sshd 8 .
+.It Ic permit-x11-forwarding
+Allows X11 forwarding.
+.It Ic source-address Ns = Ns Ar address_list
+Restrict the source addresses from which the certificate is considered valid.
+The
+.Ar address_list
+is a comma-separated list of one or more address/netmask pairs in CIDR
+format.
+.El
+.Pp
+At present, no options are valid for host keys.
+.It Fl P Ar passphrase
+Provides the (old) passphrase.
+.It Fl p
+Requests changing the passphrase of a private key file instead of
+creating a new private key.
+The program will prompt for the file
+containing the private key, for the old passphrase, and twice for the
+new passphrase.
+.It Fl q
+Silence
+.Nm ssh-keygen .
+.It Fl R Ar hostname
+Removes all keys belonging to
+.Ar hostname
+from a
+.Pa known_hosts
+file.
+This option is useful to delete hashed hosts (see the
+.Fl H
+option above).
+.It Fl r Ar hostname
+Print the SSHFP fingerprint resource record named
+.Ar hostname
+for the specified public key file.
+.It Fl S Ar start
+Specify start point (in hex) when generating candidate moduli for DH-GEX.
+.It Fl s Ar ca_key
+Certify (sign) a public key using the specified CA key.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl T Ar output_file
+Test DH group exchange candidate primes (generated using the
+.Fl G
+option) for safety.
+.It Fl t Ar type
+Specifies the type of key to create.
+The possible values are
+.Dq rsa1
+for protocol version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+for protocol version 2.
+.It Fl V Ar validity_interval
+Specify a validity interval when signing a certificate.
+A validity interval may consist of a single time, indicating that the
+certificate is valid beginning now and expiring at that time, or may consist
+of two times separated by a colon to indicate an explicit time interval.
+The start time may be specified as a date in YYYYMMDD format, a time
+in YYYYMMDDHHMMSS format or a relative time (to the current time) consisting
+of a minus sign followed by a relative time in the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMMSS time or
+a relative time starting with a plus character.
+.Pp
+For example:
+.Dq +52w1d
+(valid from now to 52 weeks and one day from now),
+.Dq -4w:+4w
+(valid from four weeks ago to four weeks from now),
+.Dq 20100101123000:20110101123000
+(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011),
+.Dq -1d:20110101
+(valid from yesterday to midnight, January 1st, 2011).
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful for debugging moduli generation.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.It Fl W Ar generator
+Specify desired generator when testing candidate moduli for DH-GEX.
+.It Fl y
+This option will read a private
+OpenSSH format file and print an OpenSSH public key to stdout.
+.It Fl z Ar serial_number
+Specifies a serial number to be embedded in the certificate to distinguish
+this certificate from others from the same CA.
+The default serial number is zero.
+.El
+.Sh MODULI GENERATION
+.Nm
+may be used to generate groups for the Diffie-Hellman Group Exchange
+(DH-GEX) protocol.
+Generating these groups is a two-step process: first, candidate
+primes are generated using a fast, but memory intensive process.
+These candidate primes are then tested for suitability (a CPU-intensive
+process).
+.Pp
+Generation of primes is performed using the
+.Fl G
+option.
+The desired length of the primes may be specified by the
+.Fl b
+option.
+For example:
+.Pp
+.Dl # ssh-keygen -G moduli-2048.candidates -b 2048
+.Pp
+By default, the search for primes begins at a random point in the
+desired length range.
+This may be overridden using the
+.Fl S
+option, which specifies a different start point (in hex).
+.Pp
+Once a set of candidates have been generated, they must be tested for
+suitability.
+This may be performed using the
+.Fl T
+option.
+In this mode
+.Nm
+will read candidates from standard input (or a file specified using the
+.Fl f
+option).
+For example:
+.Pp
+.Dl # ssh-keygen -T moduli-2048 -f moduli-2048.candidates
+.Pp
+By default, each candidate will be subjected to 100 primality tests.
+This may be overridden using the
+.Fl a
+option.
+The DH generator value will be chosen automatically for the
+prime under consideration.
+If a specific generator is desired, it may be requested using the
+.Fl W
+option.
+Valid generator values are 2, 3, and 5.
+.Pp
+Screened DH groups may be installed in
+.Pa /etc/moduli .
+It is important that this file contains moduli of a range of bit lengths and
+that both ends of a connection share common moduli.
+.Sh CERTIFICATES
+.Nm
+supports signing of keys to produce certificates that may be used for
+user or host authentication.
+Certificates consist of a public key, some identity information, zero or
+more principal (user or host) names and a set of options that
+are signed by a Certification Authority (CA) key.
+Clients or servers may then trust only the CA key and verify its signature
+on a certificate rather than trusting many user/host keys.
+Note that OpenSSH certificates are a different, and much simpler, format to
+the X.509 certificates used in
+.Xr ssl 8 .
+.Pp
+.Nm
+supports two types of certificates: user and host.
+User certificates authenticate users to servers, whereas host certificates
+authenticate server hosts to users.
+To generate a user certificate:
+.Pp
+.Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub
+.Pp
+The resultant certificate will be placed in
+.Pa /path/to/user_key-cert.pub .
+A host certificate requires the
+.Fl h
+option:
+.Pp
+.Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub
+.Pp
+The host certificate will be output to
+.Pa /path/to/host_key-cert.pub .
+.Pp
+It is possible to sign using a CA key stored in a PKCS#11 token by
+providing the token library using
+.Fl D
+and identifying the CA key by providing its public half as an argument
+to
+.Fl s :
+.Pp
+.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub
+.Pp
+In all cases,
+.Ar key_id
+is a "key identifier" that is logged by the server when the certificate
+is used for authentication.
+.Pp
+Certificates may be limited to be valid for a set of principal (user/host)
+names.
+By default, generated certificates are valid for all users or hosts.
+To generate a certificate for a specified set of principals:
+.Pp
+.Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
+.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub"
+.Pp
+Additional limitations on the validity and use of user certificates may
+be specified through certificate options.
+A certificate option may disable features of the SSH session, may be
+valid only when presented from particular source addresses or may
+force the use of a specific command.
+For a list of valid certificate options, see the documentation for the
+.Fl O
+option above.
+.Pp
+Finally, certificates may be defined with a validity lifetime.
+The
+.Fl V
+option allows specification of certificate start and end times.
+A certificate that is presented at a time outside this range will not be
+considered valid.
+By default, certificates have a maximum validity interval.
+.Pp
+For certificates to be used for user or host authentication, the CA
+public key must be trusted by
+.Xr sshd 8
+or
+.Xr ssh 1 .
+Please refer to those manual pages for details.
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.ssh/identity
+Contains the protocol version 1 RSA authentication identity of the user.
+This file should not be readable by anyone but the user.
+It is possible to
+specify a passphrase when generating the key; that passphrase will be
+used to encrypt the private part of this file using 3DES.
+This file is not automatically accessed by
+.Nm
+but it is offered as the default file for the private key.
+.Xr ssh 1
+will read this file when a login attempt is made.
+.Pp
+.It Pa ~/.ssh/identity.pub
+Contains the protocol version 1 RSA public key for authentication.
+The contents of this file should be added to
+.Pa ~/.ssh/authorized_keys
+on all machines
+where the user wishes to log in using RSA authentication.
+There is no need to keep the contents of this file secret.
+.Pp
+.It Pa ~/.ssh/id_dsa
+.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_rsa
+Contains the protocol version 2 DSA, ECDSA or RSA authentication identity of the user.
+This file should not be readable by anyone but the user.
+It is possible to
+specify a passphrase when generating the key; that passphrase will be
+used to encrypt the private part of this file using 128-bit AES.
+This file is not automatically accessed by
+.Nm
+but it is offered as the default file for the private key.
+.Xr ssh 1
+will read this file when a login attempt is made.
+.Pp
+.It Pa ~/.ssh/id_dsa.pub
+.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_rsa.pub
+Contains the protocol version 2 DSA, ECDSA or RSA public key for authentication.
+The contents of this file should be added to
+.Pa ~/.ssh/authorized_keys
+on all machines
+where the user wishes to log in using public key authentication.
+There is no need to keep the contents of this file secret.
+.Pp
+.It Pa /etc/moduli
+Contains Diffie-Hellman groups used for DH-GEX.
+The file format is described in
+.Xr moduli 5 .
+.El
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-vulnkey 1 ,
+.Xr moduli 5 ,
+.Xr sshd 8
+.Rs
+.%R RFC 4716
+.%T "The Secure Shell (SSH) Public Key File Format"
+.%D 2006
+.Re
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/openbsd-docs.patch/ssh.1 b/.pc/openbsd-docs.patch/ssh.1
new file mode 100644 (file)
index 0000000..e085d15
--- /dev/null
@@ -0,0 +1,1498 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh.1,v 1.320 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH 1
+.Os
+.Sh NAME
+.Nm ssh
+.Nd OpenSSH SSH client (remote login program)
+.Sh SYNOPSIS
+.Nm ssh
+.Bk -words
+.Op Fl 1246AaCfgKkMNnqsTtVvXxYy
+.Op Fl b Ar bind_address
+.Op Fl c Ar cipher_spec
+.Op Fl D Oo Ar bind_address : Oc Ns Ar port
+.Op Fl e Ar escape_char
+.Op Fl F Ar configfile
+.Op Fl I Ar pkcs11
+.Op Fl i Ar identity_file
+.Op Fl L Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl l Ar login_name
+.Op Fl m Ar mac_spec
+.Op Fl O Ar ctl_cmd
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Op Fl R Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl S Ar ctl_path
+.Op Fl W Ar host : Ns Ar port
+.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
+.Oo Ar user Ns @ Oc Ns Ar hostname
+.Op Ar command
+.Ek
+.Sh DESCRIPTION
+.Nm
+(SSH client) is a program for logging into a remote machine and for
+executing commands on a remote machine.
+It is intended to replace rlogin and rsh,
+and provide secure encrypted communications between
+two untrusted hosts over an insecure network.
+X11 connections and arbitrary TCP ports
+can also be forwarded over the secure channel.
+.Pp
+.Nm
+connects and logs into the specified
+.Ar hostname
+(with optional
+.Ar user
+name).
+The user must prove
+his/her identity to the remote machine using one of several methods
+depending on the protocol version used (see below).
+.Pp
+If
+.Ar command
+is specified,
+it is executed on the remote host instead of a login shell.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 1
+Forces
+.Nm
+to try protocol version 1 only.
+.It Fl 2
+Forces
+.Nm
+to try protocol version 2 only.
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl A
+Enables forwarding of the authentication agent connection.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's
+.Ux Ns -domain
+socket) can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Fl a
+Disables forwarding of the authentication agent connection.
+.It Fl b Ar bind_address
+Use
+.Ar bind_address
+on the local machine as the source address
+of the connection.
+Only useful on systems with more than one address.
+.It Fl C
+Requests compression of all data (including stdin, stdout, stderr, and
+data for forwarded X11 and TCP connections).
+The compression algorithm is the same used by
+.Xr gzip 1 ,
+and the
+.Dq level
+can be controlled by the
+.Cm CompressionLevel
+option for protocol version 1.
+Compression is desirable on modem lines and other
+slow connections, but will only slow down things on fast networks.
+The default value can be set on a host-by-host basis in the
+configuration files; see the
+.Cm Compression
+option.
+.It Fl c Ar cipher_spec
+Selects the cipher specification for encrypting the session.
+.Pp
+Protocol version 1 allows specification of a single cipher.
+The supported values are
+.Dq 3des ,
+.Dq blowfish ,
+and
+.Dq des .
+.Ar 3des
+(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
+It is believed to be secure.
+.Ar blowfish
+is a fast block cipher; it appears very secure and is much faster than
+.Ar 3des .
+.Ar des
+is only supported in the
+.Nm
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.Pp
+For protocol version 2,
+.Ar cipher_spec
+is a comma-separated list of ciphers
+listed in order of preference.
+See the
+.Cm Ciphers
+keyword in
+.Xr ssh_config 5
+for more information.
+.It Fl D Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port
+.Sm on
+.Xc
+Specifies a local
+.Dq dynamic
+application-level port forwarding.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Nm
+will act as a SOCKS server.
+Only root can forward privileged ports.
+Dynamic port forwardings can also be specified in the configuration file.
+.Pp
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl e Ar escape_char
+Sets the escape character for sessions with a pty (default:
+.Ql ~ ) .
+The escape character is only recognized at the beginning of a line.
+The escape character followed by a dot
+.Pq Ql \&.
+closes the connection;
+followed by control-Z suspends the connection;
+and followed by itself sends the escape character once.
+Setting the character to
+.Dq none
+disables any escapes and makes the session fully transparent.
+.It Fl F Ar configfile
+Specifies an alternative per-user configuration file.
+If a configuration file is given on the command line,
+the system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+will be ignored.
+The default for the per-user configuration file is
+.Pa ~/.ssh/config .
+.It Fl f
+Requests
+.Nm
+to go to background just before command execution.
+This is useful if
+.Nm
+is going to ask for passwords or passphrases, but the user
+wants it in the background.
+This implies
+.Fl n .
+The recommended way to start X11 programs at a remote site is with
+something like
+.Ic ssh -f host xterm .
+.Pp
+If the
+.Cm ExitOnForwardFailure
+configuration option is set to
+.Dq yes ,
+then a client started with
+.Fl f
+will wait for all remote port forwards to be successfully established
+before placing itself in the background.
+.It Fl g
+Allows remote hosts to connect to local forwarded ports.
+.It Fl I Ar pkcs11
+Specify the PKCS#11 shared library
+.Nm
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Fl i Ar identity_file
+Selects a file from which the identity (private key) for
+public key authentication is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Identity files may also be specified on
+a per-host basis in the configuration file.
+It is possible to have multiple
+.Fl i
+options (and multiple identities specified in
+configuration files).
+.Nm
+will also try to load certificate information from the filename obtained
+by appending
+.Pa -cert.pub
+to identity filenames.
+.It Fl K
+Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI
+credentials to the server.
+.It Fl k
+Disables forwarding (delegation) of GSSAPI credentials to the server.
+.It Fl L Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the local (client) host is to be
+forwarded to the given host and port on the remote side.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the remote machine.
+Port forwardings can also be specified in the configuration file.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl l Ar login_name
+Specifies the user to log in as on the remote machine.
+This also may be specified on a per-host basis in the configuration file.
+.It Fl M
+Places the
+.Nm
+client into
+.Dq master
+mode for connection sharing.
+Multiple
+.Fl M
+options places
+.Nm
+into
+.Dq master
+mode with confirmation required before slave connections are accepted.
+Refer to the description of
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl m Ar mac_spec
+Additionally, for protocol version 2 a comma-separated list of MAC
+(message authentication code) algorithms can
+be specified in order of preference.
+See the
+.Cm MACs
+keyword for more information.
+.It Fl N
+Do not execute a remote command.
+This is useful for just forwarding ports
+(protocol version 2 only).
+.It Fl n
+Redirects stdin from
+.Pa /dev/null
+(actually, prevents reading from stdin).
+This must be used when
+.Nm
+is run in the background.
+A common trick is to use this to run X11 programs on a remote machine.
+For example,
+.Ic ssh -n shadows.cs.hut.fi emacs &
+will start an emacs on shadows.cs.hut.fi, and the X11
+connection will be automatically forwarded over an encrypted channel.
+The
+.Nm
+program will be put in the background.
+(This does not work if
+.Nm
+needs to ask for a password or passphrase; see also the
+.Fl f
+option.)
+.It Fl O Ar ctl_cmd
+Control an active connection multiplexing master process.
+When the
+.Fl O
+option is specified, the
+.Ar ctl_cmd
+argument is interpreted and passed to the master process.
+Valid commands are:
+.Dq check
+(check that the master process is running),
+.Dq forward
+(request forwardings without command execution),
+.Dq exit
+(request the master to exit), and
+.Dq stop
+(request the master to stop accepting further multiplexing requests).
+.It Fl o Ar option
+Can be used to give options in the format used in the configuration file.
+This is useful for specifying options for which there is no separate
+command-line flag.
+For full details of the options listed below, and their possible values, see
+.Xr ssh_config 5 .
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It AddressFamily
+.It BatchMode
+.It BindAddress
+.It ChallengeResponseAuthentication
+.It CheckHostIP
+.It Cipher
+.It Ciphers
+.It ClearAllForwardings
+.It Compression
+.It CompressionLevel
+.It ConnectionAttempts
+.It ConnectTimeout
+.It ControlMaster
+.It ControlPath
+.It DynamicForward
+.It EscapeChar
+.It ExitOnForwardFailure
+.It ForwardAgent
+.It ForwardX11
+.It ForwardX11Trusted
+.It GatewayPorts
+.It GlobalKnownHostsFile
+.It GSSAPIAuthentication
+.It GSSAPIDelegateCredentials
+.It HashKnownHosts
+.It Host
+.It HostbasedAuthentication
+.It HostKeyAlgorithms
+.It HostKeyAlias
+.It HostName
+.It IdentityFile
+.It IdentitiesOnly
+.It IPQoS
+.It KbdInteractiveDevices
+.It KexAlgorithms
+.It LocalCommand
+.It LocalForward
+.It LogLevel
+.It MACs
+.It NoHostAuthenticationForLocalhost
+.It NumberOfPasswordPrompts
+.It PasswordAuthentication
+.It PermitLocalCommand
+.It PKCS11Provider
+.It Port
+.It PreferredAuthentications
+.It Protocol
+.It ProxyCommand
+.It PubkeyAuthentication
+.It RekeyLimit
+.It RemoteForward
+.It RequestTTY
+.It RhostsRSAAuthentication
+.It RSAAuthentication
+.It SendEnv
+.It ServerAliveInterval
+.It ServerAliveCountMax
+.It StrictHostKeyChecking
+.It TCPKeepAlive
+.It Tunnel
+.It TunnelDevice
+.It UsePrivilegedPort
+.It User
+.It UserKnownHostsFile
+.It VerifyHostKeyDNS
+.It VisualHostKey
+.It XAuthLocation
+.El
+.It Fl p Ar port
+Port to connect to on the remote host.
+This can be specified on a
+per-host basis in the configuration file.
+.It Fl q
+Quiet mode.
+Causes most warning and diagnostic messages to be suppressed.
+.It Fl R Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the remote (server) host is to be
+forwarded to the given host and port on the local side.
+This works by allocating a socket to listen to
+.Ar port
+on the remote side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the local machine.
+.Pp
+Port forwardings can also be specified in the configuration file.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+IPv6 addresses can be specified by enclosing the address in square braces.
+.Pp
+By default, the listening socket on the server will be bound to the loopback
+interface only.
+This may be overridden by specifying a
+.Ar bind_address .
+An empty
+.Ar bind_address ,
+or the address
+.Ql * ,
+indicates that the remote socket should listen on all interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+When used together with
+.Ic -O forward
+the allocated port will be printed to the standard output.
+.It Fl S Ar ctl_path
+Specifies the location of a control socket for connection sharing,
+or the string
+.Dq none
+to disable connection sharing.
+Refer to the description of
+.Cm ControlPath
+and
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl s
+May be used to request invocation of a subsystem on the remote system.
+Subsystems are a feature of the SSH2 protocol which facilitate the use
+of SSH as a secure transport for other applications (eg.\&
+.Xr sftp 1 ) .
+The subsystem is specified as the remote command.
+.It Fl T
+Disable pseudo-tty allocation.
+.It Fl t
+Force pseudo-tty allocation.
+This can be used to execute arbitrary
+screen-based programs on a remote machine, which can be very useful,
+e.g. when implementing menu services.
+Multiple
+.Fl t
+options force tty allocation, even if
+.Nm
+has no local tty.
+.It Fl V
+Display the version number and exit.
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in
+debugging connection, authentication, and configuration problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.It Fl W Ar host : Ns Ar port
+Requests that standard input and output on the client be forwarded to
+.Ar host
+on
+.Ar port
+over the secure channel.
+Implies
+.Fl N ,
+.Fl T ,
+.Cm ExitOnForwardFailure
+and
+.Cm ClearAllForwardings
+and works with Protocol version 2 only.
+.It Fl w Xo
+.Ar local_tun Ns Op : Ns Ar remote_tun
+.Xc
+Requests
+tunnel
+device forwarding with the specified
+.Xr tun 4
+devices between the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+See also the
+.Cm Tunnel
+and
+.Cm TunnelDevice
+directives in
+.Xr ssh_config 5 .
+If the
+.Cm Tunnel
+directive is unset, it is set to the default tunnel mode, which is
+.Dq point-to-point .
+.It Fl X
+Enables X11 forwarding.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring.
+.Pp
+For this reason, X11 forwarding is subjected to X11 SECURITY extension
+restrictions by default.
+Please refer to the
+.Nm
+.Fl Y
+option and the
+.Cm ForwardX11Trusted
+directive in
+.Xr ssh_config 5
+for more information.
+.It Fl x
+Disables X11 forwarding.
+.It Fl Y
+Enables trusted X11 forwarding.
+Trusted X11 forwardings are not subjected to the X11 SECURITY extension
+controls.
+.It Fl y
+Send log information using the
+.Xr syslog 3
+system module.
+By default this information is sent to stderr.
+.El
+.Pp
+.Nm
+may additionally obtain configuration data from
+a per-user configuration file and a system-wide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Sh AUTHENTICATION
+The OpenSSH SSH client supports SSH protocols 1 and 2.
+The default is to use protocol 2 only,
+though this can be changed via the
+.Cm Protocol
+option in
+.Xr ssh_config 5
+or the
+.Fl 1
+and
+.Fl 2
+options (see above).
+Both protocols support similar authentication methods,
+but protocol 2 is the default since
+it provides additional mechanisms for confidentiality
+(the traffic is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour)
+and integrity (hmac-md5, hmac-sha1,
+hmac-sha2-256, hmac-sha2-512,
+umac-64, hmac-ripemd160).
+Protocol 1 lacks a strong mechanism for ensuring the
+integrity of the connection.
+.Pp
+The methods available for authentication are:
+GSSAPI-based authentication,
+host-based authentication,
+public key authentication,
+challenge-response authentication,
+and password authentication.
+Authentication methods are tried in the order specified above,
+though protocol 2 has a configuration option to change the default order:
+.Cm PreferredAuthentications .
+.Pp
+Host-based authentication works as follows:
+If the machine the user logs in from is listed in
+.Pa /etc/hosts.equiv
+or
+.Pa /etc/shosts.equiv
+on the remote machine, and the user names are
+the same on both sides, or if the files
+.Pa ~/.rhosts
+or
+.Pa ~/.shosts
+exist in the user's home directory on the
+remote machine and contain a line containing the name of the client
+machine and the name of the user on that machine, the user is
+considered for login.
+Additionally, the server
+.Em must
+be able to verify the client's
+host key (see the description of
+.Pa /etc/ssh/ssh_known_hosts
+and
+.Pa ~/.ssh/known_hosts ,
+below)
+for login to be permitted.
+This authentication method closes security holes due to IP
+spoofing, DNS spoofing, and routing spoofing.
+[Note to the administrator:
+.Pa /etc/hosts.equiv ,
+.Pa ~/.rhosts ,
+and the rlogin/rsh protocol in general, are inherently insecure and should be
+disabled if security is desired.]
+.Pp
+Public key authentication works as follows:
+The scheme is based on public-key cryptography,
+using cryptosystems
+where encryption and decryption are done using separate keys,
+and it is unfeasible to derive the decryption key from the encryption key.
+The idea is that each user creates a public/private
+key pair for authentication purposes.
+The server knows the public key, and only the user knows the private key.
+.Nm
+implements public key authentication protocol automatically,
+using one of the DSA, ECDSA or RSA algorithms.
+Protocol 1 is restricted to using only RSA keys,
+but protocol 2 may use any.
+The
+.Sx HISTORY
+section of
+.Xr ssl 8
+contains a brief discussion of the DSA and RSA algorithms.
+.Pp
+The file
+.Pa ~/.ssh/authorized_keys
+lists the public keys that are permitted for logging in.
+When the user logs in, the
+.Nm
+program tells the server which key pair it would like to use for
+authentication.
+The client proves that it has access to the private key
+and the server checks that the corresponding public key
+is authorized to accept the account.
+.Pp
+The user creates his/her key pair by running
+.Xr ssh-keygen 1 .
+This stores the private key in
+.Pa ~/.ssh/identity
+(protocol 1),
+.Pa ~/.ssh/id_dsa
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa
+(protocol 2 RSA)
+and stores the public key in
+.Pa ~/.ssh/identity.pub
+(protocol 1),
+.Pa ~/.ssh/id_dsa.pub
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa.pub
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa.pub
+(protocol 2 RSA)
+in the user's home directory.
+The user should then copy the public key
+to
+.Pa ~/.ssh/authorized_keys
+in his/her home directory on the remote machine.
+The
+.Pa authorized_keys
+file corresponds to the conventional
+.Pa ~/.rhosts
+file, and has one key
+per line, though the lines can be very long.
+After this, the user can log in without giving the password.
+.Pp
+A variation on public key authentication
+is available in the form of certificate authentication:
+instead of a set of public/private keys,
+signed certificates are used.
+This has the advantage that a single trusted certification authority
+can be used in place of many public/private keys.
+See the
+.Sx CERTIFICATES
+section of
+.Xr ssh-keygen 1
+for more information.
+.Pp
+The most convenient way to use public key or certificate authentication
+may be with an authentication agent.
+See
+.Xr ssh-agent 1
+for more information.
+.Pp
+Challenge-response authentication works as follows:
+The server sends an arbitrary
+.Qq challenge
+text, and prompts for a response.
+Protocol 2 allows multiple challenges and responses;
+protocol 1 is restricted to just one challenge/response.
+Examples of challenge-response authentication include
+BSD Authentication (see
+.Xr login.conf 5 )
+and PAM (some non-OpenBSD systems).
+.Pp
+Finally, if other authentication methods fail,
+.Nm
+prompts the user for a password.
+The password is sent to the remote
+host for checking; however, since all communications are encrypted,
+the password cannot be seen by someone listening on the network.
+.Pp
+.Nm
+automatically maintains and checks a database containing
+identification for all hosts it has ever been used with.
+Host keys are stored in
+.Pa ~/.ssh/known_hosts
+in the user's home directory.
+Additionally, the file
+.Pa /etc/ssh/ssh_known_hosts
+is automatically checked for known hosts.
+Any new hosts are automatically added to the user's file.
+If a host's identification ever changes,
+.Nm
+warns about this and disables password authentication to prevent
+server spoofing or man-in-the-middle attacks,
+which could otherwise be used to circumvent the encryption.
+The
+.Cm StrictHostKeyChecking
+option can be used to control logins to machines whose
+host key is not known or has changed.
+.Pp
+When the user's identity has been accepted by the server, the server
+either executes the given command, or logs into the machine and gives
+the user a normal shell on the remote machine.
+All communication with
+the remote command or shell will be automatically encrypted.
+.Pp
+If a pseudo-terminal has been allocated (normal login session), the
+user may use the escape characters noted below.
+.Pp
+If no pseudo-tty has been allocated,
+the session is transparent and can be used to reliably transfer binary data.
+On most systems, setting the escape character to
+.Dq none
+will also make the session transparent even if a tty is used.
+.Pp
+The session terminates when the command or shell on the remote
+machine exits and all X11 and TCP connections have been closed.
+.Sh ESCAPE CHARACTERS
+When a pseudo-terminal has been requested,
+.Nm
+supports a number of functions through the use of an escape character.
+.Pp
+A single tilde character can be sent as
+.Ic ~~
+or by following the tilde by a character other than those described below.
+The escape character must always follow a newline to be interpreted as
+special.
+The escape character can be changed in configuration files using the
+.Cm EscapeChar
+configuration directive or on the command line by the
+.Fl e
+option.
+.Pp
+The supported escapes (assuming the default
+.Ql ~ )
+are:
+.Bl -tag -width Ds
+.It Cm ~.
+Disconnect.
+.It Cm ~^Z
+Background
+.Nm .
+.It Cm ~#
+List forwarded connections.
+.It Cm ~&
+Background
+.Nm
+at logout when waiting for forwarded connection / X11 sessions to terminate.
+.It Cm ~?
+Display a list of escape characters.
+.It Cm ~B
+Send a BREAK to the remote system
+(only useful for SSH protocol version 2 and if the peer supports it).
+.It Cm ~C
+Open command line.
+Currently this allows the addition of port forwardings using the
+.Fl L ,
+.Fl R
+and
+.Fl D
+options (see above).
+It also allows the cancellation of existing remote port-forwardings
+using
+.Sm off
+.Fl KR Oo Ar bind_address : Oc Ar port .
+.Sm on
+.Ic !\& Ns Ar command
+allows the user to execute a local command if the
+.Ic PermitLocalCommand
+option is enabled in
+.Xr ssh_config 5 .
+Basic help is available, using the
+.Fl h
+option.
+.It Cm ~R
+Request rekeying of the connection
+(only useful for SSH protocol version 2 and if the peer supports it).
+.El
+.Sh TCP FORWARDING
+Forwarding of arbitrary TCP connections over the secure channel can
+be specified either on the command line or in a configuration file.
+One possible application of TCP forwarding is a secure connection to a
+mail server; another is going through firewalls.
+.Pp
+In the example below, we look at encrypting communication between
+an IRC client and server, even though the IRC server does not directly
+support encrypted communications.
+This works as follows:
+the user connects to the remote host using
+.Nm ,
+specifying a port to be used to forward connections
+to the remote server.
+After that it is possible to start the service which is to be encrypted
+on the client machine,
+connecting to the same local port,
+and
+.Nm
+will encrypt and forward the connection.
+.Pp
+The following example tunnels an IRC session from client machine
+.Dq 127.0.0.1
+(localhost)
+to remote server
+.Dq server.example.com :
+.Bd -literal -offset 4n
+$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
+$ irc -c '#users' -p 1234 pinky 127.0.0.1
+.Ed
+.Pp
+This tunnels a connection to IRC server
+.Dq server.example.com ,
+joining channel
+.Dq #users ,
+nickname
+.Dq pinky ,
+using port 1234.
+It doesn't matter which port is used,
+as long as it's greater than 1023
+(remember, only root can open sockets on privileged ports)
+and doesn't conflict with any ports already in use.
+The connection is forwarded to port 6667 on the remote server,
+since that's the standard port for IRC services.
+.Pp
+The
+.Fl f
+option backgrounds
+.Nm
+and the remote command
+.Dq sleep 10
+is specified to allow an amount of time
+(10 seconds, in the example)
+to start the service which is to be tunnelled.
+If no connections are made within the time specified,
+.Nm
+will exit.
+.Sh X11 FORWARDING
+If the
+.Cm ForwardX11
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl X ,
+.Fl x ,
+and
+.Fl Y
+options above)
+and the user is using X11 (the
+.Ev DISPLAY
+environment variable is set), the connection to the X11 display is
+automatically forwarded to the remote side in such a way that any X11
+programs started from the shell (or command) will go through the
+encrypted channel, and the connection to the real X server will be made
+from the local machine.
+The user should not manually set
+.Ev DISPLAY .
+Forwarding of X11 connections can be
+configured on the command line or in configuration files.
+.Pp
+The
+.Ev DISPLAY
+value set by
+.Nm
+will point to the server machine, but with a display number greater than zero.
+This is normal, and happens because
+.Nm
+creates a
+.Dq proxy
+X server on the server machine for forwarding the
+connections over the encrypted channel.
+.Pp
+.Nm
+will also automatically set up Xauthority data on the server machine.
+For this purpose, it will generate a random authorization cookie,
+store it in Xauthority on the server, and verify that any forwarded
+connections carry this cookie and replace it by the real cookie when
+the connection is opened.
+The real authentication cookie is never
+sent to the server machine (and no cookies are sent in the plain).
+.Pp
+If the
+.Cm ForwardAgent
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl A
+and
+.Fl a
+options above) and
+the user is using an authentication agent, the connection to the agent
+is automatically forwarded to the remote side.
+.Sh VERIFYING HOST KEYS
+When connecting to a server for the first time,
+a fingerprint of the server's public key is presented to the user
+(unless the option
+.Cm StrictHostKeyChecking
+has been disabled).
+Fingerprints can be determined using
+.Xr ssh-keygen 1 :
+.Pp
+.Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
+.Pp
+If the fingerprint is already known, it can be matched
+and the key can be accepted or rejected.
+Because of the difficulty of comparing host keys
+just by looking at hex strings,
+there is also support to compare host keys visually,
+using
+.Em random art .
+By setting the
+.Cm VisualHostKey
+option to
+.Dq yes ,
+a small ASCII graphic gets displayed on every login to a server, no matter
+if the session itself is interactive or not.
+By learning the pattern a known server produces, a user can easily
+find out that the host key has changed when a completely different pattern
+is displayed.
+Because these patterns are not unambiguous however, a pattern that looks
+similar to the pattern remembered only gives a good probability that the
+host key is the same, not guaranteed proof.
+.Pp
+To get a listing of the fingerprints along with their random art for
+all known hosts, the following command line can be used:
+.Pp
+.Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts
+.Pp
+If the fingerprint is unknown,
+an alternative method of verification is available:
+SSH fingerprints verified by DNS.
+An additional resource record (RR),
+SSHFP,
+is added to a zonefile
+and the connecting client is able to match the fingerprint
+with that of the key presented.
+.Pp
+In this example, we are connecting a client to a server,
+.Dq host.example.com .
+The SSHFP resource records should first be added to the zonefile for
+host.example.com:
+.Bd -literal -offset indent
+$ ssh-keygen -r host.example.com.
+.Ed
+.Pp
+The output lines will have to be added to the zonefile.
+To check that the zone is answering fingerprint queries:
+.Pp
+.Dl $ dig -t SSHFP host.example.com
+.Pp
+Finally the client connects:
+.Bd -literal -offset indent
+$ ssh -o "VerifyHostKeyDNS ask" host.example.com
+[...]
+Matching host key fingerprint found in DNS.
+Are you sure you want to continue connecting (yes/no)?
+.Ed
+.Pp
+See the
+.Cm VerifyHostKeyDNS
+option in
+.Xr ssh_config 5
+for more information.
+.Sh SSH-BASED VIRTUAL PRIVATE NETWORKS
+.Nm
+contains support for Virtual Private Network (VPN) tunnelling
+using the
+.Xr tun 4
+network pseudo-device,
+allowing two networks to be joined securely.
+The
+.Xr sshd_config 5
+configuration option
+.Cm PermitTunnel
+controls whether the server supports this,
+and at what level (layer 2 or 3 traffic).
+.Pp
+The following example would connect client network 10.0.50.0/24
+with remote network 10.0.99.0/24 using a point-to-point connection
+from 10.1.1.1 to 10.1.1.2,
+provided that the SSH server running on the gateway to the remote network,
+at 192.168.1.15, allows it.
+.Pp
+On the client:
+.Bd -literal -offset indent
+# ssh -f -w 0:1 192.168.1.15 true
+# ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
+# route add 10.0.99.0/24 10.1.1.2
+.Ed
+.Pp
+On the server:
+.Bd -literal -offset indent
+# ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
+# route add 10.0.50.0/24 10.1.1.1
+.Ed
+.Pp
+Client access may be more finely tuned via the
+.Pa /root/.ssh/authorized_keys
+file (see below) and the
+.Cm PermitRootLogin
+server option.
+The following entry would permit connections on
+.Xr tun 4
+device 1 from user
+.Dq jane
+and on tun device 2 from user
+.Dq john ,
+if
+.Cm PermitRootLogin
+is set to
+.Dq forced-commands-only :
+.Bd -literal -offset 2n
+tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane
+tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john
+.Ed
+.Pp
+Since an SSH-based setup entails a fair amount of overhead,
+it may be more suited to temporary setups,
+such as for wireless VPNs.
+More permanent VPNs are better provided by tools such as
+.Xr ipsecctl 8
+and
+.Xr isakmpd 8 .
+.Sh ENVIRONMENT
+.Nm
+will normally set the following environment variables:
+.Bl -tag -width "SSH_ORIGINAL_COMMAND"
+.It Ev DISPLAY
+The
+.Ev DISPLAY
+variable indicates the location of the X11 server.
+It is automatically set by
+.Nm
+to point to a value of the form
+.Dq hostname:n ,
+where
+.Dq hostname
+indicates the host where the shell runs, and
+.Sq n
+is an integer \*(Ge 1.
+.Nm
+uses this special value to forward X11 connections over the secure
+channel.
+The user should normally not set
+.Ev DISPLAY
+explicitly, as that
+will render the X11 connection insecure (and will require the user to
+manually copy any required authorization cookies).
+.It Ev HOME
+Set to the path of the user's home directory.
+.It Ev LOGNAME
+Synonym for
+.Ev USER ;
+set for compatibility with systems that use this variable.
+.It Ev MAIL
+Set to the path of the user's mailbox.
+.It Ev PATH
+Set to the default
+.Ev PATH ,
+as specified when compiling
+.Nm .
+.It Ev SSH_ASKPASS
+If
+.Nm
+needs a passphrase, it will read the passphrase from the current
+terminal if it was run from a terminal.
+If
+.Nm
+does not have a terminal associated with it but
+.Ev DISPLAY
+and
+.Ev SSH_ASKPASS
+are set, it will execute the program specified by
+.Ev SSH_ASKPASS
+and open an X11 window to read the passphrase.
+This is particularly useful when calling
+.Nm
+from a
+.Pa .xsession
+or related script.
+(Note that on some machines it
+may be necessary to redirect the input from
+.Pa /dev/null
+to make this work.)
+.It Ev SSH_AUTH_SOCK
+Identifies the path of a
+.Ux Ns -domain
+socket used to communicate with the agent.
+.It Ev SSH_CONNECTION
+Identifies the client and server ends of the connection.
+The variable contains
+four space-separated values: client IP address, client port number,
+server IP address, and server port number.
+.It Ev SSH_ORIGINAL_COMMAND
+This variable contains the original command line if a forced command
+is executed.
+It can be used to extract the original arguments.
+.It Ev SSH_TTY
+This is set to the name of the tty (path to the device) associated
+with the current shell or command.
+If the current session has no tty,
+this variable is not set.
+.It Ev TZ
+This variable is set to indicate the present time zone if it
+was set when the daemon was started (i.e. the daemon passes the value
+on to new connections).
+.It Ev USER
+Set to the name of the user logging in.
+.El
+.Pp
+Additionally,
+.Nm
+reads
+.Pa ~/.ssh/environment ,
+and adds lines of the format
+.Dq VARNAME=value
+to the environment if the file exists and users are allowed to
+change their environment.
+For more information, see the
+.Cm PermitUserEnvironment
+option in
+.Xr sshd_config 5 .
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.rhosts
+This file is used for host-based authentication (see above).
+On some machines this file may need to be
+world-readable if the user's home directory is on an NFS partition,
+because
+.Xr sshd 8
+reads it as root.
+Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else.
+The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.Pp
+.It Pa ~/.shosts
+This file is used in exactly the same way as
+.Pa .rhosts ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa ~/.ssh/
+This directory is the default location for all user-specific configuration
+and authentication information.
+There is no general requirement to keep the entire contents of this directory
+secret, but the recommended permissions are read/write/execute for the user,
+and not accessible by others.
+.Pp
+.It Pa ~/.ssh/authorized_keys
+Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as
+this user.
+The format of this file is described in the
+.Xr sshd 8
+manual page.
+This file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.Pp
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+It may be group-writable provided that the group in question contains only
+the user.
+.Pp
+.It Pa ~/.ssh/environment
+Contains additional definitions for environment variables; see
+.Sx ENVIRONMENT ,
+above.
+.Pp
+.It Pa ~/.ssh/identity
+.It Pa ~/.ssh/id_dsa
+.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_rsa
+Contains the private key for authentication.
+These files
+contain sensitive data and should be readable by the user but not
+accessible by others (read/write/execute).
+.Nm
+will simply ignore a private key file if it is accessible by others.
+It is possible to specify a passphrase when
+generating the key which will be used to encrypt the
+sensitive part of this file using 3DES.
+.Pp
+.It Pa ~/.ssh/identity.pub
+.It Pa ~/.ssh/id_dsa.pub
+.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_rsa.pub
+Contains the public key for authentication.
+These files are not
+sensitive and can (but need not) be readable by anyone.
+.Pp
+.It Pa ~/.ssh/known_hosts
+Contains a list of host keys for all hosts the user has logged into
+that are not already in the systemwide list of known host keys.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa ~/.ssh/rc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is
+started.
+See the
+.Xr sshd 8
+manual page for more information.
+.Pp
+.It Pa /etc/hosts.equiv
+This file is for host-based authentication (see above).
+It should only be writable by root.
+.Pp
+.It Pa /etc/shosts.equiv
+This file is used in exactly the same way as
+.Pa hosts.equiv ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Pp
+.It Pa /etc/ssh/ssh_host_key
+.It Pa /etc/ssh/ssh_host_dsa_key
+.It Pa /etc/ssh/ssh_host_ecdsa_key
+.It Pa /etc/ssh/ssh_host_rsa_key
+These three files contain the private parts of the host keys
+and are used for host-based authentication.
+If protocol version 1 is used,
+.Nm
+must be setuid root, since the host key is readable only by root.
+For protocol version 2,
+.Nm
+uses
+.Xr ssh-keysign 8
+to access the host keys,
+eliminating the requirement that
+.Nm
+be setuid root when host-based authentication is used.
+By default
+.Nm
+is not setuid root.
+.Pp
+.It Pa /etc/ssh/ssh_known_hosts
+Systemwide list of known host keys.
+This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization.
+It should be world-readable.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa /etc/ssh/sshrc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is started.
+See the
+.Xr sshd 8
+manual page for more information.
+.El
+.Sh EXIT STATUS
+.Nm
+exits with the exit status of the remote command or with 255
+if an error occurred.
+.Sh SEE ALSO
+.Xr scp 1 ,
+.Xr sftp 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-keygen 1 ,
+.Xr ssh-keyscan 1 ,
+.Xr ssh-vulnkey 1 ,
+.Xr tun 4 ,
+.Xr hosts.equiv 5 ,
+.Xr ssh_config 5 ,
+.Xr ssh-keysign 8 ,
+.Xr sshd 8
+.Rs
+.%R RFC 4250
+.%T "The Secure Shell (SSH) Protocol Assigned Numbers"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4251
+.%T "The Secure Shell (SSH) Protocol Architecture"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4252
+.%T "The Secure Shell (SSH) Authentication Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4253
+.%T "The Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4254
+.%T "The Secure Shell (SSH) Connection Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4255
+.%T "Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4256
+.%T "Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4335
+.%T "The Secure Shell (SSH) Session Channel Break Extension"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4344
+.%T "The Secure Shell (SSH) Transport Layer Encryption Modes"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4345
+.%T "Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4419
+.%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4716
+.%T "The Secure Shell (SSH) Public Key File Format"
+.%D 2006
+.Re
+.Rs
+.%R RFC 5656
+.%T "Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer"
+.%D 2009
+.Re
+.Rs
+.%T "Hash Visualization: a New Technique to improve Real-World Security"
+.%A A. Perrig
+.%A D. Song
+.%D 1999
+.%O "International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)"
+.Re
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/openbsd-docs.patch/sshd.8 b/.pc/openbsd-docs.patch/sshd.8
new file mode 100644 (file)
index 0000000..b08c8fa
--- /dev/null
@@ -0,0 +1,980 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd.8,v 1.263 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD 8
+.Os
+.Sh NAME
+.Nm sshd
+.Nd OpenSSH SSH daemon
+.Sh SYNOPSIS
+.Nm sshd
+.Bk -words
+.Op Fl 46DdeiqTt
+.Op Fl b Ar bits
+.Op Fl C Ar connection_spec
+.Op Fl c Ar host_certificate_file
+.Op Fl f Ar config_file
+.Op Fl g Ar login_grace_time
+.Op Fl h Ar host_key_file
+.Op Fl k Ar key_gen_time
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Op Fl u Ar len
+.Ek
+.Sh DESCRIPTION
+.Nm
+(OpenSSH Daemon) is the daemon program for
+.Xr ssh 1 .
+Together these programs replace
+.Xr rlogin 1
+and
+.Xr rsh 1 ,
+and provide secure encrypted communications between two untrusted hosts
+over an insecure network.
+.Pp
+.Nm
+listens for connections from clients.
+It is normally started at boot from
+.Pa /etc/rc .
+It forks a new
+daemon for each incoming connection.
+The forked daemons handle
+key exchange, encryption, authentication, command execution,
+and data exchange.
+.Pp
+.Nm
+can be configured using command-line options or a configuration file
+(by default
+.Xr sshd_config 5 ) ;
+command-line options override values specified in the
+configuration file.
+.Nm
+rereads its configuration file when it receives a hangup signal,
+.Dv SIGHUP ,
+by executing itself with the name and options it was started with, e.g.\&
+.Pa /usr/sbin/sshd .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl b Ar bits
+Specifies the number of bits in the ephemeral protocol version 1
+server key (default 1024).
+.It Fl C Ar connection_spec
+Specify the connection parameters to use for the
+.Fl T
+extended test mode.
+If provided, any
+.Cm Match
+directives in the configuration file
+that would apply to the specified user, host, and address will be set before
+the configuration is written to standard output.
+The connection parameters are supplied as keyword=value pairs.
+The keywords are
+.Dq user ,
+.Dq host ,
+and
+.Dq addr .
+All are required and may be supplied in any order, either with multiple
+.Fl C
+options or as a comma-separated list.
+.It Fl c Ar host_certificate_file
+Specifies a path to a certificate file to identify
+.Nm
+during key exchange.
+The certificate file must match a host key file specified using the
+.Fl h
+option or the
+.Cm HostKey
+configuration directive.
+.It Fl D
+When this option is specified,
+.Nm
+will not detach and does not become a daemon.
+This allows easy monitoring of
+.Nm sshd .
+.It Fl d
+Debug mode.
+The server sends verbose debug output to standard error,
+and does not put itself in the background.
+The server also will not fork and will only process one connection.
+This option is only intended for debugging for the server.
+Multiple
+.Fl d
+options increase the debugging level.
+Maximum is 3.
+.It Fl e
+When this option is specified,
+.Nm
+will send the output to the standard error instead of the system log.
+.It Fl f Ar config_file
+Specifies the name of the configuration file.
+The default is
+.Pa /etc/ssh/sshd_config .
+.Nm
+refuses to start if there is no configuration file.
+.It Fl g Ar login_grace_time
+Gives the grace time for clients to authenticate themselves (default
+120 seconds).
+If the client fails to authenticate the user within
+this many seconds, the server disconnects and exits.
+A value of zero indicates no limit.
+.It Fl h Ar host_key_file
+Specifies a file from which a host key is read.
+This option must be given if
+.Nm
+is not run as root (as the normal
+host key files are normally not readable by anyone but root).
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+It is possible to have multiple host key files for
+the different protocol versions and host key algorithms.
+.It Fl i
+Specifies that
+.Nm
+is being run from
+.Xr inetd 8 .
+.Nm
+is normally not run
+from inetd because it needs to generate the server key before it can
+respond to the client, and this may take tens of seconds.
+Clients would have to wait too long if the key was regenerated every time.
+However, with small key sizes (e.g. 512) using
+.Nm
+from inetd may
+be feasible.
+.It Fl k Ar key_gen_time
+Specifies how often the ephemeral protocol version 1 server key is
+regenerated (default 3600 seconds, or one hour).
+The motivation for regenerating the key fairly
+often is that the key is not stored anywhere, and after about an hour
+it becomes impossible to recover the key for decrypting intercepted
+communications even if the machine is cracked into or physically
+seized.
+A value of zero indicates that the key will never be regenerated.
+.It Fl o Ar option
+Can be used to give options in the format used in the configuration file.
+This is useful for specifying options for which there is no separate
+command-line flag.
+For full details of the options, and their values, see
+.Xr sshd_config 5 .
+.It Fl p Ar port
+Specifies the port on which the server listens for connections
+(default 22).
+Multiple port options are permitted.
+Ports specified in the configuration file with the
+.Cm Port
+option are ignored when a command-line port is specified.
+Ports specified using the
+.Cm ListenAddress
+option override command-line ports.
+.It Fl q
+Quiet mode.
+Nothing is sent to the system log.
+Normally the beginning,
+authentication, and termination of each connection is logged.
+.It Fl T
+Extended test mode.
+Check the validity of the configuration file, output the effective configuration
+to stdout and then exit.
+Optionally,
+.Cm Match
+rules may be applied by specifying the connection parameters using one or more
+.Fl C
+options.
+.It Fl t
+Test mode.
+Only check the validity of the configuration file and sanity of the keys.
+This is useful for updating
+.Nm
+reliably as configuration options may change.
+.It Fl u Ar len
+This option is used to specify the size of the field
+in the
+.Li utmp
+structure that holds the remote host name.
+If the resolved host name is longer than
+.Ar len ,
+the dotted decimal value will be used instead.
+This allows hosts with very long host names that
+overflow this field to still be uniquely identified.
+Specifying
+.Fl u0
+indicates that only dotted decimal addresses
+should be put into the
+.Pa utmp
+file.
+.Fl u0
+may also be used to prevent
+.Nm
+from making DNS requests unless the authentication
+mechanism or configuration requires it.
+Authentication mechanisms that may require DNS include
+.Cm RhostsRSAAuthentication ,
+.Cm HostbasedAuthentication ,
+and using a
+.Cm from="pattern-list"
+option in a key file.
+Configuration options that require DNS include using a
+USER@HOST pattern in
+.Cm AllowUsers
+or
+.Cm DenyUsers .
+.El
+.Sh AUTHENTICATION
+The OpenSSH SSH daemon supports SSH protocols 1 and 2.
+The default is to use protocol 2 only,
+though this can be changed via the
+.Cm Protocol
+option in
+.Xr sshd_config 5 .
+Protocol 2 supports DSA, ECDSA and RSA keys;
+protocol 1 only supports RSA keys.
+For both protocols,
+each host has a host-specific key,
+normally 2048 bits,
+used to identify the host.
+.Pp
+Forward security for protocol 1 is provided through
+an additional server key,
+normally 768 bits,
+generated when the server starts.
+This key is normally regenerated every hour if it has been used, and
+is never stored on disk.
+Whenever a client connects, the daemon responds with its public
+host and server keys.
+The client compares the
+RSA host key against its own database to verify that it has not changed.
+The client then generates a 256-bit random number.
+It encrypts this
+random number using both the host key and the server key, and sends
+the encrypted number to the server.
+Both sides then use this
+random number as a session key which is used to encrypt all further
+communications in the session.
+The rest of the session is encrypted
+using a conventional cipher, currently Blowfish or 3DES, with 3DES
+being used by default.
+The client selects the encryption algorithm
+to use from those offered by the server.
+.Pp
+For protocol 2,
+forward security is provided through a Diffie-Hellman key agreement.
+This key agreement results in a shared session key.
+The rest of the session is encrypted using a symmetric cipher, currently
+128-bit AES, Blowfish, 3DES, CAST128, Arcfour, 192-bit AES, or 256-bit AES.
+The client selects the encryption algorithm
+to use from those offered by the server.
+Additionally, session integrity is provided
+through a cryptographic message authentication code
+(hmac-md5, hmac-sha1, umac-64, hmac-ripemd160,
+hmac-sha2-256 or hmac-sha2-512).
+.Pp
+Finally, the server and the client enter an authentication dialog.
+The client tries to authenticate itself using
+host-based authentication,
+public key authentication,
+challenge-response authentication,
+or password authentication.
+.Pp
+Regardless of the authentication type, the account is checked to
+ensure that it is accessible.  An account is not accessible if it is
+locked, listed in
+.Cm DenyUsers
+or its group is listed in
+.Cm DenyGroups
+\&.  The definition of a locked account is system dependant. Some platforms
+have their own account database (eg AIX) and some modify the passwd field (
+.Ql \&*LK\&*
+on Solaris and UnixWare,
+.Ql \&*
+on HP-UX, containing
+.Ql Nologin
+on Tru64,
+a leading
+.Ql \&*LOCKED\&*
+on FreeBSD and a leading
+.Ql \&!
+on most Linuxes).
+If there is a requirement to disable password authentication
+for the account while allowing still public-key, then the passwd field
+should be set to something other than these values (eg
+.Ql NP
+or
+.Ql \&*NP\&*
+).
+.Pp
+If the client successfully authenticates itself, a dialog for
+preparing the session is entered.
+At this time the client may request
+things like allocating a pseudo-tty, forwarding X11 connections,
+forwarding TCP connections, or forwarding the authentication agent
+connection over the secure channel.
+.Pp
+After this, the client either requests a shell or execution of a command.
+The sides then enter session mode.
+In this mode, either side may send
+data at any time, and such data is forwarded to/from the shell or
+command on the server side, and the user terminal in the client side.
+.Pp
+When the user program terminates and all forwarded X11 and other
+connections have been closed, the server sends command exit status to
+the client, and both sides exit.
+.Sh LOGIN PROCESS
+When a user successfully logs in,
+.Nm
+does the following:
+.Bl -enum -offset indent
+.It
+If the login is on a tty, and no command has been specified,
+prints last login time and
+.Pa /etc/motd
+(unless prevented in the configuration file or by
+.Pa ~/.hushlogin ;
+see the
+.Sx FILES
+section).
+.It
+If the login is on a tty, records login time.
+.It
+Checks
+.Pa /etc/nologin ;
+if it exists, prints contents and quits
+(unless root).
+.It
+Changes to run with normal user privileges.
+.It
+Sets up basic environment.
+.It
+Reads the file
+.Pa ~/.ssh/environment ,
+if it exists, and users are allowed to change their environment.
+See the
+.Cm PermitUserEnvironment
+option in
+.Xr sshd_config 5 .
+.It
+Changes to user's home directory.
+.It
+If
+.Pa ~/.ssh/rc
+exists, runs it; else if
+.Pa /etc/ssh/sshrc
+exists, runs
+it; otherwise runs xauth.
+The
+.Dq rc
+files are given the X11
+authentication protocol and cookie in standard input.
+See
+.Sx SSHRC ,
+below.
+.It
+Runs user's shell or command.
+.El
+.Sh SSHRC
+If the file
+.Pa ~/.ssh/rc
+exists,
+.Xr sh 1
+runs it after reading the
+environment files but before starting the user's shell or command.
+It must not produce any output on stdout; stderr must be used
+instead.
+If X11 forwarding is in use, it will receive the "proto cookie" pair in
+its standard input (and
+.Ev DISPLAY
+in its environment).
+The script must call
+.Xr xauth 1
+because
+.Nm
+will not run xauth automatically to add X11 cookies.
+.Pp
+The primary purpose of this file is to run any initialization routines
+which may be needed before the user's home directory becomes
+accessible; AFS is a particular example of such an environment.
+.Pp
+This file will probably contain some initialization code followed by
+something similar to:
+.Bd -literal -offset 3n
+if read proto cookie && [ -n "$DISPLAY" ]; then
+       if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then
+               # X11UseLocalhost=yes
+               echo add unix:`echo $DISPLAY |
+                   cut -c11-` $proto $cookie
+       else
+               # X11UseLocalhost=no
+               echo add $DISPLAY $proto $cookie
+       fi | xauth -q -
+fi
+.Ed
+.Pp
+If this file does not exist,
+.Pa /etc/ssh/sshrc
+is run, and if that
+does not exist either, xauth is used to add the cookie.
+.Sh AUTHORIZED_KEYS FILE FORMAT
+.Cm AuthorizedKeysFile
+specifies the files containing public keys for
+public key authentication;
+if none is specified, the default is
+.Pa ~/.ssh/authorized_keys
+and
+.Pa ~/.ssh/authorized_keys2 .
+Each line of the file contains one
+key (empty lines and lines starting with a
+.Ql #
+are ignored as
+comments).
+Protocol 1 public keys consist of the following space-separated fields:
+options, bits, exponent, modulus, comment.
+Protocol 2 public key consist of:
+options, keytype, base64-encoded key, comment.
+The options field is optional;
+its presence is determined by whether the line starts
+with a number or not (the options field never starts with a number).
+The bits, exponent, modulus, and comment fields give the RSA key for
+protocol version 1; the
+comment field is not used for anything (but may be convenient for the
+user to identify the key).
+For protocol version 2 the keytype is
+.Dq ecdsa-sha2-nistp256 ,
+.Dq ecdsa-sha2-nistp384 ,
+.Dq ecdsa-sha2-nistp521 ,
+.Dq ssh-dss
+or
+.Dq ssh-rsa .
+.Pp
+Note that lines in this file are usually several hundred bytes long
+(because of the size of the public key encoding) up to a limit of
+8 kilobytes, which permits DSA keys up to 8 kilobits and RSA
+keys up to 16 kilobits.
+You don't want to type them in; instead, copy the
+.Pa identity.pub ,
+.Pa id_dsa.pub ,
+.Pa id_ecdsa.pub ,
+or the
+.Pa id_rsa.pub
+file and edit it.
+.Pp
+.Nm
+enforces a minimum RSA key modulus size for protocol 1
+and protocol 2 keys of 768 bits.
+.Pp
+The options (if present) consist of comma-separated option
+specifications.
+No spaces are permitted, except within double quotes.
+The following option specifications are supported (note
+that option keywords are case-insensitive):
+.Bl -tag -width Ds
+.It Cm cert-authority
+Specifies that the listed key is a certification authority (CA) that is
+trusted to validate signed certificates for user authentication.
+.Pp
+Certificates may encode access restrictions similar to these key options.
+If both certificate restrictions and key options are present, the most
+restrictive union of the two is applied.
+.It Cm command="command"
+Specifies that the command is executed whenever this key is used for
+authentication.
+The command supplied by the user (if any) is ignored.
+The command is run on a pty if the client requests a pty;
+otherwise it is run without a tty.
+If an 8-bit clean channel is required,
+one must not request a pty or should specify
+.Cm no-pty .
+A quote may be included in the command by quoting it with a backslash.
+This option might be useful
+to restrict certain public keys to perform just a specific operation.
+An example might be a key that permits remote backups but nothing else.
+Note that the client may specify TCP and/or X11
+forwarding unless they are explicitly prohibited.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Note that this option applies to shell, command or subsystem execution.
+Also note that this command may be superseded by either a
+.Xr sshd_config 5
+.Cm ForceCommand
+directive or a command embedded in a certificate.
+.It Cm environment="NAME=value"
+Specifies that the string is to be added to the environment when
+logging in using this key.
+Environment variables set this way
+override other default environment values.
+Multiple options of this type are permitted.
+Environment processing is disabled by default and is
+controlled via the
+.Cm PermitUserEnvironment
+option.
+This option is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm from="pattern-list"
+Specifies that in addition to public key authentication, either the canonical
+name of the remote host or its IP address must be present in the
+comma-separated list of patterns.
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.Pp
+In addition to the wildcard matching that may be applied to hostnames or
+addresses, a
+.Cm from
+stanza may match IP addresses using CIDR address/masklen notation.
+.Pp
+The purpose of this option is to optionally increase security: public key
+authentication by itself does not trust the network or name servers or
+anything (but the key); however, if somebody somehow steals the key, the key
+permits an intruder to log in from anywhere in the world.
+This additional option makes using a stolen key more difficult (name
+servers and/or routers would have to be compromised in addition to
+just the key).
+.It Cm no-agent-forwarding
+Forbids authentication agent forwarding when this key is used for
+authentication.
+.It Cm no-port-forwarding
+Forbids TCP forwarding when this key is used for authentication.
+Any port forward requests by the client will return an error.
+This might be used, e.g. in connection with the
+.Cm command
+option.
+.It Cm no-pty
+Prevents tty allocation (a request to allocate a pty will fail).
+.It Cm no-user-rc
+Disables execution of
+.Pa ~/.ssh/rc .
+.It Cm no-X11-forwarding
+Forbids X11 forwarding when this key is used for authentication.
+Any X11 forward requests by the client will return an error.
+.It Cm permitopen="host:port"
+Limit local
+.Li ``ssh -L''
+port forwarding such that it may only connect to the specified host and
+port.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Multiple
+.Cm permitopen
+options may be applied separated by commas.
+No pattern matching is performed on the specified hostnames,
+they must be literal domains or addresses.
+.It Cm principals="principals"
+On a
+.Cm cert-authority
+line, specifies allowed principals for certificate authentication as a
+comma-separated list.
+At least one name from the list must appear in the certificate's
+list of principals for the certificate to be accepted.
+This option is ignored for keys that are not marked as trusted certificate
+signers using the
+.Cm cert-authority
+option.
+.It Cm tunnel="n"
+Force a
+.Xr tun 4
+device on the server.
+Without this option, the next available device will be used if
+the client requests a tunnel.
+.El
+.Pp
+An example authorized_keys file:
+.Bd -literal -offset 3n
+# Comments allowed at start of line
+ssh-rsa AAAAB3Nza...LiPk== user@example.net
+from="*.sales.example.net,!pc.sales.example.net" ssh-rsa
+AAAAB2...19Q== john@example.net
+command="dump /home",no-pty,no-port-forwarding ssh-dss
+AAAAC3...51R== example.net
+permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss
+AAAAB5...21S==
+tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...==
+jane@example.net
+.Ed
+.Sh SSH_KNOWN_HOSTS FILE FORMAT
+The
+.Pa /etc/ssh/ssh_known_hosts
+and
+.Pa ~/.ssh/known_hosts
+files contain host public keys for all known hosts.
+The global file should
+be prepared by the administrator (optional), and the per-user file is
+maintained automatically: whenever the user connects from an unknown host,
+its key is added to the per-user file.
+.Pp
+Each line in these files contains the following fields: markers (optional),
+hostnames, bits, exponent, modulus, comment.
+The fields are separated by spaces.
+.Pp
+The marker is optional, but if it is present then it must be one of
+.Dq @cert-authority ,
+to indicate that the line contains a certification authority (CA) key,
+or
+.Dq @revoked ,
+to indicate that the key contained on the line is revoked and must not ever
+be accepted.
+Only one marker should be used on a key line.
+.Pp
+Hostnames is a comma-separated list of patterns
+.Pf ( Ql *
+and
+.Ql \&?
+act as
+wildcards); each pattern in turn is matched against the canonical host
+name (when authenticating a client) or against the user-supplied
+name (when authenticating a server).
+A pattern may also be preceded by
+.Ql \&!
+to indicate negation: if the host name matches a negated
+pattern, it is not accepted (by that line) even if it matched another
+pattern on the line.
+A hostname or address may optionally be enclosed within
+.Ql \&[
+and
+.Ql \&]
+brackets then followed by
+.Ql \&:
+and a non-standard port number.
+.Pp
+Alternately, hostnames may be stored in a hashed form which hides host names
+and addresses should the file's contents be disclosed.
+Hashed hostnames start with a
+.Ql |
+character.
+Only one hashed hostname may appear on a single line and none of the above
+negation or wildcard operators may be applied.
+.Pp
+Bits, exponent, and modulus are taken directly from the RSA host key; they
+can be obtained, for example, from
+.Pa /etc/ssh/ssh_host_key.pub .
+The optional comment field continues to the end of the line, and is not used.
+.Pp
+Lines starting with
+.Ql #
+and empty lines are ignored as comments.
+.Pp
+When performing host authentication, authentication is accepted if any
+matching line has the proper key; either one that matches exactly or,
+if the server has presented a certificate for authentication, the key
+of the certification authority that signed the certificate.
+For a key to be trusted as a certification authority, it must use the
+.Dq @cert-authority
+marker described above.
+.Pp
+The known hosts file also provides a facility to mark keys as revoked,
+for example when it is known that the associated private key has been
+stolen.
+Revoked keys are specified by including the
+.Dq @revoked
+marker at the beginning of the key line, and are never accepted for
+authentication or as certification authorities, but instead will
+produce a warning from
+.Xr ssh 1
+when they are encountered.
+.Pp
+It is permissible (but not
+recommended) to have several lines or different host keys for the same
+names.
+This will inevitably happen when short forms of host names
+from different domains are put in the file.
+It is possible
+that the files contain conflicting information; authentication is
+accepted if valid information can be found from either file.
+.Pp
+Note that the lines in these files are typically hundreds of characters
+long, and you definitely don't want to type in the host keys by hand.
+Rather, generate them by a script,
+.Xr ssh-keyscan 1
+or by taking
+.Pa /etc/ssh/ssh_host_key.pub
+and adding the host names at the front.
+.Xr ssh-keygen 1
+also offers some basic automated editing for
+.Pa ~/.ssh/known_hosts
+including removing hosts matching a host name and converting all host
+names to their hashed representations.
+.Pp
+An example ssh_known_hosts file:
+.Bd -literal -offset 3n
+# Comments allowed at start of line
+closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net
+cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=
+# A hashed hostname
+|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa
+AAAA1234.....=
+# A revoked key
+@revoked * ssh-rsa AAAAB5W...
+# A CA key, accepted for any host in *.mydomain.com or *.mydomain.org
+@cert-authority *.mydomain.org,*.mydomain.com ssh-rsa AAAAB5W...
+.Ed
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.hushlogin
+This file is used to suppress printing the last login time and
+.Pa /etc/motd ,
+if
+.Cm PrintLastLog
+and
+.Cm PrintMotd ,
+respectively,
+are enabled.
+It does not suppress printing of the banner specified by
+.Cm Banner .
+.Pp
+.It Pa ~/.rhosts
+This file is used for host-based authentication (see
+.Xr ssh 1
+for more information).
+On some machines this file may need to be
+world-readable if the user's home directory is on an NFS partition,
+because
+.Nm
+reads it as root.
+Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else.
+The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.Pp
+.It Pa ~/.shosts
+This file is used in exactly the same way as
+.Pa .rhosts ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa ~/.ssh/
+This directory is the default location for all user-specific configuration
+and authentication information.
+There is no general requirement to keep the entire contents of this directory
+secret, but the recommended permissions are read/write/execute for the user,
+and not accessible by others.
+.Pp
+.It Pa ~/.ssh/authorized_keys
+Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in
+as this user.
+The format of this file is described above.
+The content of the file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.Pp
+If this file, the
+.Pa ~/.ssh
+directory, or the user's home directory are writable
+by other users, then the file could be modified or replaced by unauthorized
+users.
+In this case,
+.Nm
+will not allow it to be used unless the
+.Cm StrictModes
+option has been set to
+.Dq no .
+.Pp
+.It Pa ~/.ssh/environment
+This file is read into the environment at login (if it exists).
+It can only contain empty lines, comment lines (that start with
+.Ql # ) ,
+and assignment lines of the form name=value.
+The file should be writable
+only by the user; it need not be readable by anyone else.
+Environment processing is disabled by default and is
+controlled via the
+.Cm PermitUserEnvironment
+option.
+.Pp
+.It Pa ~/.ssh/known_hosts
+Contains a list of host keys for all hosts the user has logged into
+that are not already in the systemwide list of known host keys.
+The format of this file is described above.
+This file should be writable only by root/the owner and
+can, but need not be, world-readable.
+.Pp
+.It Pa ~/.ssh/rc
+Contains initialization routines to be run before
+the user's home directory becomes accessible.
+This file should be writable only by the user, and need not be
+readable by anyone else.
+.Pp
+.It Pa /etc/hosts.allow
+.It Pa /etc/hosts.deny
+Access controls that should be enforced by tcp-wrappers are defined here.
+Further details are described in
+.Xr hosts_access 5 .
+.Pp
+.It Pa /etc/hosts.equiv
+This file is for host-based authentication (see
+.Xr ssh 1 ) .
+It should only be writable by root.
+.Pp
+.It Pa /etc/moduli
+Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange".
+The file format is described in
+.Xr moduli 5 .
+.Pp
+.It Pa /etc/motd
+See
+.Xr motd 5 .
+.Pp
+.It Pa /etc/nologin
+If this file exists,
+.Nm
+refuses to let anyone except root log in.
+The contents of the file
+are displayed to anyone trying to log in, and non-root connections are
+refused.
+The file should be world-readable.
+.Pp
+.It Pa /etc/shosts.equiv
+This file is used in exactly the same way as
+.Pa hosts.equiv ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa /etc/ssh/ssh_host_key
+.It Pa /etc/ssh/ssh_host_dsa_key
+.It Pa /etc/ssh/ssh_host_ecdsa_key
+.It Pa /etc/ssh/ssh_host_rsa_key
+These three files contain the private parts of the host keys.
+These files should only be owned by root, readable only by root, and not
+accessible to others.
+Note that
+.Nm
+does not start if these files are group/world-accessible.
+.Pp
+.It Pa /etc/ssh/ssh_host_key.pub
+.It Pa /etc/ssh/ssh_host_dsa_key.pub
+.It Pa /etc/ssh/ssh_host_ecdsa_key.pub
+.It Pa /etc/ssh/ssh_host_rsa_key.pub
+These three files contain the public parts of the host keys.
+These files should be world-readable but writable only by
+root.
+Their contents should match the respective private parts.
+These files are not
+really used for anything; they are provided for the convenience of
+the user so their contents can be copied to known hosts files.
+These files are created using
+.Xr ssh-keygen 1 .
+.Pp
+.It Pa /etc/ssh/ssh_known_hosts
+Systemwide list of known host keys.
+This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization.
+The format of this file is described above.
+This file should be writable only by root/the owner and
+should be world-readable.
+.Pp
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Nm sshd .
+The file format and configuration options are described in
+.Xr sshd_config 5 .
+.Pp
+.It Pa /etc/ssh/sshrc
+Similar to
+.Pa ~/.ssh/rc ,
+it can be used to specify
+machine-specific login-time initializations globally.
+This file should be writable only by root, and should be world-readable.
+.Pp
+.It Pa /var/empty
+.Xr chroot 2
+directory used by
+.Nm
+during privilege separation in the pre-authentication phase.
+The directory should not contain any files and must be owned by root
+and not group or world-writable.
+.Pp
+.It Pa /var/run/sshd.pid
+Contains the process ID of the
+.Nm
+listening for connections (if there are several daemons running
+concurrently for different ports, this contains the process ID of the one
+started last).
+The content of this file is not sensitive; it can be world-readable.
+.El
+.Sh SEE ALSO
+.Xr scp 1 ,
+.Xr sftp 1 ,
+.Xr ssh 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-keygen 1 ,
+.Xr ssh-keyscan 1 ,
+.Xr ssh-vulnkey 1 ,
+.Xr chroot 2 ,
+.Xr hosts_access 5 ,
+.Xr login.conf 5 ,
+.Xr moduli 5 ,
+.Xr sshd_config 5 ,
+.Xr inetd 8 ,
+.Xr sftp-server 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
+.Sh CAVEATS
+System security is not improved unless
+.Nm rshd ,
+.Nm rlogind ,
+and
+.Nm rexecd
+are disabled (thus completely disabling
+.Xr rlogin
+and
+.Xr rsh
+into the machine).
diff --git a/.pc/openbsd-docs.patch/sshd_config.5 b/.pc/openbsd-docs.patch/sshd_config.5
new file mode 100644 (file)
index 0000000..156047e
--- /dev/null
@@ -0,0 +1,1265 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd_config.5,v 1.135 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD_CONFIG 5
+.Os
+.Sh NAME
+.Nm sshd_config
+.Nd OpenSSH SSH daemon configuration file
+.Sh SYNOPSIS
+.Nm /etc/ssh/sshd_config
+.Sh DESCRIPTION
+.Xr sshd 8
+reads configuration data from
+.Pa /etc/ssh/sshd_config
+(or the file specified with
+.Fl f
+on the command line).
+The file contains keyword-argument pairs, one per line.
+Lines starting with
+.Ql #
+and empty lines are interpreted as comments.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm AcceptEnv
+Specifies what environment variables sent by the client will be copied into
+the session's
+.Xr environ 7 .
+See
+.Cm SendEnv
+in
+.Xr ssh_config 5
+for how to configure the client.
+Note that environment passing is only supported for protocol 2.
+Variables are specified by name, which may contain the wildcard characters
+.Ql *
+and
+.Ql \&? .
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm AcceptEnv
+directives.
+Be warned that some environment variables could be used to bypass restricted
+user environments.
+For this reason, care should be taken in the use of this directive.
+The default is not to accept any environment variables.
+.It Cm AddressFamily
+Specifies which address family should be used by
+.Xr sshd 8 .
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+The default is
+.Dq any .
+.It Cm AllowAgentForwarding
+Specifies whether
+.Xr ssh-agent 1
+forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling agent forwarding does not improve security
+unless users are also denied shell access, as they can always install
+their own forwarders.
+.It Cm AllowGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+If specified, login is allowed only for users whose primary
+group or supplementary group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling TCP forwarding does not improve security unless
+users are also denied shell access, as they can always install their
+own forwarders.
+.It Cm AllowUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+If specified, login is allowed only for user names that
+match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AuthorizedKeysFile
+Specifies the file that contains the public keys that can be used
+for user authentication.
+The format is described in the
+.Sx AUTHORIZED_KEYS FILE FORMAT
+section of
+.Xr sshd 8 .
+.Cm AuthorizedKeysFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedKeysFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+Multiple files may be listed, separated by whitespace.
+The default is
+.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
+.It Cm AuthorizedPrincipalsFile
+Specifies a file that lists principal names that are accepted for
+certificate authentication.
+When using certificates signed by a key listed in
+.Cm TrustedUserCAKeys ,
+this file lists names, one of which must appear in the certificate for it
+to be accepted for authentication.
+Names are listed one per line preceded by key options (as described
+in
+.Sx AUTHORIZED_KEYS FILE FORMAT
+in
+.Xr sshd 8 ) .
+Empty lines and comments starting with
+.Ql #
+are ignored.
+.Pp
+.Cm AuthorizedPrincipalsFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedPrincipalsFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+.Pp
+The default is not to use a principals file \(en in this case, the username
+of the user must appear in a certificate's principals list for it to be
+accepted.
+Note that
+.Cm AuthorizedPrincipalsFile
+is only used when authentication proceeds using a CA listed in
+.Cm TrustedUserCAKeys
+and is not consulted for certification authorities trusted via
+.Pa ~/.ssh/authorized_keys ,
+though the
+.Cm principals=
+key option offers a similar facility (see
+.Xr sshd 8
+for details).
+.It Cm Banner
+The contents of the specified file are sent to the remote user before
+authentication is allowed.
+If the argument is
+.Dq none
+then no banner is displayed.
+This option is only available for protocol version 2.
+By default, no banner is displayed.
+.It Cm ChallengeResponseAuthentication
+Specifies whether challenge-response authentication is allowed (e.g. via
+PAM or though authentication styles supported in
+.Xr login.conf 5 )
+The default is
+.Dq yes .
+.It Cm ChrootDirectory
+Specifies the pathname of a directory to
+.Xr chroot 2
+to after authentication.
+All components of the pathname must be root-owned directories that are
+not writable by any other user or group.
+After the chroot,
+.Xr sshd 8
+changes the working directory to the user's home directory.
+.Pp
+The pathname may contain the following tokens that are expanded at runtime once
+the connecting user has been authenticated: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+.Pp
+The
+.Cm ChrootDirectory
+must contain the necessary files and directories to support the
+user's session.
+For an interactive session this requires at least a shell, typically
+.Xr sh 1 ,
+and basic
+.Pa /dev
+nodes such as
+.Xr null 4 ,
+.Xr zero 4 ,
+.Xr stdin 4 ,
+.Xr stdout 4 ,
+.Xr stderr 4 ,
+.Xr arandom 4
+and
+.Xr tty 4
+devices.
+For file transfer sessions using
+.Dq sftp ,
+no additional configuration of the environment is necessary if the
+in-process sftp server is used,
+though sessions which use logging do require
+.Pa /dev/log
+inside the chroot directory (see
+.Xr sftp-server 8
+for details).
+.Pp
+The default is not to
+.Xr chroot 2 .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClientAliveCountMax
+Sets the number of client alive messages (see below) which may be
+sent without
+.Xr sshd 8
+receiving any messages back from the client.
+If this threshold is reached while client alive messages are being sent,
+sshd will disconnect the client, terminating the session.
+It is important to note that the use of client alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The client alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The client alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If
+.Cm ClientAliveInterval
+(see below) is set to 15, and
+.Cm ClientAliveCountMax
+is left at the default, unresponsive SSH clients
+will be disconnected after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ClientAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the client,
+.Xr sshd 8
+will send a message through the encrypted
+channel to request a response from the client.
+The default
+is 0, indicating that these messages will not be sent to the client.
+This option applies to protocol version 2 only.
+.It Cm Compression
+Specifies whether compression is allowed, or delayed until
+the user has authenticated successfully.
+The argument must be
+.Dq yes ,
+.Dq delayed ,
+or
+.Dq no .
+The default is
+.Dq delayed .
+.It Cm DebianBanner
+Specifies whether the distribution-specified extra version suffix is
+included during initial protocol handshake.
+The default is
+.Dq yes .
+.It Cm DenyGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+Login is disallowed for users whose primary group or supplementary
+group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm DenyUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+Login is disallowed for user names that match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm ForceCommand
+Forces the execution of the command specified by
+.Cm ForceCommand ,
+ignoring any command supplied by the client and
+.Pa ~/.ssh/rc
+if present.
+The command is invoked by using the user's login shell with the -c option.
+This applies to shell, command, or subsystem execution.
+It is most useful inside a
+.Cm Match
+block.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Specifying a command of
+.Dq internal-sftp
+will force the use of an in-process sftp server that requires no support
+files when used with
+.Cm ChrootDirectory .
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to ports
+forwarded for the client.
+By default,
+.Xr sshd 8
+binds remote port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that sshd
+should allow remote port forwardings to bind to non-loopback addresses, thus
+allowing other hosts to connect.
+The argument may be
+.Dq no
+to force remote port forwardings to be available to the local host only,
+.Dq yes
+to force remote port forwardings to bind to the wildcard address, or
+.Dq clientspecified
+to allow the client to select the address to which the forwarding is bound.
+The default is
+.Dq no .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICleanupCredentials
+Specifies whether to automatically destroy the user's credentials cache
+on logout.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor 
+a client authenticates against. If
+.Dq yes
+then the client must authenticate against the
+.Pa host
+service on the current hostname. If 
+.Dq no
+then the client may authenticate against any service key stored in the 
+machine's default store. This facility is provided to assist with operation 
+on multi homed machines. 
+The default is
+.Dq yes .
+Note that this option applies only to protocol version 2 GSSAPI connections,
+and setting it to 
+.Dq no
+may only work with recent Kerberos GSSAPI libraries.
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
+.Dq no .
+.It Cm HostbasedAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful public key client host authentication is allowed
+(host-based authentication).
+This option is similar to
+.Cm RhostsRSAAuthentication
+and applies to protocol version 2 only.
+The default is
+.Dq no .
+.It Cm HostbasedUsesNameFromPacketOnly
+Specifies whether or not the server will attempt to perform a reverse
+name lookup when matching the name in the
+.Pa ~/.shosts ,
+.Pa ~/.rhosts ,
+and
+.Pa /etc/hosts.equiv
+files during
+.Cm HostbasedAuthentication .
+A setting of
+.Dq yes
+means that
+.Xr sshd 8
+uses the name supplied by the client rather than
+attempting to resolve the name from the TCP connection itself.
+The default is
+.Dq no .
+.It Cm HostCertificate
+Specifies a file containing a public host certificate.
+The certificate's public key must match a private host key already specified
+by
+.Cm HostKey .
+The default behaviour of
+.Xr sshd 8
+is not to load any certificates.
+.It Cm HostKey
+Specifies a file containing a private host key
+used by SSH.
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+Note that
+.Xr sshd 8
+will refuse to use a file if it is group/world-accessible.
+It is possible to have multiple host key files.
+.Dq rsa1
+keys are used for version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+are used for version 2 of the SSH protocol.
+.It Cm IgnoreRhosts
+Specifies that
+.Pa .rhosts
+and
+.Pa .shosts
+files will not be used in
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+.Pp
+.Pa /etc/hosts.equiv
+and
+.Pa /etc/shosts.equiv
+are still used.
+The default is
+.Dq yes .
+.It Cm IgnoreUserKnownHosts
+Specifies whether
+.Xr sshd 8
+should ignore the user's
+.Pa ~/.ssh/known_hosts
+during
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+The default is
+.Dq no .
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for the connection.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KerberosAuthentication
+Specifies whether the password provided by the user for
+.Cm PasswordAuthentication
+will be validated through the Kerberos KDC.
+To use this option, the server needs a
+Kerberos servtab which allows the verification of the KDC's identity.
+The default is
+.Dq no .
+.It Cm KerberosGetAFSToken
+If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
+an AFS token before accessing the user's home directory.
+The default is
+.Dq no .
+.It Cm KerberosOrLocalPasswd
+If password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as
+.Pa /etc/passwd .
+The default is
+.Dq yes .
+.It Cm KerberosTicketCleanup
+Specifies whether to automatically destroy the user's ticket cache
+file on logout.
+The default is
+.Dq yes .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq ecdh-sha2-nistp256 ,
+.Dq ecdh-sha2-nistp384 ,
+.Dq ecdh-sha2-nistp521 ,
+.Dq diffie-hellman-group-exchange-sha256 ,
+.Dq diffie-hellman-group-exchange-sha1 ,
+.Dq diffie-hellman-group14-sha1 ,
+.Dq diffie-hellman-group1-sha1 .
+.It Cm KeyRegenerationInterval
+In protocol version 1, the ephemeral server key is automatically regenerated
+after this many seconds (if it has been used).
+The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys.
+The key is never stored anywhere.
+If the value is 0, the key is never regenerated.
+The default is 3600 (seconds).
+.It Cm ListenAddress
+Specifies the local addresses
+.Xr sshd 8
+should listen on.
+The following forms may be used:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No : Ar port
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Oo
+.Ar host No | Ar IPv6_addr Oc : Ar port
+.Sm on
+.El
+.Pp
+If
+.Ar port
+is not specified,
+sshd will listen on the address and all prior
+.Cm Port
+options specified.
+The default is to listen on all local addresses.
+Multiple
+.Cm ListenAddress
+options are permitted.
+Additionally, any
+.Cm Port
+options must precede this option for non-port qualified addresses.
+.It Cm LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in.
+If the value is 0, there is no time limit.
+The default is 120 seconds.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr sshd 8 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of debugging output.
+Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm MACs
+Specifies the available MAC (message authentication code) algorithms.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm Match
+Introduces a conditional block.
+If all of the criteria on the
+.Cm Match
+line are satisfied, the keywords on the following lines override those
+set in the global section of the config file, until either another
+.Cm Match
+line or the end of the file.
+.Pp
+The arguments to
+.Cm Match
+are one or more criteria-pattern pairs.
+The available criteria are
+.Cm User ,
+.Cm Group ,
+.Cm Host ,
+and
+.Cm Address .
+The match patterns may consist of single entries or comma-separated
+lists and may use the wildcard and negation operators described in the
+.Sx PATTERNS
+section of
+.Xr ssh_config 5 .
+.Pp
+The patterns in an
+.Cm Address
+criteria may additionally contain addresses to match in CIDR
+address/masklen format, e.g.\&
+.Dq 192.0.2.0/24
+or
+.Dq 3ffe:ffff::/32 .
+Note that the mask length provided must be consistent with the address -
+it is an error to specify a mask length that is too long for the address
+or one with bits set in this host portion of the address.
+For example,
+.Dq 192.0.2.0/33
+and
+.Dq 192.0.2.0/8
+respectively.
+.Pp
+Only a subset of keywords may be used on the lines following a
+.Cm Match
+keyword.
+Available keywords are
+.Cm AllowAgentForwarding ,
+.Cm AllowTcpForwarding ,
+.Cm AuthorizedKeysFile ,
+.Cm AuthorizedPrincipalsFile ,
+.Cm Banner ,
+.Cm ChrootDirectory ,
+.Cm ForceCommand ,
+.Cm GatewayPorts ,
+.Cm GSSAPIAuthentication ,
+.Cm HostbasedAuthentication ,
+.Cm HostbasedUsesNameFromPacketOnly ,
+.Cm KbdInteractiveAuthentication ,
+.Cm KerberosAuthentication ,
+.Cm MaxAuthTries ,
+.Cm MaxSessions ,
+.Cm PasswordAuthentication ,
+.Cm PermitEmptyPasswords ,
+.Cm PermitOpen ,
+.Cm PermitRootLogin ,
+.Cm PermitTunnel ,
+.Cm PubkeyAuthentication ,
+.Cm RhostsRSAAuthentication ,
+.Cm RSAAuthentication ,
+.Cm X11DisplayOffset ,
+.Cm X11Forwarding
+and
+.Cm X11UseLocalHost .
+.It Cm MaxAuthTries
+Specifies the maximum number of authentication attempts permitted per
+connection.
+Once the number of failures reaches half this value,
+additional failures are logged.
+The default is 6.
+.It Cm MaxSessions
+Specifies the maximum number of open sessions permitted per network connection.
+The default is 10.
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+SSH daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g. "10:30:60").
+.Xr sshd 8
+will refuse connection attempts with a probability of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probability increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
+.It Cm PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is
+.Dq yes .
+.It Cm PermitBlacklistedKeys
+Specifies whether
+.Xr sshd 8
+should allow keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 ) .
+If
+.Dq yes ,
+then attempts to authenticate with compromised keys will be logged but
+accepted.
+If
+.Dq no ,
+then attempts to authenticate with compromised keys will be rejected.
+The default is
+.Dq no .
+.It Cm PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings.
+The default is
+.Dq no .
+.It Cm PermitOpen
+Specifies the destinations to which TCP port forwarding is permitted.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Dq any
+can be used to remove all restrictions and permit any forwarding requests.
+By default all port forwarding requests are permitted.
+.It Cm PermitRootLogin
+Specifies whether root can log in using
+.Xr ssh 1 .
+The argument must be
+.Dq yes ,
+.Dq without-password ,
+.Dq forced-commands-only ,
+or
+.Dq no .
+The default is
+.Dq yes .
+.Pp
+If this option is set to
+.Dq without-password ,
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only ,
+root login with public key authentication will be allowed,
+but only if the
+.Ar command
+option has been specified
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+All other authentication methods are disabled for root.
+.Pp
+If this option is set to
+.Dq no ,
+root is not allowed to log in.
+.It Cm PermitTunnel
+Specifies whether
+.Xr tun 4
+device forwarding is allowed.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2), or
+.Dq no .
+Specifying
+.Dq yes
+permits both
+.Dq point-to-point
+and
+.Dq ethernet .
+The default is
+.Dq no .
+.It Cm PermitUserEnvironment
+Specifies whether
+.Pa ~/.ssh/environment
+and
+.Cm environment=
+options in
+.Pa ~/.ssh/authorized_keys
+are processed by
+.Xr sshd 8 .
+The default is
+.Dq no .
+Enabling environment processing may enable users to bypass access
+restrictions in some configurations using mechanisms such as
+.Ev LD_PRELOAD .
+.It Cm PidFile
+Specifies the file that contains the process ID of the
+SSH daemon.
+The default is
+.Pa /var/run/sshd.pid .
+.It Cm Port
+Specifies the port number that
+.Xr sshd 8
+listens on.
+The default is 22.
+Multiple options of this type are permitted.
+See also
+.Cm ListenAddress .
+.It Cm PrintLastLog
+Specifies whether
+.Xr sshd 8
+should print the date and time of the last user login when a user logs
+in interactively.
+The default is
+.Dq yes .
+.It Cm PrintMotd
+Specifies whether
+.Xr sshd 8
+should print
+.Pa /etc/motd
+when a user logs in interactively.
+(On some systems it is also printed by the shell,
+.Pa /etc/profile ,
+or equivalent.)
+The default is
+.Dq yes .
+.It Cm Protocol
+Specifies the protocol versions
+.Xr sshd 8
+supports.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Sq 2 .
+Note that the order of the protocol list does not indicate preference,
+because the client selects among multiple protocol versions offered
+by the server.
+Specifying
+.Dq 2,1
+is identical to
+.Dq 1,2 .
+.It Cm PubkeyAuthentication
+Specifies whether public key authentication is allowed.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm RevokedKeys
+Specifies a list of revoked public keys.
+Keys listed in this file will be refused for public key authentication.
+Note that if this file is not readable, then public key authentication will
+be refused for all users.
+.It Cm RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RSAAuthentication
+Specifies whether pure RSA authentication is allowed.
+The default is
+.Dq yes .
+This option applies to protocol version 1 only.
+.It Cm ServerKeyBits
+Defines the number of bits in the ephemeral protocol version 1 server key.
+The minimum value is 512, and the default is 1024.
+.It Cm StrictModes
+Specifies whether
+.Xr sshd 8
+should check file modes and ownership of the
+user's files and home directory before accepting login.
+This is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable.
+The default is
+.Dq yes .
+Note that this does not apply to
+.Cm ChrootDirectory ,
+whose permissions and ownership are checked unconditionally.
+.It Cm Subsystem
+Configures an external subsystem (e.g. file transfer daemon).
+Arguments should be a subsystem name and a command (with optional arguments)
+to execute upon subsystem request.
+.Pp
+The command
+.Xr sftp-server 8
+implements the
+.Dq sftp
+file transfer subsystem.
+.Pp
+Alternately the name
+.Dq internal-sftp
+implements an in-process
+.Dq sftp
+server.
+This may simplify configurations using
+.Cm ChrootDirectory
+to force a different filesystem root on clients.
+.Pp
+By default no subsystems are defined.
+Note that this option applies to protocol version 2 only.
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Xr sshd 8 .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is AUTH.
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+On the other hand, if TCP keepalives are not sent,
+sessions may hang indefinitely on the server, leaving
+.Dq ghost
+users and consuming server resources.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the server will notice
+if the network goes down or the client host crashes.
+This avoids infinitely hanging sessions.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.Pp
+This option was formerly called
+.Cm KeepAlive .
+.It Cm TrustedUserCAKeys
+Specifies a file containing public keys of certificate authorities that are
+trusted to sign user certificates for authentication.
+Keys are listed one per line; empty lines and comments starting with
+.Ql #
+are allowed.
+If a certificate is presented for authentication and has its signing CA key
+listed in this file, then it may be used for authentication for any user
+listed in the certificate's principals list.
+Note that certificates that lack a list of principals will not be permitted
+for authentication using
+.Cm TrustedUserCAKeys .
+For more details on certificates, see the
+.Sx CERTIFICATES
+section in
+.Xr ssh-keygen 1 .
+.It Cm UseDNS
+Specifies whether
+.Xr sshd 8
+should look up the remote host name and check that
+the resolved host name for the remote IP address maps back to the
+very same IP address.
+The default is
+.Dq yes .
+.It Cm UseLogin
+Specifies whether
+.Xr login 1
+is used for interactive login sessions.
+The default is
+.Dq no .
+Note that
+.Xr login 1
+is never used for remote command execution.
+Note also, that if this is enabled,
+.Cm X11Forwarding
+will be disabled because
+.Xr login 1
+does not know how to handle
+.Xr xauth 1
+cookies.
+If
+.Cm UsePrivilegeSeparation
+is specified, it will be disabled after authentication.
+.It Cm UsePAM
+Enables the Pluggable Authentication Module interface.
+If set to
+.Dq yes
+this will enable PAM authentication using
+.Cm ChallengeResponseAuthentication
+and
+.Cm PasswordAuthentication
+in addition to PAM account and session module processing for all
+authentication types.
+.Pp
+Because PAM challenge-response authentication usually serves an equivalent
+role to password authentication, you should disable either
+.Cm PasswordAuthentication
+or
+.Cm ChallengeResponseAuthentication.
+.Pp
+If
+.Cm UsePAM
+is enabled, you will not be able to run
+.Xr sshd 8
+as a non-root user.
+The default is
+.Dq no .
+.It Cm UsePrivilegeSeparation
+Specifies whether
+.Xr sshd 8
+separates privileges by creating an unprivileged child process
+to deal with incoming network traffic.
+After successful authentication, another process will be created that has
+the privilege of the authenticated user.
+The goal of privilege separation is to prevent privilege
+escalation by containing any corruption within the unprivileged processes.
+The default is
+.Dq yes .
+If
+.Cm UsePrivilegeSeparation
+is set to
+.Dq sandbox
+then the pre-authentication unprivileged process is subject to additional
+restrictions.
+.It Cm X11DisplayOffset
+Specifies the first display number available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from interfering with real X11 servers.
+The default is 10.
+.It Cm X11Forwarding
+Specifies whether X11 forwarding is permitted.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+When X11 forwarding is enabled, there may be additional exposure to
+the server and to client displays if the
+.Xr sshd 8
+proxy display is configured to listen on the wildcard address (see
+.Cm X11UseLocalhost
+below), though this is not the default.
+Additionally, the authentication spoofing and authentication data
+verification and substitution occur on the client side.
+The security risk of using X11 forwarding is that the client's X11
+display server may be exposed to attack when the SSH client requests
+forwarding (see the warnings for
+.Cm ForwardX11
+in
+.Xr ssh_config 5 ) .
+A system administrator may have a stance in which they want to
+protect clients that may expose themselves to attack by unwittingly
+requesting X11 forwarding, which can warrant a
+.Dq no
+setting.
+.Pp
+Note that disabling X11 forwarding does not prevent users from
+forwarding X11 traffic, as users can always install their own forwarders.
+X11 forwarding is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm X11UseLocalhost
+Specifies whether
+.Xr sshd 8
+should bind the X11 forwarding server to the loopback address or to
+the wildcard address.
+By default,
+sshd binds the forwarding server to the loopback address and sets the
+hostname part of the
+.Ev DISPLAY
+environment variable to
+.Dq localhost .
+This prevents remote hosts from connecting to the proxy display.
+However, some older X11 clients may not function with this
+configuration.
+.Cm X11UseLocalhost
+may be set to
+.Dq no
+to specify that the forwarding server should be bound to the wildcard
+address.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh TIME FORMATS
+.Xr sshd 8
+command-line arguments and configuration file options that specify time
+may be expressed using a sequence of the form:
+.Sm off
+.Ar time Op Ar qualifier ,
+.Sm on
+where
+.Ar time
+is a positive integer value and
+.Ar qualifier
+is one of the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Aq Cm none
+seconds
+.It Cm s | Cm S
+seconds
+.It Cm m | Cm M
+minutes
+.It Cm h | Cm H
+hours
+.It Cm d | Cm D
+days
+.It Cm w | Cm W
+weeks
+.El
+.Pp
+Each member of the sequence is added together to calculate
+the total time value.
+.Pp
+Time format examples:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It 600
+600 seconds (10 minutes)
+.It 10m
+10 minutes
+.It 1h30m
+1 hour 30 minutes (90 minutes)
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Xr sshd 8 .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.El
+.Sh SEE ALSO
+.Xr sshd 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
diff --git a/.pc/package-versioning.patch/sshconnect.c b/.pc/package-versioning.patch/sshconnect.c
new file mode 100644 (file)
index 0000000..9b3dd2f
--- /dev/null
@@ -0,0 +1,1291 @@
+/* $OpenBSD: sshconnect.c,v 1.234 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Code to connect to a remote host, and to perform the client side of the
+ * login (authentication) dialog.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
+#include "ssh.h"
+#include "rsa.h"
+#include "buffer.h"
+#include "packet.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "key.h"
+#include "sshconnect.h"
+#include "hostfile.h"
+#include "log.h"
+#include "readconf.h"
+#include "atomicio.h"
+#include "misc.h"
+#include "dns.h"
+#include "roaming.h"
+#include "ssh2.h"
+#include "version.h"
+
+char *client_version_string = NULL;
+char *server_version_string = NULL;
+
+static int matching_host_key_dns = 0;
+
+static pid_t proxy_command_pid = 0;
+
+/* import */
+extern Options options;
+extern char *__progname;
+extern uid_t original_real_uid;
+extern uid_t original_effective_uid;
+
+static int show_other_keys(struct hostkeys *, Key *);
+static void warn_changed_key(Key *);
+
+/*
+ * Connect to the given ssh server using a proxy command.
+ */
+static int
+ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
+{
+       char *command_string, *tmp;
+       int pin[2], pout[2];
+       pid_t pid;
+       char *shell, strport[NI_MAXSERV];
+
+       if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
+               shell = _PATH_BSHELL;
+
+       /* Convert the port number into a string. */
+       snprintf(strport, sizeof strport, "%hu", port);
+
+       /*
+        * Build the final command string in the buffer by making the
+        * appropriate substitutions to the given proxy command.
+        *
+        * Use "exec" to avoid "sh -c" processes on some platforms
+        * (e.g. Solaris)
+        */
+       xasprintf(&tmp, "exec %s", proxy_command);
+       command_string = percent_expand(tmp, "h", host, "p", strport,
+           "r", options.user, (char *)NULL);
+       xfree(tmp);
+
+       /* Create pipes for communicating with the proxy. */
+       if (pipe(pin) < 0 || pipe(pout) < 0)
+               fatal("Could not create pipes to communicate with the proxy: %.100s",
+                   strerror(errno));
+
+       debug("Executing proxy command: %.500s", command_string);
+
+       /* Fork and execute the proxy command. */
+       if ((pid = fork()) == 0) {
+               char *argv[10];
+
+               /* Child.  Permanently give up superuser privileges. */
+               permanently_drop_suid(original_real_uid);
+
+               /* Redirect stdin and stdout. */
+               close(pin[1]);
+               if (pin[0] != 0) {
+                       if (dup2(pin[0], 0) < 0)
+                               perror("dup2 stdin");
+                       close(pin[0]);
+               }
+               close(pout[0]);
+               if (dup2(pout[1], 1) < 0)
+                       perror("dup2 stdout");
+               /* Cannot be 1 because pin allocated two descriptors. */
+               close(pout[1]);
+
+               /* Stderr is left as it is so that error messages get
+                  printed on the user's terminal. */
+               argv[0] = shell;
+               argv[1] = "-c";
+               argv[2] = command_string;
+               argv[3] = NULL;
+
+               /* Execute the proxy command.  Note that we gave up any
+                  extra privileges above. */
+               signal(SIGPIPE, SIG_DFL);
+               execvp(argv[0], argv);
+               perror(argv[0]);
+               exit(1);
+       }
+       /* Parent. */
+       if (pid < 0)
+               fatal("fork failed: %.100s", strerror(errno));
+       else
+               proxy_command_pid = pid; /* save pid to clean up later */
+
+       /* Close child side of the descriptors. */
+       close(pin[0]);
+       close(pout[1]);
+
+       /* Free the command name. */
+       xfree(command_string);
+
+       /* Set the connection file descriptors. */
+       packet_set_connection(pout[0], pin[1]);
+       packet_set_timeout(options.server_alive_interval,
+           options.server_alive_count_max);
+
+       /* Indicate OK return */
+       return 0;
+}
+
+void
+ssh_kill_proxy_command(void)
+{
+       /*
+        * Send SIGHUP to proxy command if used. We don't wait() in
+        * case it hangs and instead rely on init to reap the child
+        */
+       if (proxy_command_pid > 1)
+               kill(proxy_command_pid, SIGHUP);
+}
+
+/*
+ * Creates a (possibly privileged) socket for use as the ssh connection.
+ */
+static int
+ssh_create_socket(int privileged, struct addrinfo *ai)
+{
+       int sock, gaierr;
+       struct addrinfo hints, *res;
+
+       /*
+        * If we are running as root and want to connect to a privileged
+        * port, bind our own socket to a privileged port.
+        */
+       if (privileged) {
+               int p = IPPORT_RESERVED - 1;
+               PRIV_START;
+               sock = rresvport_af(&p, ai->ai_family);
+               PRIV_END;
+               if (sock < 0)
+                       error("rresvport: af=%d %.100s", ai->ai_family,
+                           strerror(errno));
+               else
+                       debug("Allocated local port %d.", p);
+               return sock;
+       }
+       sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+       if (sock < 0) {
+               error("socket: %.100s", strerror(errno));
+               return -1;
+       }
+       fcntl(sock, F_SETFD, FD_CLOEXEC);
+
+       /* Bind the socket to an alternative local IP address */
+       if (options.bind_address == NULL)
+               return sock;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = ai->ai_family;
+       hints.ai_socktype = ai->ai_socktype;
+       hints.ai_protocol = ai->ai_protocol;
+       hints.ai_flags = AI_PASSIVE;
+       gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res);
+       if (gaierr) {
+               error("getaddrinfo: %s: %s", options.bind_address,
+                   ssh_gai_strerror(gaierr));
+               close(sock);
+               return -1;
+       }
+       if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
+               error("bind: %s: %s", options.bind_address, strerror(errno));
+               close(sock);
+               freeaddrinfo(res);
+               return -1;
+       }
+       freeaddrinfo(res);
+       return sock;
+}
+
+static int
+timeout_connect(int sockfd, const struct sockaddr *serv_addr,
+    socklen_t addrlen, int *timeoutp)
+{
+       fd_set *fdset;
+       struct timeval tv, t_start;
+       socklen_t optlen;
+       int optval, rc, result = -1;
+
+       gettimeofday(&t_start, NULL);
+
+       if (*timeoutp <= 0) {
+               result = connect(sockfd, serv_addr, addrlen);
+               goto done;
+       }
+
+       set_nonblock(sockfd);
+       rc = connect(sockfd, serv_addr, addrlen);
+       if (rc == 0) {
+               unset_nonblock(sockfd);
+               result = 0;
+               goto done;
+       }
+       if (errno != EINPROGRESS) {
+               result = -1;
+               goto done;
+       }
+
+       fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS),
+           sizeof(fd_mask));
+       FD_SET(sockfd, fdset);
+       ms_to_timeval(&tv, *timeoutp);
+
+       for (;;) {
+               rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
+               if (rc != -1 || errno != EINTR)
+                       break;
+       }
+
+       switch (rc) {
+       case 0:
+               /* Timed out */
+               errno = ETIMEDOUT;
+               break;
+       case -1:
+               /* Select error */
+               debug("select: %s", strerror(errno));
+               break;
+       case 1:
+               /* Completed or failed */
+               optval = 0;
+               optlen = sizeof(optval);
+               if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
+                   &optlen) == -1) {
+                       debug("getsockopt: %s", strerror(errno));
+                       break;
+               }
+               if (optval != 0) {
+                       errno = optval;
+                       break;
+               }
+               result = 0;
+               unset_nonblock(sockfd);
+               break;
+       default:
+               /* Should not occur */
+               fatal("Bogus return (%d) from select()", rc);
+       }
+
+       xfree(fdset);
+
+ done:
+       if (result == 0 && *timeoutp > 0) {
+               ms_subtract_diff(&t_start, timeoutp);
+               if (*timeoutp <= 0) {
+                       errno = ETIMEDOUT;
+                       result = -1;
+               }
+       }
+
+       return (result);
+}
+
+/*
+ * Opens a TCP/IP connection to the remote server on the given host.
+ * The address of the remote host will be returned in hostaddr.
+ * If port is 0, the default port will be used.  If needpriv is true,
+ * a privileged port will be allocated to make the connection.
+ * This requires super-user privileges if needpriv is true.
+ * Connection_attempts specifies the maximum number of tries (one per
+ * second).  If proxy_command is non-NULL, it specifies the command (with %h
+ * and %p substituted for host and port, respectively) to use to contact
+ * the daemon.
+ */
+int
+ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
+    u_short port, int family, int connection_attempts, int *timeout_ms,
+    int want_keepalive, int needpriv, const char *proxy_command)
+{
+       int gaierr;
+       int on = 1;
+       int sock = -1, attempt;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+       struct addrinfo hints, *ai, *aitop;
+
+       debug2("ssh_connect: needpriv %d", needpriv);
+
+       /* If a proxy command is given, connect using it. */
+       if (proxy_command != NULL)
+               return ssh_proxy_connect(host, port, proxy_command);
+
+       /* No proxy command. */
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = family;
+       hints.ai_socktype = SOCK_STREAM;
+       snprintf(strport, sizeof strport, "%u", port);
+       if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
+               fatal("%s: Could not resolve hostname %.100s: %s", __progname,
+                   host, ssh_gai_strerror(gaierr));
+
+       for (attempt = 0; attempt < connection_attempts; attempt++) {
+               if (attempt > 0) {
+                       /* Sleep a moment before retrying. */
+                       sleep(1);
+                       debug("Trying again...");
+               }
+               /*
+                * Loop through addresses for this host, and try each one in
+                * sequence until the connection succeeds.
+                */
+               for (ai = aitop; ai; ai = ai->ai_next) {
+                       if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                               continue;
+                       if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                           ntop, sizeof(ntop), strport, sizeof(strport),
+                           NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
+                               error("ssh_connect: getnameinfo failed");
+                               continue;
+                       }
+                       debug("Connecting to %.200s [%.100s] port %s.",
+                               host, ntop, strport);
+
+                       /* Create a socket for connecting. */
+                       sock = ssh_create_socket(needpriv, ai);
+                       if (sock < 0)
+                               /* Any error is already output */
+                               continue;
+
+                       if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
+                           timeout_ms) >= 0) {
+                               /* Successful connection. */
+                               memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
+                               break;
+                       } else {
+                               debug("connect to address %s port %s: %s",
+                                   ntop, strport, strerror(errno));
+                               close(sock);
+                               sock = -1;
+                       }
+               }
+               if (sock != -1)
+                       break;  /* Successful connection. */
+       }
+
+       freeaddrinfo(aitop);
+
+       /* Return failure if we didn't get a successful connection. */
+       if (sock == -1) {
+               error("ssh: connect to host %s port %s: %s",
+                   host, strport, strerror(errno));
+               return (-1);
+       }
+
+       debug("Connection established.");
+
+       /* Set SO_KEEPALIVE if requested. */
+       if (want_keepalive &&
+           setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
+           sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
+       /* Set the connection. */
+       packet_set_connection(sock, sock);
+       packet_set_timeout(options.server_alive_interval,
+           options.server_alive_count_max);
+
+       return 0;
+}
+
+/*
+ * Waits for the server identification string, and sends our own
+ * identification string.
+ */
+void
+ssh_exchange_identification(int timeout_ms)
+{
+       char buf[256], remote_version[256];     /* must be same size! */
+       int remote_major, remote_minor, mismatch;
+       int connection_in = packet_get_connection_in();
+       int connection_out = packet_get_connection_out();
+       int minor1 = PROTOCOL_MINOR_1;
+       u_int i, n;
+       size_t len;
+       int fdsetsz, remaining, rc;
+       struct timeval t_start, t_remaining;
+       fd_set *fdset;
+
+       fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
+       fdset = xcalloc(1, fdsetsz);
+
+       /* Read other side's version identification. */
+       remaining = timeout_ms;
+       for (n = 0;;) {
+               for (i = 0; i < sizeof(buf) - 1; i++) {
+                       if (timeout_ms > 0) {
+                               gettimeofday(&t_start, NULL);
+                               ms_to_timeval(&t_remaining, remaining);
+                               FD_SET(connection_in, fdset);
+                               rc = select(connection_in + 1, fdset, NULL,
+                                   fdset, &t_remaining);
+                               ms_subtract_diff(&t_start, &remaining);
+                               if (rc == 0 || remaining <= 0)
+                                       fatal("Connection timed out during "
+                                           "banner exchange");
+                               if (rc == -1) {
+                                       if (errno == EINTR)
+                                               continue;
+                                       fatal("ssh_exchange_identification: "
+                                           "select: %s", strerror(errno));
+                               }
+                       }
+
+                       len = roaming_atomicio(read, connection_in, &buf[i], 1);
+
+                       if (len != 1 && errno == EPIPE)
+                               fatal("ssh_exchange_identification: "
+                                   "Connection closed by remote host");
+                       else if (len != 1)
+                               fatal("ssh_exchange_identification: "
+                                   "read: %.100s", strerror(errno));
+                       if (buf[i] == '\r') {
+                               buf[i] = '\n';
+                               buf[i + 1] = 0;
+                               continue;               /**XXX wait for \n */
+                       }
+                       if (buf[i] == '\n') {
+                               buf[i + 1] = 0;
+                               break;
+                       }
+                       if (++n > 65536)
+                               fatal("ssh_exchange_identification: "
+                                   "No banner received");
+               }
+               buf[sizeof(buf) - 1] = 0;
+               if (strncmp(buf, "SSH-", 4) == 0)
+                       break;
+               debug("ssh_exchange_identification: %s", buf);
+       }
+       server_version_string = xstrdup(buf);
+       xfree(fdset);
+
+       /*
+        * Check that the versions match.  In future this might accept
+        * several versions and set appropriate flags to handle them.
+        */
+       if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
+           &remote_major, &remote_minor, remote_version) != 3)
+               fatal("Bad remote protocol version identification: '%.100s'", buf);
+       debug("Remote protocol version %d.%d, remote software version %.100s",
+           remote_major, remote_minor, remote_version);
+
+       compat_datafellows(remote_version);
+       mismatch = 0;
+
+       switch (remote_major) {
+       case 1:
+               if (remote_minor == 99 &&
+                   (options.protocol & SSH_PROTO_2) &&
+                   !(options.protocol & SSH_PROTO_1_PREFERRED)) {
+                       enable_compat20();
+                       break;
+               }
+               if (!(options.protocol & SSH_PROTO_1)) {
+                       mismatch = 1;
+                       break;
+               }
+               if (remote_minor < 3) {
+                       fatal("Remote machine has too old SSH software version.");
+               } else if (remote_minor == 3 || remote_minor == 4) {
+                       /* We speak 1.3, too. */
+                       enable_compat13();
+                       minor1 = 3;
+                       if (options.forward_agent) {
+                               logit("Agent forwarding disabled for protocol 1.3");
+                               options.forward_agent = 0;
+                       }
+               }
+               break;
+       case 2:
+               if (options.protocol & SSH_PROTO_2) {
+                       enable_compat20();
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               mismatch = 1;
+               break;
+       }
+       if (mismatch)
+               fatal("Protocol major versions differ: %d vs. %d",
+                   (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
+                   remote_major);
+       /* Send our own protocol version identification. */
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
+           compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
+           compat20 ? PROTOCOL_MINOR_2 : minor1,
+           SSH_VERSION, compat20 ? "\r\n" : "\n");
+       if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
+           != strlen(buf))
+               fatal("write: %.100s", strerror(errno));
+       client_version_string = xstrdup(buf);
+       chop(client_version_string);
+       chop(server_version_string);
+       debug("Local version string %.100s", client_version_string);
+}
+
+/* defaults to 'no' */
+static int
+confirm(const char *prompt)
+{
+       const char *msg, *again = "Please type 'yes' or 'no': ";
+       char *p;
+       int ret = -1;
+
+       if (options.batch_mode)
+               return 0;
+       for (msg = prompt;;msg = again) {
+               p = read_passphrase(msg, RP_ECHO);
+               if (p == NULL ||
+                   (p[0] == '\0') || (p[0] == '\n') ||
+                   strncasecmp(p, "no", 2) == 0)
+                       ret = 0;
+               if (p && strncasecmp(p, "yes", 3) == 0)
+                       ret = 1;
+               if (p)
+                       xfree(p);
+               if (ret != -1)
+                       return ret;
+       }
+}
+
+static int
+check_host_cert(const char *host, const Key *host_key)
+{
+       const char *reason;
+
+       if (key_cert_check_authority(host_key, 1, 0, host, &reason) != 0) {
+               error("%s", reason);
+               return 0;
+       }
+       if (buffer_len(&host_key->cert->critical) != 0) {
+               error("Certificate for %s contains unsupported "
+                   "critical options(s)", host);
+               return 0;
+       }
+       return 1;
+}
+
+static int
+sockaddr_is_local(struct sockaddr *hostaddr)
+{
+       switch (hostaddr->sa_family) {
+       case AF_INET:
+               return (ntohl(((struct sockaddr_in *)hostaddr)->
+                   sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
+       case AF_INET6:
+               return IN6_IS_ADDR_LOOPBACK(
+                   &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
+       default:
+               return 0;
+       }
+}
+
+/*
+ * Prepare the hostname and ip address strings that are used to lookup
+ * host keys in known_hosts files. These may have a port number appended.
+ */
+void
+get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
+    u_short port, char **hostfile_hostname, char **hostfile_ipaddr)
+{
+       char ntop[NI_MAXHOST];
+       socklen_t addrlen;
+
+       switch (hostaddr == NULL ? -1 : hostaddr->sa_family) {
+       case -1:
+               addrlen = 0;
+               break;
+       case AF_INET:
+               addrlen = sizeof(struct sockaddr_in);
+               break;
+       case AF_INET6:
+               addrlen = sizeof(struct sockaddr_in6);
+               break;
+       default:
+               addrlen = sizeof(struct sockaddr);
+               break;
+       }
+
+       /*
+        * We don't have the remote ip-address for connections
+        * using a proxy command
+        */
+       if (hostfile_ipaddr != NULL) {
+               if (options.proxy_command == NULL) {
+                       if (getnameinfo(hostaddr, addrlen,
+                           ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
+                       fatal("check_host_key: getnameinfo failed");
+                       *hostfile_ipaddr = put_host_port(ntop, port);
+               } else {
+                       *hostfile_ipaddr = xstrdup("<no hostip for proxy "
+                           "command>");
+               }
+       }
+
+       /*
+        * Allow the user to record the key under a different name or
+        * differentiate a non-standard port.  This is useful for ssh
+        * tunneling over forwarded connections or if you run multiple
+        * sshd's on different ports on the same machine.
+        */
+       if (hostfile_hostname != NULL) {
+               if (options.host_key_alias != NULL) {
+                       *hostfile_hostname = xstrdup(options.host_key_alias);
+                       debug("using hostkeyalias: %s", *hostfile_hostname);
+               } else {
+                       *hostfile_hostname = put_host_port(hostname, port);
+               }
+       }
+}
+
+/*
+ * check whether the supplied host key is valid, return -1 if the key
+ * is not valid. user_hostfile[0] will not be updated if 'readonly' is true.
+ */
+#define RDRW   0
+#define RDONLY 1
+#define ROQUIET        2
+static int
+check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
+    Key *host_key, int readonly,
+    char **user_hostfiles, u_int num_user_hostfiles,
+    char **system_hostfiles, u_int num_system_hostfiles)
+{
+       HostStatus host_status;
+       HostStatus ip_status;
+       Key *raw_key = NULL;
+       char *ip = NULL, *host = NULL;
+       char hostline[1000], *hostp, *fp, *ra;
+       char msg[1024];
+       const char *type;
+       const struct hostkey_entry *host_found, *ip_found;
+       int len, cancelled_forwarding = 0;
+       int local = sockaddr_is_local(hostaddr);
+       int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
+       struct hostkeys *host_hostkeys, *ip_hostkeys;
+       u_int i;
+
+       /*
+        * Force accepting of the host key for loopback/localhost. The
+        * problem is that if the home directory is NFS-mounted to multiple
+        * machines, localhost will refer to a different machine in each of
+        * them, and the user will get bogus HOST_CHANGED warnings.  This
+        * essentially disables host authentication for localhost; however,
+        * this is probably not a real problem.
+        */
+       if (options.no_host_authentication_for_localhost == 1 && local &&
+           options.host_key_alias == NULL) {
+               debug("Forcing accepting of host key for "
+                   "loopback/localhost.");
+               return 0;
+       }
+
+       /*
+        * Prepare the hostname and address strings used for hostkey lookup.
+        * In some cases, these will have a port number appended.
+        */
+       get_hostfile_hostname_ipaddr(hostname, hostaddr, port, &host, &ip);
+
+       /*
+        * Turn off check_host_ip if the connection is to localhost, via proxy
+        * command or if we don't have a hostname to compare with
+        */
+       if (options.check_host_ip && (local ||
+           strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
+               options.check_host_ip = 0;
+
+       host_hostkeys = init_hostkeys();
+       for (i = 0; i < num_user_hostfiles; i++)
+               load_hostkeys(host_hostkeys, host, user_hostfiles[i]);
+       for (i = 0; i < num_system_hostfiles; i++)
+               load_hostkeys(host_hostkeys, host, system_hostfiles[i]);
+
+       ip_hostkeys = NULL;
+       if (!want_cert && options.check_host_ip) {
+               ip_hostkeys = init_hostkeys();
+               for (i = 0; i < num_user_hostfiles; i++)
+                       load_hostkeys(ip_hostkeys, ip, user_hostfiles[i]);
+               for (i = 0; i < num_system_hostfiles; i++)
+                       load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]);
+       }
+
+ retry:
+       /* Reload these as they may have changed on cert->key downgrade */
+       want_cert = key_is_cert(host_key);
+       type = key_type(host_key);
+
+       /*
+        * Check if the host key is present in the user's list of known
+        * hosts or in the systemwide list.
+        */
+       host_status = check_key_in_hostkeys(host_hostkeys, host_key,
+           &host_found);
+
+       /*
+        * Also perform check for the ip address, skip the check if we are
+        * localhost, looking for a certificate, or the hostname was an ip
+        * address to begin with.
+        */
+       if (!want_cert && ip_hostkeys != NULL) {
+               ip_status = check_key_in_hostkeys(ip_hostkeys, host_key,
+                   &ip_found);
+               if (host_status == HOST_CHANGED &&
+                   (ip_status != HOST_CHANGED || 
+                   (ip_found != NULL &&
+                   !key_equal(ip_found->key, host_found->key))))
+                       host_ip_differ = 1;
+       } else
+               ip_status = host_status;
+
+       switch (host_status) {
+       case HOST_OK:
+               /* The host is known and the key matches. */
+               debug("Host '%.200s' is known and matches the %s host %s.",
+                   host, type, want_cert ? "certificate" : "key");
+               debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
+                   host_found->file, host_found->line);
+               if (want_cert && !check_host_cert(hostname, host_key))
+                       goto fail;
+               if (options.check_host_ip && ip_status == HOST_NEW) {
+                       if (readonly || want_cert)
+                               logit("%s host key for IP address "
+                                   "'%.128s' not in list of known hosts.",
+                                   type, ip);
+                       else if (!add_host_to_hostfile(user_hostfiles[0], ip,
+                           host_key, options.hash_known_hosts))
+                               logit("Failed to add the %s host key for IP "
+                                   "address '%.128s' to the list of known "
+                                   "hosts (%.30s).", type, ip,
+                                   user_hostfiles[0]);
+                       else
+                               logit("Warning: Permanently added the %s host "
+                                   "key for IP address '%.128s' to the list "
+                                   "of known hosts.", type, ip);
+               } else if (options.visual_host_key) {
+                       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+                       ra = key_fingerprint(host_key, SSH_FP_MD5,
+                           SSH_FP_RANDOMART);
+                       logit("Host key fingerprint is %s\n%s\n", fp, ra);
+                       xfree(ra);
+                       xfree(fp);
+               }
+               break;
+       case HOST_NEW:
+               if (options.host_key_alias == NULL && port != 0 &&
+                   port != SSH_DEFAULT_PORT) {
+                       debug("checking without port identifier");
+                       if (check_host_key(hostname, hostaddr, 0, host_key,
+                           ROQUIET, user_hostfiles, num_user_hostfiles,
+                           system_hostfiles, num_system_hostfiles) == 0) {
+                               debug("found matching key w/out port");
+                               break;
+                       }
+               }
+               if (readonly || want_cert)
+                       goto fail;
+               /* The host is new. */
+               if (options.strict_host_key_checking == 1) {
+                       /*
+                        * User has requested strict host key checking.  We
+                        * will not add the host key automatically.  The only
+                        * alternative left is to abort.
+                        */
+                       error("No %s host key is known for %.200s and you "
+                           "have requested strict checking.", type, host);
+                       goto fail;
+               } else if (options.strict_host_key_checking == 2) {
+                       char msg1[1024], msg2[1024];
+
+                       if (show_other_keys(host_hostkeys, host_key))
+                               snprintf(msg1, sizeof(msg1),
+                                   "\nbut keys of different type are already"
+                                   " known for this host.");
+                       else
+                               snprintf(msg1, sizeof(msg1), ".");
+                       /* The default */
+                       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+                       ra = key_fingerprint(host_key, SSH_FP_MD5,
+                           SSH_FP_RANDOMART);
+                       msg2[0] = '\0';
+                       if (options.verify_host_key_dns) {
+                               if (matching_host_key_dns)
+                                       snprintf(msg2, sizeof(msg2),
+                                           "Matching host key fingerprint"
+                                           " found in DNS.\n");
+                               else
+                                       snprintf(msg2, sizeof(msg2),
+                                           "No matching host key fingerprint"
+                                           " found in DNS.\n");
+                       }
+                       snprintf(msg, sizeof(msg),
+                           "The authenticity of host '%.200s (%s)' can't be "
+                           "established%s\n"
+                           "%s key fingerprint is %s.%s%s\n%s"
+                           "Are you sure you want to continue connecting "
+                           "(yes/no)? ",
+                           host, ip, msg1, type, fp,
+                           options.visual_host_key ? "\n" : "",
+                           options.visual_host_key ? ra : "",
+                           msg2);
+                       xfree(ra);
+                       xfree(fp);
+                       if (!confirm(msg))
+                               goto fail;
+               }
+               /*
+                * If not in strict mode, add the key automatically to the
+                * local known_hosts file.
+                */
+               if (options.check_host_ip && ip_status == HOST_NEW) {
+                       snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
+                       hostp = hostline;
+                       if (options.hash_known_hosts) {
+                               /* Add hash of host and IP separately */
+                               r = add_host_to_hostfile(user_hostfiles[0],
+                                   host, host_key, options.hash_known_hosts) &&
+                                   add_host_to_hostfile(user_hostfiles[0], ip,
+                                   host_key, options.hash_known_hosts);
+                       } else {
+                               /* Add unhashed "host,ip" */
+                               r = add_host_to_hostfile(user_hostfiles[0],
+                                   hostline, host_key,
+                                   options.hash_known_hosts);
+                       }
+               } else {
+                       r = add_host_to_hostfile(user_hostfiles[0], host,
+                           host_key, options.hash_known_hosts);
+                       hostp = host;
+               }
+
+               if (!r)
+                       logit("Failed to add the host to the list of known "
+                           "hosts (%.500s).", user_hostfiles[0]);
+               else
+                       logit("Warning: Permanently added '%.200s' (%s) to the "
+                           "list of known hosts.", hostp, type);
+               break;
+       case HOST_REVOKED:
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("@       WARNING: REVOKED HOST KEY DETECTED!               @");
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("The %s host key for %s is marked as revoked.", type, host);
+               error("This could mean that a stolen key is being used to");
+               error("impersonate this host.");
+
+               /*
+                * If strict host key checking is in use, the user will have
+                * to edit the key manually and we can only abort.
+                */
+               if (options.strict_host_key_checking) {
+                       error("%s host key for %.200s was revoked and you have "
+                           "requested strict checking.", type, host);
+                       goto fail;
+               }
+               goto continue_unsafe;
+
+       case HOST_CHANGED:
+               if (want_cert) {
+                       /*
+                        * This is only a debug() since it is valid to have
+                        * CAs with wildcard DNS matches that don't match
+                        * all hosts that one might visit.
+                        */
+                       debug("Host certificate authority does not "
+                           "match %s in %s:%lu", CA_MARKER,
+                           host_found->file, host_found->line);
+                       goto fail;
+               }
+               if (readonly == ROQUIET)
+                       goto fail;
+               if (options.check_host_ip && host_ip_differ) {
+                       char *key_msg;
+                       if (ip_status == HOST_NEW)
+                               key_msg = "is unknown";
+                       else if (ip_status == HOST_OK)
+                               key_msg = "is unchanged";
+                       else
+                               key_msg = "has a different value";
+                       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+                       error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
+                       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+                       error("The %s host key for %s has changed,", type, host);
+                       error("and the key for the corresponding IP address %s", ip);
+                       error("%s. This could either mean that", key_msg);
+                       error("DNS SPOOFING is happening or the IP address for the host");
+                       error("and its host key have changed at the same time.");
+                       if (ip_status != HOST_NEW)
+                               error("Offending key for IP in %s:%lu",
+                                   ip_found->file, ip_found->line);
+               }
+               /* The host key has changed. */
+               warn_changed_key(host_key);
+               error("Add correct host key in %.100s to get rid of this message.",
+                   user_hostfiles[0]);
+               error("Offending %s key in %s:%lu", key_type(host_found->key),
+                   host_found->file, host_found->line);
+
+               /*
+                * If strict host key checking is in use, the user will have
+                * to edit the key manually and we can only abort.
+                */
+               if (options.strict_host_key_checking) {
+                       error("%s host key for %.200s has changed and you have "
+                           "requested strict checking.", type, host);
+                       goto fail;
+               }
+
+ continue_unsafe:
+               /*
+                * If strict host key checking has not been requested, allow
+                * the connection but without MITM-able authentication or
+                * forwarding.
+                */
+               if (options.password_authentication) {
+                       error("Password authentication is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.password_authentication = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.kbd_interactive_authentication) {
+                       error("Keyboard-interactive authentication is disabled"
+                           " to avoid man-in-the-middle attacks.");
+                       options.kbd_interactive_authentication = 0;
+                       options.challenge_response_authentication = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.challenge_response_authentication) {
+                       error("Challenge/response authentication is disabled"
+                           " to avoid man-in-the-middle attacks.");
+                       options.challenge_response_authentication = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.forward_agent) {
+                       error("Agent forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.forward_agent = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.forward_x11) {
+                       error("X11 forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.forward_x11 = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.num_local_forwards > 0 ||
+                   options.num_remote_forwards > 0) {
+                       error("Port forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.num_local_forwards =
+                           options.num_remote_forwards = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.tun_open != SSH_TUNMODE_NO) {
+                       error("Tunnel forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.tun_open = SSH_TUNMODE_NO;
+                       cancelled_forwarding = 1;
+               }
+               if (options.exit_on_forward_failure && cancelled_forwarding)
+                       fatal("Error: forwarding disabled due to host key "
+                           "check failure");
+               
+               /*
+                * XXX Should permit the user to change to use the new id.
+                * This could be done by converting the host key to an
+                * identifying sentence, tell that the host identifies itself
+                * by that sentence, and ask the user if he/she wishes to
+                * accept the authentication.
+                */
+               break;
+       case HOST_FOUND:
+               fatal("internal error");
+               break;
+       }
+
+       if (options.check_host_ip && host_status != HOST_CHANGED &&
+           ip_status == HOST_CHANGED) {
+               snprintf(msg, sizeof(msg),
+                   "Warning: the %s host key for '%.200s' "
+                   "differs from the key for the IP address '%.128s'"
+                   "\nOffending key for IP in %s:%lu",
+                   type, host, ip, ip_found->file, ip_found->line);
+               if (host_status == HOST_OK) {
+                       len = strlen(msg);
+                       snprintf(msg + len, sizeof(msg) - len,
+                           "\nMatching host key in %s:%lu",
+                           host_found->file, host_found->line);
+               }
+               if (options.strict_host_key_checking == 1) {
+                       logit("%s", msg);
+                       error("Exiting, you have requested strict checking.");
+                       goto fail;
+               } else if (options.strict_host_key_checking == 2) {
+                       strlcat(msg, "\nAre you sure you want "
+                           "to continue connecting (yes/no)? ", sizeof(msg));
+                       if (!confirm(msg))
+                               goto fail;
+               } else {
+                       logit("%s", msg);
+               }
+       }
+
+       xfree(ip);
+       xfree(host);
+       if (host_hostkeys != NULL)
+               free_hostkeys(host_hostkeys);
+       if (ip_hostkeys != NULL)
+               free_hostkeys(ip_hostkeys);
+       return 0;
+
+fail:
+       if (want_cert && host_status != HOST_REVOKED) {
+               /*
+                * No matching certificate. Downgrade cert to raw key and
+                * search normally.
+                */
+               debug("No matching CA found. Retry with plain key");
+               raw_key = key_from_private(host_key);
+               if (key_drop_cert(raw_key) != 0)
+                       fatal("Couldn't drop certificate");
+               host_key = raw_key;
+               goto retry;
+       }
+       if (raw_key != NULL)
+               key_free(raw_key);
+       xfree(ip);
+       xfree(host);
+       if (host_hostkeys != NULL)
+               free_hostkeys(host_hostkeys);
+       if (ip_hostkeys != NULL)
+               free_hostkeys(ip_hostkeys);
+       return -1;
+}
+
+/* returns 0 if key verifies or -1 if key does NOT verify */
+int
+verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
+{
+       int flags = 0;
+       char *fp;
+
+       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+       debug("Server host key: %s %s", key_type(host_key), fp);
+       xfree(fp);
+
+       /* XXX certs are not yet supported for DNS */
+       if (!key_is_cert(host_key) && options.verify_host_key_dns &&
+           verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
+               if (flags & DNS_VERIFY_FOUND) {
+
+                       if (options.verify_host_key_dns == 1 &&
+                           flags & DNS_VERIFY_MATCH &&
+                           flags & DNS_VERIFY_SECURE)
+                               return 0;
+
+                       if (flags & DNS_VERIFY_MATCH) {
+                               matching_host_key_dns = 1;
+                       } else {
+                               warn_changed_key(host_key);
+                               error("Update the SSHFP RR in DNS with the new "
+                                   "host key to get rid of this message.");
+                       }
+               }
+       }
+
+       return check_host_key(host, hostaddr, options.port, host_key, RDRW,
+           options.user_hostfiles, options.num_user_hostfiles,
+           options.system_hostfiles, options.num_system_hostfiles);
+}
+
+/*
+ * Starts a dialog with the server, and authenticates the current user on the
+ * server.  This does not need any extra privileges.  The basic connection
+ * to the server must already have been established before this is called.
+ * If login fails, this function prints an error and never returns.
+ * This function does not require super-user privileges.
+ */
+void
+ssh_login(Sensitive *sensitive, const char *orighost,
+    struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
+{
+       char *host, *cp;
+       char *server_user, *local_user;
+
+       local_user = xstrdup(pw->pw_name);
+       server_user = options.user ? options.user : local_user;
+
+       /* Convert the user-supplied hostname into all lowercase. */
+       host = xstrdup(orighost);
+       for (cp = host; *cp; cp++)
+               if (isupper(*cp))
+                       *cp = (char)tolower(*cp);
+
+       /* Exchange protocol version identification strings with the server. */
+       ssh_exchange_identification(timeout_ms);
+
+       /* Put the connection into non-blocking mode. */
+       packet_set_nonblocking();
+
+       /* key exchange */
+       /* authenticate user */
+       if (compat20) {
+               ssh_kex2(host, hostaddr, port);
+               ssh_userauth2(local_user, server_user, host, sensitive);
+       } else {
+               ssh_kex(host, hostaddr);
+               ssh_userauth1(local_user, server_user, host, sensitive);
+       }
+       xfree(local_user);
+}
+
+void
+ssh_put_password(char *password)
+{
+       int size;
+       char *padded;
+
+       if (datafellows & SSH_BUG_PASSWORDPAD) {
+               packet_put_cstring(password);
+               return;
+       }
+       size = roundup(strlen(password) + 1, 32);
+       padded = xcalloc(1, size);
+       strlcpy(padded, password, size);
+       packet_put_string(padded, size);
+       memset(padded, 0, size);
+       xfree(padded);
+}
+
+/* print all known host keys for a given host, but skip keys of given type */
+static int
+show_other_keys(struct hostkeys *hostkeys, Key *key)
+{
+       int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1};
+       int i, ret = 0;
+       char *fp, *ra;
+       const struct hostkey_entry *found;
+
+       for (i = 0; type[i] != -1; i++) {
+               if (type[i] == key->type)
+                       continue;
+               if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
+                       continue;
+               fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
+               ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
+               logit("WARNING: %s key found for host %s\n"
+                   "in %s:%lu\n"
+                   "%s key fingerprint %s.",
+                   key_type(found->key),
+                   found->host, found->file, found->line,
+                   key_type(found->key), fp);
+               if (options.visual_host_key)
+                       logit("%s", ra);
+               xfree(ra);
+               xfree(fp);
+               ret = 1;
+       }
+       return ret;
+}
+
+static void
+warn_changed_key(Key *host_key)
+{
+       char *fp;
+
+       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+
+       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+       error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
+       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+       error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
+       error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
+       error("It is also possible that a host key has just been changed.");
+       error("The fingerprint for the %s key sent by the remote host is\n%s.",
+           key_type(host_key), fp);
+       error("Please contact your system administrator.");
+
+       xfree(fp);
+}
+
+/*
+ * Execute a local command
+ */
+int
+ssh_local_cmd(const char *args)
+{
+       char *shell;
+       pid_t pid;
+       int status;
+       void (*osighand)(int);
+
+       if (!options.permit_local_command ||
+           args == NULL || !*args)
+               return (1);
+
+       if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
+               shell = _PATH_BSHELL;
+
+       osighand = signal(SIGCHLD, SIG_DFL);
+       pid = fork();
+       if (pid == 0) {
+               signal(SIGPIPE, SIG_DFL);
+               debug3("Executing %s -c \"%s\"", shell, args);
+               execlp(shell, shell, "-c", args, (char *)NULL);
+               error("Couldn't execute %s -c \"%s\": %s",
+                   shell, args, strerror(errno));
+               _exit(1);
+       } else if (pid == -1)
+               fatal("fork failed: %.100s", strerror(errno));
+       while (waitpid(pid, &status, 0) == -1)
+               if (errno != EINTR)
+                       fatal("Couldn't wait for child: %s", strerror(errno));
+       signal(SIGCHLD, osighand);
+
+       if (!WIFEXITED(status))
+               return (1);
+
+       return (WEXITSTATUS(status));
+}
diff --git a/.pc/package-versioning.patch/sshd.c b/.pc/package-versioning.patch/sshd.c
new file mode 100644 (file)
index 0000000..b3477c3
--- /dev/null
@@ -0,0 +1,2486 @@
+/* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * This program is the ssh daemon.  It listens for connections from clients,
+ * and performs authentication, executes use commands or shell, and forwards
+ * information to/from the application to the user client over an encrypted
+ * connection.  This can also handle forwarding of X11, TCP/IP, and
+ * authentication agent connections.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 implementation:
+ * Privilege Separation:
+ *
+ * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2002 Niels Provos.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include "openbsd-compat/sys-tree.h"
+#include "openbsd-compat/sys-queue.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/md5.h>
+#include <openssl/rand.h>
+#include "openbsd-compat/openssl-compat.h"
+
+#ifdef HAVE_SECUREWARE
+#include <sys/security.h>
+#include <prot.h>
+#endif
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "rsa.h"
+#include "sshpty.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "dh.h"
+#include "myproposal.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "atomicio.h"
+#include "canohost.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "misc.h"
+#include "msg.h"
+#include "dispatch.h"
+#include "channels.h"
+#include "session.h"
+#include "monitor_mm.h"
+#include "monitor.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "roaming.h"
+#include "ssh-sandbox.h"
+#include "version.h"
+
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
+
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int allow_severity;
+int deny_severity;
+#endif /* LIBWRAP */
+
+#ifndef O_NOCTTY
+#define O_NOCTTY       0
+#endif
+
+/* Re-exec fds */
+#define REEXEC_DEVCRYPTO_RESERVED_FD   (STDERR_FILENO + 1)
+#define REEXEC_STARTUP_PIPE_FD         (STDERR_FILENO + 2)
+#define REEXEC_CONFIG_PASS_FD          (STDERR_FILENO + 3)
+#define REEXEC_MIN_FREE_FD             (STDERR_FILENO + 4)
+
+extern char *__progname;
+
+/* Server configuration options. */
+ServerOptions options;
+
+/* Name of the server configuration file. */
+char *config_file_name = _PATH_SERVER_CONFIG_FILE;
+
+/*
+ * Debug mode flag.  This can be set on the command line.  If debug
+ * mode is enabled, extra debugging output will be sent to the system
+ * log, the daemon will not go to background, and will exit after processing
+ * the first connection.
+ */
+int debug_flag = 0;
+
+/* Flag indicating that the daemon should only test the configuration and keys. */
+int test_flag = 0;
+
+/* Flag indicating that the daemon is being started from inetd. */
+int inetd_flag = 0;
+
+/* Flag indicating that sshd should not detach and become a daemon. */
+int no_daemon_flag = 0;
+
+/* debug goes to stderr unless inetd_flag is set */
+int log_stderr = 0;
+
+/* Saved arguments to main(). */
+char **saved_argv;
+int saved_argc;
+
+/* re-exec */
+int rexeced_flag = 0;
+int rexec_flag = 1;
+int rexec_argc = 0;
+char **rexec_argv;
+
+/*
+ * The sockets that the server is listening; this is used in the SIGHUP
+ * signal handler.
+ */
+#define        MAX_LISTEN_SOCKS        16
+int listen_socks[MAX_LISTEN_SOCKS];
+int num_listen_socks = 0;
+
+/*
+ * the client's version string, passed by sshd2 in compat mode. if != NULL,
+ * sshd will skip the version-number exchange
+ */
+char *client_version_string = NULL;
+char *server_version_string = NULL;
+
+/* for rekeying XXX fixme */
+Kex *xxx_kex;
+
+/*
+ * Any really sensitive data in the application is contained in this
+ * structure. The idea is that this structure could be locked into memory so
+ * that the pages do not get written into swap.  However, there are some
+ * problems. The private key contains BIGNUMs, and we do not (in principle)
+ * have access to the internals of them, and locking just the structure is
+ * not very useful.  Currently, memory locking is not implemented.
+ */
+struct {
+       Key     *server_key;            /* ephemeral server key */
+       Key     *ssh1_host_key;         /* ssh1 host key */
+       Key     **host_keys;            /* all private host keys */
+       Key     **host_certificates;    /* all public host certificates */
+       int     have_ssh1_key;
+       int     have_ssh2_key;
+       u_char  ssh1_cookie[SSH_SESSION_KEY_LENGTH];
+} sensitive_data;
+
+/*
+ * Flag indicating whether the RSA server key needs to be regenerated.
+ * Is set in the SIGALRM handler and cleared when the key is regenerated.
+ */
+static volatile sig_atomic_t key_do_regen = 0;
+
+/* This is set to true when a signal is received. */
+static volatile sig_atomic_t received_sighup = 0;
+static volatile sig_atomic_t received_sigterm = 0;
+
+/* session identifier, used by RSA-auth */
+u_char session_id[16];
+
+/* same for ssh2 */
+u_char *session_id2 = NULL;
+u_int session_id2_len = 0;
+
+/* record remote hostname or ip */
+u_int utmp_len = MAXHOSTNAMELEN;
+
+/* options.max_startup sized array of fd ints */
+int *startup_pipes = NULL;
+int startup_pipe;              /* in child */
+
+/* variables used for privilege separation */
+int use_privsep = -1;
+struct monitor *pmonitor = NULL;
+
+/* global authentication context */
+Authctxt *the_authctxt = NULL;
+
+/* sshd_config buffer */
+Buffer cfg;
+
+/* message to be displayed after login */
+Buffer loginmsg;
+
+/* Unprivileged user */
+struct passwd *privsep_pw = NULL;
+
+/* Prototypes for various functions defined later in this file. */
+void destroy_sensitive_data(void);
+void demote_sensitive_data(void);
+
+static void do_ssh1_kex(void);
+static void do_ssh2_kex(void);
+
+/*
+ * Close all listening sockets
+ */
+static void
+close_listen_socks(void)
+{
+       int i;
+
+       for (i = 0; i < num_listen_socks; i++)
+               close(listen_socks[i]);
+       num_listen_socks = -1;
+}
+
+static void
+close_startup_pipes(void)
+{
+       int i;
+
+       if (startup_pipes)
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               close(startup_pipes[i]);
+}
+
+/*
+ * Signal handler for SIGHUP.  Sshd execs itself when it receives SIGHUP;
+ * the effect is to reread the configuration file (and to regenerate
+ * the server key).
+ */
+
+/*ARGSUSED*/
+static void
+sighup_handler(int sig)
+{
+       int save_errno = errno;
+
+       received_sighup = 1;
+       signal(SIGHUP, sighup_handler);
+       errno = save_errno;
+}
+
+/*
+ * Called from the main program after receiving SIGHUP.
+ * Restarts the server.
+ */
+static void
+sighup_restart(void)
+{
+       logit("Received SIGHUP; restarting.");
+       close_listen_socks();
+       close_startup_pipes();
+       alarm(0);  /* alarm timer persists across exec */
+       signal(SIGHUP, SIG_IGN); /* will be restored after exec */
+       execv(saved_argv[0], saved_argv);
+       logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
+           strerror(errno));
+       exit(1);
+}
+
+/*
+ * Generic signal handler for terminating signals in the master daemon.
+ */
+/*ARGSUSED*/
+static void
+sigterm_handler(int sig)
+{
+       received_sigterm = sig;
+}
+
+/*
+ * SIGCHLD handler.  This is called whenever a child dies.  This will then
+ * reap any zombies left by exited children.
+ */
+/*ARGSUSED*/
+static void
+main_sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+           (pid < 0 && errno == EINTR))
+               ;
+
+       signal(SIGCHLD, main_sigchld_handler);
+       errno = save_errno;
+}
+
+/*
+ * Signal handler for the alarm after the login grace period has expired.
+ */
+/*ARGSUSED*/
+static void
+grace_alarm_handler(int sig)
+{
+       if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
+               kill(pmonitor->m_pid, SIGALRM);
+
+       /* Log error and exit. */
+       sigdie("Timeout before authentication for %s", get_remote_ipaddr());
+}
+
+/*
+ * Signal handler for the key regeneration alarm.  Note that this
+ * alarm only occurs in the daemon waiting for connections, and it does not
+ * do anything with the private key or random state before forking.
+ * Thus there should be no concurrency control/asynchronous execution
+ * problems.
+ */
+static void
+generate_ephemeral_server_key(void)
+{
+       verbose("Generating %s%d bit RSA key.",
+           sensitive_data.server_key ? "new " : "", options.server_key_bits);
+       if (sensitive_data.server_key != NULL)
+               key_free(sensitive_data.server_key);
+       sensitive_data.server_key = key_generate(KEY_RSA1,
+           options.server_key_bits);
+       verbose("RSA key generation complete.");
+
+       arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+       arc4random_stir();
+}
+
+/*ARGSUSED*/
+static void
+key_regeneration_alarm(int sig)
+{
+       int save_errno = errno;
+
+       signal(SIGALRM, SIG_DFL);
+       errno = save_errno;
+       key_do_regen = 1;
+}
+
+static void
+sshd_exchange_identification(int sock_in, int sock_out)
+{
+       u_int i;
+       int mismatch;
+       int remote_major, remote_minor;
+       int major, minor;
+       char *s, *newline = "\n";
+       char buf[256];                  /* Must not be larger than remote_version. */
+       char remote_version[256];       /* Must be at least as big as buf. */
+
+       if ((options.protocol & SSH_PROTO_1) &&
+           (options.protocol & SSH_PROTO_2)) {
+               major = PROTOCOL_MAJOR_1;
+               minor = 99;
+       } else if (options.protocol & SSH_PROTO_2) {
+               major = PROTOCOL_MAJOR_2;
+               minor = PROTOCOL_MINOR_2;
+               newline = "\r\n";
+       } else {
+               major = PROTOCOL_MAJOR_1;
+               minor = PROTOCOL_MINOR_1;
+       }
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+           SSH_VERSION, newline);
+       server_version_string = xstrdup(buf);
+
+       /* Send our protocol version identification. */
+       if (roaming_atomicio(vwrite, sock_out, server_version_string,
+           strlen(server_version_string))
+           != strlen(server_version_string)) {
+               logit("Could not write ident string to %s", get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+
+       /* Read other sides version identification. */
+       memset(buf, 0, sizeof(buf));
+       for (i = 0; i < sizeof(buf) - 1; i++) {
+               if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {
+                       logit("Did not receive identification string from %s",
+                           get_remote_ipaddr());
+                       cleanup_exit(255);
+               }
+               if (buf[i] == '\r') {
+                       buf[i] = 0;
+                       /* Kludge for F-Secure Macintosh < 1.0.2 */
+                       if (i == 12 &&
+                           strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
+                               break;
+                       continue;
+               }
+               if (buf[i] == '\n') {
+                       buf[i] = 0;
+                       break;
+               }
+       }
+       buf[sizeof(buf) - 1] = 0;
+       client_version_string = xstrdup(buf);
+
+       /*
+        * Check that the versions match.  In future this might accept
+        * several versions and set appropriate flags to handle them.
+        */
+       if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
+           &remote_major, &remote_minor, remote_version) != 3) {
+               s = "Protocol mismatch.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Bad protocol version identification '%.100s' from %s",
+                   client_version_string, get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+       debug("Client protocol version %d.%d; client software version %.100s",
+           remote_major, remote_minor, remote_version);
+
+       compat_datafellows(remote_version);
+
+       if (datafellows & SSH_BUG_PROBE) {
+               logit("probed from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       if (datafellows & SSH_BUG_SCANNER) {
+               logit("scanned from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       mismatch = 0;
+       switch (remote_major) {
+       case 1:
+               if (remote_minor == 99) {
+                       if (options.protocol & SSH_PROTO_2)
+                               enable_compat20();
+                       else
+                               mismatch = 1;
+                       break;
+               }
+               if (!(options.protocol & SSH_PROTO_1)) {
+                       mismatch = 1;
+                       break;
+               }
+               if (remote_minor < 3) {
+                       packet_disconnect("Your ssh version is too old and "
+                           "is no longer supported.  Please install a newer version.");
+               } else if (remote_minor == 3) {
+                       /* note that this disables agent-forwarding */
+                       enable_compat13();
+               }
+               break;
+       case 2:
+               if (options.protocol & SSH_PROTO_2) {
+                       enable_compat20();
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               mismatch = 1;
+               break;
+       }
+       chop(server_version_string);
+       debug("Local version string %.200s", server_version_string);
+
+       if (mismatch) {
+               s = "Protocol major versions differ.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Protocol major versions differ for %s: %.200s vs. %.200s",
+                   get_remote_ipaddr(),
+                   server_version_string, client_version_string);
+               cleanup_exit(255);
+       }
+}
+
+/* Destroy the host and server keys.  They will no longer be needed. */
+void
+destroy_sensitive_data(void)
+{
+       int i;
+
+       if (sensitive_data.server_key) {
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = NULL;
+       }
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = NULL;
+               }
+               if (sensitive_data.host_certificates[i]) {
+                       key_free(sensitive_data.host_certificates[i]);
+                       sensitive_data.host_certificates[i] = NULL;
+               }
+       }
+       sensitive_data.ssh1_host_key = NULL;
+       memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
+}
+
+/* Demote private to public keys for network child */
+void
+demote_sensitive_data(void)
+{
+       Key *tmp;
+       int i;
+
+       if (sensitive_data.server_key) {
+               tmp = key_demote(sensitive_data.server_key);
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = tmp;
+       }
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       tmp = key_demote(sensitive_data.host_keys[i]);
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = tmp;
+                       if (tmp->type == KEY_RSA1)
+                               sensitive_data.ssh1_host_key = tmp;
+               }
+               /* Certs do not need demotion */
+       }
+
+       /* We do not clear ssh1_host key and cookie.  XXX - Okay Niels? */
+}
+
+static void
+privsep_preauth_child(void)
+{
+       u_int32_t rnd[256];
+       gid_t gidset[1];
+
+       /* Enable challenge-response authentication for privilege separation */
+       privsep_challenge_enable();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       /* Change our root directory */
+       if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+               fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+                   strerror(errno));
+       if (chdir("/") == -1)
+               fatal("chdir(\"/\"): %s", strerror(errno));
+
+       /* Drop our privileges */
+       debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
+           (u_int)privsep_pw->pw_gid);
+#if 0
+       /* XXX not ready, too heavy after chroot */
+       do_setusercontext(privsep_pw);
+#else
+       gidset[0] = privsep_pw->pw_gid;
+       if (setgroups(1, gidset) < 0)
+               fatal("setgroups: %.100s", strerror(errno));
+       permanently_set_uid(privsep_pw);
+#endif
+}
+
+static int
+privsep_preauth(Authctxt *authctxt)
+{
+       int status;
+       pid_t pid;
+       struct ssh_sandbox *box = NULL;
+
+       /* Set up unprivileged child process to deal with network data */
+       pmonitor = monitor_init();
+       /* Store a pointer to the kex for later rekeying */
+       pmonitor->m_pkex = &xxx_kex;
+
+       if (use_privsep == PRIVSEP_SANDBOX)
+               box = ssh_sandbox_init();
+       pid = fork();
+       if (pid == -1) {
+               fatal("fork of unprivileged child failed");
+       } else if (pid != 0) {
+               debug2("Network child is on pid %ld", (long)pid);
+
+               if (box != NULL)
+                       ssh_sandbox_parent_preauth(box, pid);
+               pmonitor->m_pid = pid;
+               monitor_child_preauth(authctxt, pmonitor);
+
+               /* Sync memory */
+               monitor_sync(pmonitor);
+
+               /* Wait for the child's exit status */
+               while (waitpid(pid, &status, 0) < 0) {
+                       if (errno != EINTR)
+                               fatal("%s: waitpid: %s", __func__,
+                                   strerror(errno));
+               }
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status) != 0)
+                               fatal("%s: preauth child exited with status %d",
+                                   __func__, WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status))
+                       fatal("%s: preauth child terminated by signal %d",
+                           __func__, WTERMSIG(status));
+               if (box != NULL)
+                       ssh_sandbox_parent_finish(box);
+               return 1;
+       } else {
+               /* child */
+               close(pmonitor->m_sendfd);
+               close(pmonitor->m_log_recvfd);
+
+               /* Arrange for logging to be sent to the monitor */
+               set_log_handler(mm_log_handler, pmonitor);
+
+               /* Demote the child */
+               if (getuid() == 0 || geteuid() == 0)
+                       privsep_preauth_child();
+               setproctitle("%s", "[net]");
+               if (box != NULL)
+                       ssh_sandbox_child(box);
+
+               return 0;
+       }
+}
+
+static void
+privsep_postauth(Authctxt *authctxt)
+{
+       u_int32_t rnd[256];
+
+#ifdef DISABLE_FD_PASSING
+       if (1) {
+#else
+       if (authctxt->pw->pw_uid == 0 || options.use_login) {
+#endif
+               /* File descriptor passing is broken or root login */
+               use_privsep = 0;
+               goto skip;
+       }
+
+       /* New socket pair */
+       monitor_reinit(pmonitor);
+
+       pmonitor->m_pid = fork();
+       if (pmonitor->m_pid == -1)
+               fatal("fork of unprivileged child failed");
+       else if (pmonitor->m_pid != 0) {
+               verbose("User child is on pid %ld", (long)pmonitor->m_pid);
+               buffer_clear(&loginmsg);
+               monitor_child_postauth(pmonitor);
+
+               /* NEVERREACHED */
+               exit(0);
+       }
+
+       /* child */
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Drop privileges */
+       do_setusercontext(authctxt->pw, authctxt->role);
+
+ skip:
+       /* It is safe now to apply the key state */
+       monitor_apply_keystate(pmonitor);
+
+       /*
+        * Tell the packet layer that authentication was successful, since
+        * this information is not part of the key state.
+        */
+       packet_set_authenticated();
+}
+
+static char *
+list_hostkey_types(void)
+{
+       Buffer b;
+       const char *p;
+       char *ret;
+       int i;
+       Key *key;
+
+       buffer_init(&b);
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = sensitive_data.host_keys[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+               /* If the private key has a cert peer, then list that too */
+               key = sensitive_data.host_certificates[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       ret = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       debug("list_hostkey_types: %s", ret);
+       return ret;
+}
+
+static Key *
+get_hostkey_by_type(int type, int need_private)
+{
+       int i;
+       Key *key;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               switch (type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       key = sensitive_data.host_certificates[i];
+                       break;
+               default:
+                       key = sensitive_data.host_keys[i];
+                       break;
+               }
+               if (key != NULL && key->type == type)
+                       return need_private ?
+                           sensitive_data.host_keys[i] : key;
+       }
+       return NULL;
+}
+
+Key *
+get_hostkey_public_by_type(int type)
+{
+       return get_hostkey_by_type(type, 0);
+}
+
+Key *
+get_hostkey_private_by_type(int type)
+{
+       return get_hostkey_by_type(type, 1);
+}
+
+Key *
+get_hostkey_by_index(int ind)
+{
+       if (ind < 0 || ind >= options.num_host_key_files)
+               return (NULL);
+       return (sensitive_data.host_keys[ind]);
+}
+
+int
+get_hostkey_index(Key *key)
+{
+       int i;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (key_is_cert(key)) {
+                       if (key == sensitive_data.host_certificates[i])
+                               return (i);
+               } else {
+                       if (key == sensitive_data.host_keys[i])
+                               return (i);
+               }
+       }
+       return (-1);
+}
+
+/*
+ * returns 1 if connection should be dropped, 0 otherwise.
+ * dropping starts at connection #max_startups_begin with a probability
+ * of (max_startups_rate/100). the probability increases linearly until
+ * all connections are dropped for startups > max_startups
+ */
+static int
+drop_connection(int startups)
+{
+       int p, r;
+
+       if (startups < options.max_startups_begin)
+               return 0;
+       if (startups >= options.max_startups)
+               return 1;
+       if (options.max_startups_rate == 100)
+               return 1;
+
+       p  = 100 - options.max_startups_rate;
+       p *= startups - options.max_startups_begin;
+       p /= options.max_startups - options.max_startups_begin;
+       p += options.max_startups_rate;
+       r = arc4random_uniform(100);
+
+       debug("drop_connection: p %d, r %d", p, r);
+       return (r < p) ? 1 : 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "%s, %s\n",
+           SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+       fprintf(stderr,
+"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
+"            [-f config_file] [-g login_grace_time] [-h host_key_file]\n"
+"            [-k key_gen_time] [-o option] [-p port] [-u len]\n"
+       );
+       exit(1);
+}
+
+static void
+send_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+
+       debug3("%s: entering fd = %d config len %d", __func__, fd,
+           buffer_len(conf));
+
+       /*
+        * Protocol from reexec master to child:
+        *      string  configuration
+        *      u_int   ephemeral_key_follows
+        *      bignum  e               (only if ephemeral_key_follows == 1)
+        *      bignum  n                       "
+        *      bignum  d                       "
+        *      bignum  iqmp                    "
+        *      bignum  p                       "
+        *      bignum  q                       "
+        *      string rngseed          (only if OpenSSL is not self-seeded)
+        */
+       buffer_init(&m);
+       buffer_put_cstring(&m, buffer_ptr(conf));
+
+       if (sensitive_data.server_key != NULL &&
+           sensitive_data.server_key->type == KEY_RSA1) {
+               buffer_put_int(&m, 1);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
+       } else
+               buffer_put_int(&m, 0);
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_send_rng_seed(&m);
+#endif
+
+       if (ssh_msg_send(fd, 0, &m) == -1)
+               fatal("%s: ssh_msg_send failed", __func__);
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+static void
+recv_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+       char *cp;
+       u_int len;
+
+       debug3("%s: entering fd = %d", __func__, fd);
+
+       buffer_init(&m);
+
+       if (ssh_msg_recv(fd, &m) == -1)
+               fatal("%s: ssh_msg_recv failed", __func__);
+       if (buffer_get_char(&m) != 0)
+               fatal("%s: rexec version mismatch", __func__);
+
+       cp = buffer_get_string(&m, &len);
+       if (conf != NULL)
+               buffer_append(conf, cp, len + 1);
+       xfree(cp);
+
+       if (buffer_get_int(&m)) {
+               if (sensitive_data.server_key != NULL)
+                       key_free(sensitive_data.server_key);
+               sensitive_data.server_key = key_new_private(KEY_RSA1);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
+               rsa_generate_additional_parameters(
+                   sensitive_data.server_key->rsa);
+       }
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_recv_rng_seed(&m);
+#endif
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+/* Accept a connection from inetd */
+static void
+server_accept_inetd(int *sock_in, int *sock_out)
+{
+       int fd;
+
+       startup_pipe = -1;
+       if (rexeced_flag) {
+               close(REEXEC_CONFIG_PASS_FD);
+               *sock_in = *sock_out = dup(STDIN_FILENO);
+               if (!debug_flag) {
+                       startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+                       close(REEXEC_STARTUP_PIPE_FD);
+               }
+       } else {
+               *sock_in = dup(STDIN_FILENO);
+               *sock_out = dup(STDOUT_FILENO);
+       }
+       /*
+        * We intentionally do not close the descriptors 0, 1, and 2
+        * as our code for setting the descriptors won't work if
+        * ttyfd happens to be one of those.
+        */
+       if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+               dup2(fd, STDIN_FILENO);
+               dup2(fd, STDOUT_FILENO);
+               if (fd > STDOUT_FILENO)
+                       close(fd);
+       }
+       debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
+}
+
+/*
+ * Listen for TCP connections
+ */
+static void
+server_listen(void)
+{
+       int ret, listen_sock, on = 1;
+       struct addrinfo *ai;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+
+       for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                       continue;
+               if (num_listen_socks >= MAX_LISTEN_SOCKS)
+                       fatal("Too many listen sockets. "
+                           "Enlarge MAX_LISTEN_SOCKS");
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                   ntop, sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           ssh_gai_strerror(ret));
+                       continue;
+               }
+               /* Create socket for listening. */
+               listen_sock = socket(ai->ai_family, ai->ai_socktype,
+                   ai->ai_protocol);
+               if (listen_sock < 0) {
+                       /* kernel may not support ipv6 */
+                       verbose("socket: %.100s", strerror(errno));
+                       continue;
+               }
+               if (set_nonblock(listen_sock) == -1) {
+                       close(listen_sock);
+                       continue;
+               }
+               /*
+                * Set socket options.
+                * Allow local port reuse in TIME_WAIT.
+                */
+               if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
+                   &on, sizeof(on)) == -1)
+                       error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+
+               /* Only communicate in IPv6 over AF_INET6 sockets. */
+               if (ai->ai_family == AF_INET6)
+                       sock_set_v6only(listen_sock);
+
+               debug("Bind to port %s on %s.", strport, ntop);
+
+               /* Bind the socket to the desired port. */
+               if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       error("Bind to port %s on %s failed: %.200s.",
+                           strport, ntop, strerror(errno));
+                       close(listen_sock);
+                       continue;
+               }
+               listen_socks[num_listen_socks] = listen_sock;
+               num_listen_socks++;
+
+               /* Start listening on the port. */
+               if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
+                       fatal("listen on [%s]:%s: %.100s",
+                           ntop, strport, strerror(errno));
+               logit("Server listening on %s port %s.", ntop, strport);
+       }
+       freeaddrinfo(options.listen_addrs);
+
+       if (!num_listen_socks)
+               fatal("Cannot bind any address.");
+}
+
+/*
+ * The main TCP accept loop. Note that, for the non-debug case, returns
+ * from this function are in a forked subprocess.
+ */
+static void
+server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
+{
+       fd_set *fdset;
+       int i, j, ret, maxfd;
+       int key_used = 0, startups = 0;
+       int startup_p[2] = { -1 , -1 };
+       struct sockaddr_storage from;
+       socklen_t fromlen;
+       pid_t pid;
+
+       /* setup fd set for accept */
+       fdset = NULL;
+       maxfd = 0;
+       for (i = 0; i < num_listen_socks; i++)
+               if (listen_socks[i] > maxfd)
+                       maxfd = listen_socks[i];
+       /* pipes connected to unauthenticated childs */
+       startup_pipes = xcalloc(options.max_startups, sizeof(int));
+       for (i = 0; i < options.max_startups; i++)
+               startup_pipes[i] = -1;
+
+       /*
+        * Stay listening for connections until the system crashes or
+        * the daemon is killed with a signal.
+        */
+       for (;;) {
+               if (received_sighup)
+                       sighup_restart();
+               if (fdset != NULL)
+                       xfree(fdset);
+               fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),
+                   sizeof(fd_mask));
+
+               for (i = 0; i < num_listen_socks; i++)
+                       FD_SET(listen_socks[i], fdset);
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               FD_SET(startup_pipes[i], fdset);
+
+               /* Wait in select until there is a connection. */
+               ret = select(maxfd+1, fdset, NULL, NULL, NULL);
+               if (ret < 0 && errno != EINTR)
+                       error("select: %.100s", strerror(errno));
+               if (received_sigterm) {
+                       logit("Received signal %d; terminating.",
+                           (int) received_sigterm);
+                       close_listen_socks();
+                       unlink(options.pid_file);
+                       exit(received_sigterm == SIGTERM ? 0 : 255);
+               }
+               if (key_used && key_do_regen) {
+                       generate_ephemeral_server_key();
+                       key_used = 0;
+                       key_do_regen = 0;
+               }
+               if (ret < 0)
+                       continue;
+
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1 &&
+                           FD_ISSET(startup_pipes[i], fdset)) {
+                               /*
+                                * the read end of the pipe is ready
+                                * if the child has closed the pipe
+                                * after successful authentication
+                                * or if the child has died
+                                */
+                               close(startup_pipes[i]);
+                               startup_pipes[i] = -1;
+                               startups--;
+                       }
+               for (i = 0; i < num_listen_socks; i++) {
+                       if (!FD_ISSET(listen_socks[i], fdset))
+                               continue;
+                       fromlen = sizeof(from);
+                       *newsock = accept(listen_socks[i],
+                           (struct sockaddr *)&from, &fromlen);
+                       if (*newsock < 0) {
+                               if (errno != EINTR && errno != EAGAIN &&
+                                   errno != EWOULDBLOCK)
+                                       error("accept: %.100s", strerror(errno));
+                               continue;
+                       }
+                       if (unset_nonblock(*newsock) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+                       if (drop_connection(startups) == 1) {
+                               debug("drop connection #%d", startups);
+                               close(*newsock);
+                               continue;
+                       }
+                       if (pipe(startup_p) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+
+                       if (rexec_flag && socketpair(AF_UNIX,
+                           SOCK_STREAM, 0, config_s) == -1) {
+                               error("reexec socketpair: %s",
+                                   strerror(errno));
+                               close(*newsock);
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               continue;
+                       }
+
+                       for (j = 0; j < options.max_startups; j++)
+                               if (startup_pipes[j] == -1) {
+                                       startup_pipes[j] = startup_p[0];
+                                       if (maxfd < startup_p[0])
+                                               maxfd = startup_p[0];
+                                       startups++;
+                                       break;
+                               }
+
+                       /*
+                        * Got connection.  Fork a child to handle it, unless
+                        * we are in debugging mode.
+                        */
+                       if (debug_flag) {
+                               /*
+                                * In debugging mode.  Close the listening
+                                * socket, and start processing the
+                                * connection without forking.
+                                */
+                               debug("Server will not fork when running in debugging mode.");
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               startup_pipe = -1;
+                               pid = getpid();
+                               if (rexec_flag) {
+                                       send_rexec_state(config_s[0],
+                                           &cfg);
+                                       close(config_s[0]);
+                               }
+                               break;
+                       }
+
+                       /*
+                        * Normal production daemon.  Fork, and have
+                        * the child process the connection. The
+                        * parent continues listening.
+                        */
+                       platform_pre_fork();
+                       if ((pid = fork()) == 0) {
+                               /*
+                                * Child.  Close the listening and
+                                * max_startup sockets.  Start using
+                                * the accepted socket. Reinitialize
+                                * logging (since our pid has changed).
+                                * We break out of the loop to handle
+                                * the connection.
+                                */
+                               platform_post_fork_child();
+                               startup_pipe = startup_p[1];
+                               close_startup_pipes();
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               log_init(__progname,
+                                   options.log_level,
+                                   options.log_facility,
+                                   log_stderr);
+                               if (rexec_flag)
+                                       close(config_s[0]);
+                               break;
+                       }
+
+                       /* Parent.  Stay in the loop. */
+                       platform_post_fork_parent(pid);
+                       if (pid < 0)
+                               error("fork: %.100s", strerror(errno));
+                       else
+                               debug("Forked child %ld.", (long)pid);
+
+                       close(startup_p[1]);
+
+                       if (rexec_flag) {
+                               send_rexec_state(config_s[0], &cfg);
+                               close(config_s[0]);
+                               close(config_s[1]);
+                       }
+
+                       /*
+                        * Mark that the key has been used (it
+                        * was "given" to the child).
+                        */
+                       if ((options.protocol & SSH_PROTO_1) &&
+                           key_used == 0) {
+                               /* Schedule server key regeneration alarm. */
+                               signal(SIGALRM, key_regeneration_alarm);
+                               alarm(options.key_regeneration_time);
+                               key_used = 1;
+                       }
+
+                       close(*newsock);
+
+                       /*
+                        * Ensure that our random state differs
+                        * from that of the child
+                        */
+                       arc4random_stir();
+               }
+
+               /* child process check (or debug mode) */
+               if (num_listen_socks < 0)
+                       break;
+       }
+}
+
+
+/*
+ * Main program for the daemon.
+ */
+int
+main(int ac, char **av)
+{
+       extern char *optarg;
+       extern int optind;
+       int opt, i, j, on = 1;
+       int sock_in = -1, sock_out = -1, newsock = -1;
+       const char *remote_ip;
+       char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
+       int remote_port;
+       char *line, *p, *cp;
+       int config_s[2] = { -1 , -1 };
+       u_int64_t ibytes, obytes;
+       mode_t new_umask;
+       Key *key;
+       Authctxt *authctxt;
+
+#ifdef HAVE_SECUREWARE
+       (void)set_auth_parameters(ac, av);
+#endif
+       __progname = ssh_get_progname(av[0]);
+
+       /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
+       saved_argc = ac;
+       rexec_argc = ac;
+       saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
+       for (i = 0; i < ac; i++)
+               saved_argv[i] = xstrdup(av[i]);
+       saved_argv[i] = NULL;
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       compat_init_setproctitle(ac, av);
+       av = saved_argv;
+#endif
+
+       if (geteuid() == 0 && setgroups(0, NULL) == -1)
+               debug("setgroups(): %.200s", strerror(errno));
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       /* Initialize configuration options to their default values. */
+       initialize_server_options(&options);
+
+       /* Parse command-line arguments. */
+       while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) {
+               switch (opt) {
+               case '4':
+                       options.address_family = AF_INET;
+                       break;
+               case '6':
+                       options.address_family = AF_INET6;
+                       break;
+               case 'f':
+                       config_file_name = optarg;
+                       break;
+               case 'c':
+                       if (options.num_host_cert_files >= MAX_HOSTCERTS) {
+                               fprintf(stderr, "too many host certificates.\n");
+                               exit(1);
+                       }
+                       options.host_cert_files[options.num_host_cert_files++] =
+                          derelativise_path(optarg);
+                       break;
+               case 'd':
+                       if (debug_flag == 0) {
+                               debug_flag = 1;
+                               options.log_level = SYSLOG_LEVEL_DEBUG1;
+                       } else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                               options.log_level++;
+                       break;
+               case 'D':
+                       no_daemon_flag = 1;
+                       break;
+               case 'e':
+                       log_stderr = 1;
+                       break;
+               case 'i':
+                       inetd_flag = 1;
+                       break;
+               case 'r':
+                       rexec_flag = 0;
+                       break;
+               case 'R':
+                       rexeced_flag = 1;
+                       inetd_flag = 1;
+                       break;
+               case 'Q':
+                       /* ignored */
+                       break;
+               case 'q':
+                       options.log_level = SYSLOG_LEVEL_QUIET;
+                       break;
+               case 'b':
+                       options.server_key_bits = (int)strtonum(optarg, 256,
+                           32768, NULL);
+                       break;
+               case 'p':
+                       options.ports_from_cmdline = 1;
+                       if (options.num_ports >= MAX_PORTS) {
+                               fprintf(stderr, "too many ports.\n");
+                               exit(1);
+                       }
+                       options.ports[options.num_ports++] = a2port(optarg);
+                       if (options.ports[options.num_ports-1] <= 0) {
+                               fprintf(stderr, "Bad port number.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'g':
+                       if ((options.login_grace_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid login grace time.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'k':
+                       if ((options.key_regeneration_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid key regeneration interval.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'h':
+                       if (options.num_host_key_files >= MAX_HOSTKEYS) {
+                               fprintf(stderr, "too many host keys.\n");
+                               exit(1);
+                       }
+                       options.host_key_files[options.num_host_key_files++] = 
+                          derelativise_path(optarg);
+                       break;
+               case 't':
+                       test_flag = 1;
+                       break;
+               case 'T':
+                       test_flag = 2;
+                       break;
+               case 'C':
+                       cp = optarg;
+                       while ((p = strsep(&cp, ",")) && *p != '\0') {
+                               if (strncmp(p, "addr=", 5) == 0)
+                                       test_addr = xstrdup(p + 5);
+                               else if (strncmp(p, "host=", 5) == 0)
+                                       test_host = xstrdup(p + 5);
+                               else if (strncmp(p, "user=", 5) == 0)
+                                       test_user = xstrdup(p + 5);
+                               else {
+                                       fprintf(stderr, "Invalid test "
+                                           "mode specification %s\n", p);
+                                       exit(1);
+                               }
+                       }
+                       break;
+               case 'u':
+                       utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
+                       if (utmp_len > MAXHOSTNAMELEN) {
+                               fprintf(stderr, "Invalid utmp length.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'o':
+                       line = xstrdup(optarg);
+                       if (process_server_config_line(&options, line,
+                           "command-line", 0, NULL, NULL, NULL, NULL) != 0)
+                               exit(1);
+                       xfree(line);
+                       break;
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+       }
+       if (rexeced_flag || inetd_flag)
+               rexec_flag = 0;
+       if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
+               fatal("sshd re-exec requires execution with an absolute path");
+       if (rexeced_flag)
+               closefrom(REEXEC_MIN_FREE_FD);
+       else
+               closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
+
+       OpenSSL_add_all_algorithms();
+
+       /*
+        * Force logging to stderr until we have loaded the private host
+        * key (unless started from inetd)
+        */
+       log_init(__progname,
+           options.log_level == SYSLOG_LEVEL_NOT_SET ?
+           SYSLOG_LEVEL_INFO : options.log_level,
+           options.log_facility == SYSLOG_FACILITY_NOT_SET ?
+           SYSLOG_FACILITY_AUTH : options.log_facility,
+           log_stderr || !inetd_flag);
+
+       /*
+        * Unset KRB5CCNAME, otherwise the user's session may inherit it from
+        * root's environment
+        */
+       if (getenv("KRB5CCNAME") != NULL)
+               unsetenv("KRB5CCNAME");
+
+#ifdef _UNICOS
+       /* Cray can define user privs drop all privs now!
+        * Not needed on PRIV_SU systems!
+        */
+       drop_cray_privs();
+#endif
+
+       sensitive_data.server_key = NULL;
+       sensitive_data.ssh1_host_key = NULL;
+       sensitive_data.have_ssh1_key = 0;
+       sensitive_data.have_ssh2_key = 0;
+
+       /*
+        * If we're doing an extended config test, make sure we have all of
+        * the parameters we need.  If we're not doing an extended test,
+        * do not silently ignore connection test params.
+        */
+       if (test_flag >= 2 &&
+          (test_user != NULL || test_host != NULL || test_addr != NULL)
+           && (test_user == NULL || test_host == NULL || test_addr == NULL))
+               fatal("user, host and addr are all required when testing "
+                  "Match configs");
+       if (test_flag < 2 && (test_user != NULL || test_host != NULL ||
+           test_addr != NULL))
+               fatal("Config test connection parameter (-C) provided without "
+                  "test mode (-T)");
+
+       /* Fetch our configuration */
+       buffer_init(&cfg);
+       if (rexeced_flag)
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
+       else
+               load_server_config(config_file_name, &cfg);
+
+       parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
+           &cfg, NULL, NULL, NULL);
+
+       seed_rng();
+
+       /* Fill in default values for those options not explicitly set. */
+       fill_default_server_options(&options);
+
+       /* challenge-response is implemented via keyboard interactive */
+       if (options.challenge_response_authentication)
+               options.kbd_interactive_authentication = 1;
+
+       /* set default channel AF */
+       channel_set_af(options.address_family);
+
+       /* Check that there are no remaining arguments. */
+       if (optind < ac) {
+               fprintf(stderr, "Extra argument %s.\n", av[optind]);
+               exit(1);
+       }
+
+       debug("sshd version %.100s", SSH_RELEASE);
+
+       /* Store privilege separation user for later use if required. */
+       if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
+               if (use_privsep || options.kerberos_authentication)
+                       fatal("Privilege separation user %s does not exist",
+                           SSH_PRIVSEP_USER);
+       } else {
+               memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd));
+               privsep_pw = pwcopy(privsep_pw);
+               xfree(privsep_pw->pw_passwd);
+               privsep_pw->pw_passwd = xstrdup("*");
+       }
+       endpwent();
+
+       /* load private host keys */
+       sensitive_data.host_keys = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_keys[i] = NULL;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = key_load_private(options.host_key_files[i], "", NULL);
+               sensitive_data.host_keys[i] = key;
+               if (key == NULL) {
+                       error("Could not load host key: %s",
+                           options.host_key_files[i]);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
+               if (auth_key_is_revoked(key, 1)) {
+                       key_free(key);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
+               switch (key->type) {
+               case KEY_RSA1:
+                       sensitive_data.ssh1_host_key = key;
+                       sensitive_data.have_ssh1_key = 1;
+                       break;
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       sensitive_data.have_ssh2_key = 1;
+                       break;
+               }
+               debug("private host key: #%d type %d %s", i, key->type,
+                   key_type(key));
+       }
+       if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
+               logit("Disabling protocol version 1. Could not load host key");
+               options.protocol &= ~SSH_PROTO_1;
+       }
+#ifndef GSSAPI
+       /* The GSSAPI key exchange can run without a host key */
+       if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
+               logit("Disabling protocol version 2. Could not load host key");
+               options.protocol &= ~SSH_PROTO_2;
+       }
+#endif
+       if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+               logit("sshd: no hostkeys available -- exiting.");
+               exit(1);
+       }
+
+       /*
+        * Load certificates. They are stored in an array at identical
+        * indices to the public keys that they relate to.
+        */
+       sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_certificates[i] = NULL;
+
+       for (i = 0; i < options.num_host_cert_files; i++) {
+               key = key_load_public(options.host_cert_files[i], NULL);
+               if (key == NULL) {
+                       error("Could not load host certificate: %s",
+                           options.host_cert_files[i]);
+                       continue;
+               }
+               if (!key_is_cert(key)) {
+                       error("Certificate file is not a certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               /* Find matching private key */
+               for (j = 0; j < options.num_host_key_files; j++) {
+                       if (key_equal_public(key,
+                           sensitive_data.host_keys[j])) {
+                               sensitive_data.host_certificates[j] = key;
+                               break;
+                       }
+               }
+               if (j >= options.num_host_key_files) {
+                       error("No matching private key for certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               sensitive_data.host_certificates[j] = key;
+               debug("host certificate: #%d type %d %s", j, key->type,
+                   key_type(key));
+       }
+       /* Check certain values for sanity. */
+       if (options.protocol & SSH_PROTO_1) {
+               if (options.server_key_bits < 512 ||
+                   options.server_key_bits > 32768) {
+                       fprintf(stderr, "Bad server key size.\n");
+                       exit(1);
+               }
+               /*
+                * Check that server and host key lengths differ sufficiently. This
+                * is necessary to make double encryption work with rsaref. Oh, I
+                * hate software patents. I dont know if this can go? Niels
+                */
+               if (options.server_key_bits >
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -
+                   SSH_KEY_BITS_RESERVED && options.server_key_bits <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       options.server_key_bits =
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                           SSH_KEY_BITS_RESERVED;
+                       debug("Forcing server key to %d bits to make it differ from host key.",
+                           options.server_key_bits);
+               }
+       }
+
+       if (use_privsep) {
+               struct stat st;
+
+               if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
+                   (S_ISDIR(st.st_mode) == 0))
+                       fatal("Missing privilege separation directory: %s",
+                           _PATH_PRIVSEP_CHROOT_DIR);
+
+#ifdef HAVE_CYGWIN
+               if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) &&
+                   (st.st_uid != getuid () ||
+                   (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
+#else
+               if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
+#endif
+                       fatal("%s must be owned by root and not group or "
+                           "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
+       }
+
+       if (test_flag > 1) {
+               if (test_user != NULL && test_addr != NULL && test_host != NULL)
+                       parse_server_match_config(&options, test_user,
+                           test_host, test_addr);
+               dump_config(&options);
+       }
+
+       /* Configuration looks good, so exit if in test mode. */
+       if (test_flag)
+               exit(0);
+
+       /*
+        * Clear out any supplemental groups we may have inherited.  This
+        * prevents inadvertent creation of files with bad modes (in the
+        * portable version at least, it's certainly possible for PAM
+        * to create a file, and we can't control the code in every
+        * module which might be used).
+        */
+       if (setgroups(0, NULL) < 0)
+               debug("setgroups() failed: %.200s", strerror(errno));
+
+       if (rexec_flag) {
+               rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *));
+               for (i = 0; i < rexec_argc; i++) {
+                       debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
+                       rexec_argv[i] = saved_argv[i];
+               }
+               rexec_argv[rexec_argc] = "-R";
+               rexec_argv[rexec_argc + 1] = NULL;
+       }
+
+       /* Ensure that umask disallows at least group and world write */
+       new_umask = umask(0077) | 0022;
+       (void) umask(new_umask);
+
+       /* Initialize the log (it is reinitialized below in case we forked). */
+       if (debug_flag && (!inetd_flag || rexeced_flag))
+               log_stderr = 1;
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /*
+        * If not in debugging mode, and not started from inetd, disconnect
+        * from the controlling terminal, and fork.  The original process
+        * exits.
+        */
+       if (!(debug_flag || inetd_flag || no_daemon_flag)) {
+#ifdef TIOCNOTTY
+               int fd;
+#endif /* TIOCNOTTY */
+               if (daemon(0, 0) < 0)
+                       fatal("daemon() failed: %.200s", strerror(errno));
+
+               /* Disconnect from the controlling tty. */
+#ifdef TIOCNOTTY
+               fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
+               if (fd >= 0) {
+                       (void) ioctl(fd, TIOCNOTTY, NULL);
+                       close(fd);
+               }
+#endif /* TIOCNOTTY */
+       }
+       /* Reinitialize the log (because of the fork above). */
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /* Initialize the random number generator. */
+       arc4random_stir();
+
+       /* Chdir to the root directory so that the current disk can be
+          unmounted if desired. */
+       chdir("/");
+
+       /* ignore SIGPIPE */
+       signal(SIGPIPE, SIG_IGN);
+
+       /* Get a connection, either from inetd or a listening TCP socket */
+       if (inetd_flag) {
+               server_accept_inetd(&sock_in, &sock_out);
+       } else {
+               platform_pre_listen();
+               server_listen();
+
+               if (options.protocol & SSH_PROTO_1)
+                       generate_ephemeral_server_key();
+
+               signal(SIGHUP, sighup_handler);
+               signal(SIGCHLD, main_sigchld_handler);
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+
+               /*
+                * Write out the pid file after the sigterm handler
+                * is setup and the listen sockets are bound
+                */
+               if (!debug_flag) {
+                       FILE *f = fopen(options.pid_file, "w");
+
+                       if (f == NULL) {
+                               error("Couldn't create pid file \"%s\": %s",
+                                   options.pid_file, strerror(errno));
+                       } else {
+                               fprintf(f, "%ld\n", (long) getpid());
+                               fclose(f);
+                       }
+               }
+
+               /* Accept a connection and return in a forked child */
+               server_accept_loop(&sock_in, &sock_out,
+                   &newsock, config_s);
+       }
+
+       /* This is the child processing a new connection. */
+       setproctitle("%s", "[accepted]");
+
+       /*
+        * Create a new session and process group since the 4.4BSD
+        * setlogin() affects the entire process group.  We don't
+        * want the child to be able to affect the parent.
+        */
+#if !defined(SSHD_ACQUIRES_CTTY)
+       /*
+        * If setsid is called, on some platforms sshd will later acquire a
+        * controlling terminal which will result in "could not set
+        * controlling tty" errors.
+        */
+       if (!debug_flag && !inetd_flag && setsid() < 0)
+               error("setsid: %.100s", strerror(errno));
+#endif
+
+       if (rexec_flag) {
+               int fd;
+
+               debug("rexec start in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+               dup2(newsock, STDIN_FILENO);
+               dup2(STDIN_FILENO, STDOUT_FILENO);
+               if (startup_pipe == -1)
+                       close(REEXEC_STARTUP_PIPE_FD);
+               else
+                       dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
+
+               dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
+               close(config_s[1]);
+               if (startup_pipe != -1)
+                       close(startup_pipe);
+
+               execv(rexec_argv[0], rexec_argv);
+
+               /* Reexec has failed, fall back and continue */
+               error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
+
+               /* Clean up fds */
+               startup_pipe = REEXEC_STARTUP_PIPE_FD;
+               close(config_s[1]);
+               close(REEXEC_CONFIG_PASS_FD);
+               newsock = sock_out = sock_in = dup(STDIN_FILENO);
+               if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       if (fd > STDERR_FILENO)
+                               close(fd);
+               }
+               debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+       }
+
+       /* Executed child processes don't need these. */
+       fcntl(sock_out, F_SETFD, FD_CLOEXEC);
+       fcntl(sock_in, F_SETFD, FD_CLOEXEC);
+
+       /*
+        * Disable the key regeneration alarm.  We will not regenerate the
+        * key since we are no longer in a position to give it to anyone. We
+        * will not restart on SIGHUP since it no longer makes sense.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGQUIT, SIG_DFL);
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGINT, SIG_DFL);
+
+       /*
+        * Register our connection.  This turns encryption off because we do
+        * not have a key.
+        */
+       packet_set_connection(sock_in, sock_out);
+       packet_set_server();
+
+       /* Set SO_KEEPALIVE if requested. */
+       if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
+           setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
+       if ((remote_port = get_remote_port()) < 0) {
+               debug("get_remote_port failed");
+               cleanup_exit(255);
+       }
+
+       /*
+        * We use get_canonical_hostname with usedns = 0 instead of
+        * get_remote_ipaddr here so IP options will be checked.
+        */
+       (void) get_canonical_hostname(0);
+       /*
+        * The rest of the code depends on the fact that
+        * get_remote_ipaddr() caches the remote ip, even if
+        * the socket goes away.
+        */
+       remote_ip = get_remote_ipaddr();
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_connection_from(remote_ip, remote_port);
+#endif
+#ifdef LIBWRAP
+       allow_severity = options.log_facility|LOG_INFO;
+       deny_severity = options.log_facility|LOG_WARNING;
+       /* Check whether logins are denied from this host. */
+       if (packet_connection_is_on_socket()) {
+               struct request_info req;
+
+               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
+               fromhost(&req);
+
+               if (!hosts_access(&req)) {
+                       debug("Connection refused by tcp wrapper");
+                       refuse(&req);
+                       /* NOTREACHED */
+                       fatal("libwrap refuse returns");
+               }
+       }
+#endif /* LIBWRAP */
+
+       /* Log the connection. */
+       verbose("Connection from %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_SECURITY_SESSION_API
+       /*
+        * Create a new security session for use by the new user login if
+        * the current session is the root session or we are not launched
+        * by inetd (eg: debugging mode or server mode).  We do not
+        * necessarily need to create a session if we are launched from
+        * inetd because Panther xinetd will create a session for us.
+        *
+        * The only case where this logic will fail is if there is an
+        * inetd running in a non-root session which is not creating
+        * new sessions for us.  Then all the users will end up in the
+        * same session (bad).
+        *
+        * When the client exits, the session will be destroyed for us
+        * automatically.
+        *
+        * We must create the session before any credentials are stored
+        * (including AFS pags, which happens a few lines below).
+        */
+       {
+               OSStatus err = 0;
+               SecuritySessionId sid = 0;
+               SessionAttributeBits sattrs = 0;
+
+               err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+               if (err)
+                       error("SessionGetInfo() failed with error %.8X",
+                           (unsigned) err);
+               else
+                       debug("Current Session ID is %.8X / Session Attributes are %.8X",
+                           (unsigned) sid, (unsigned) sattrs);
+
+               if (inetd_flag && !(sattrs & sessionIsRoot))
+                       debug("Running in inetd mode in a non-root session... "
+                           "assuming inetd created the session for us.");
+               else {
+                       debug("Creating new security session...");
+                       err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+                       if (err)
+                               error("SessionCreate() failed with error %.8X",
+                                   (unsigned) err);
+
+                       err = SessionGetInfo(callerSecuritySession, &sid, 
+                           &sattrs);
+                       if (err)
+                               error("SessionGetInfo() failed with error %.8X",
+                                   (unsigned) err);
+                       else
+                               debug("New Session ID is %.8X / Session Attributes are %.8X",
+                                   (unsigned) sid, (unsigned) sattrs);
+               }
+       }
+#endif
+
+       /*
+        * We don't want to listen forever unless the other side
+        * successfully authenticates itself.  So we set up an alarm which is
+        * cleared after successful authentication.  A limit of zero
+        * indicates no limit. Note that we don't set the alarm in debugging
+        * mode; it is just annoying to have the server exit just when you
+        * are about to discover the bug.
+        */
+       signal(SIGALRM, grace_alarm_handler);
+       if (!debug_flag)
+               alarm(options.login_grace_time);
+
+       sshd_exchange_identification(sock_in, sock_out);
+
+       /* In inetd mode, generate ephemeral key only for proto 1 connections */
+       if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
+               generate_ephemeral_server_key();
+
+       packet_set_nonblocking();
+
+       /* allocate authentication context */
+       authctxt = xcalloc(1, sizeof(*authctxt));
+
+       authctxt->loginmsg = &loginmsg;
+
+       /* XXX global for cleanup, access from other modules */
+       the_authctxt = authctxt;
+
+       /* prepare buffer to collect messages to display to user after login */
+       buffer_init(&loginmsg);
+       auth_debug_reset();
+
+       if (use_privsep)
+               if (privsep_preauth(authctxt) == 1)
+                       goto authenticated;
+
+       /* perform the key exchange */
+       /* authenticate user and start session */
+       if (compat20) {
+               do_ssh2_kex();
+               do_authentication2(authctxt);
+       } else {
+               do_ssh1_kex();
+               do_authentication(authctxt);
+       }
+       /*
+        * If we use privilege separation, the unprivileged child transfers
+        * the current keystate and exits
+        */
+       if (use_privsep) {
+               mm_send_keystate(pmonitor);
+               exit(0);
+       }
+
+ authenticated:
+       /*
+        * Cancel the alarm we set to limit the time taken for
+        * authentication.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       authctxt->authenticated = 1;
+       if (startup_pipe != -1) {
+               close(startup_pipe);
+               startup_pipe = -1;
+       }
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_event(SSH_AUTH_SUCCESS);
+#endif
+
+#ifdef GSSAPI
+       if (options.gss_authentication) {
+               temporarily_use_uid(authctxt->pw);
+               ssh_gssapi_storecreds();
+               restore_uid();
+       }
+#endif
+#ifdef USE_PAM
+       if (options.use_pam) {
+               do_pam_setcred(1);
+               do_pam_session();
+       }
+#endif
+
+       /*
+        * In privilege separation, we fork another child and prepare
+        * file descriptor passing.
+        */
+       if (use_privsep) {
+               privsep_postauth(authctxt);
+               /* the monitor process [priv] will not return */
+               if (!compat20)
+                       destroy_sensitive_data();
+       }
+
+       packet_set_timeout(options.client_alive_interval,
+           options.client_alive_count_max);
+
+       /* Start session. */
+       do_authenticated(authctxt);
+
+       /* The connection has been terminated. */
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes",
+           (unsigned long long)obytes, (unsigned long long)ibytes);
+
+       verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               finish_pam();
+#endif /* USE_PAM */
+
+#ifdef SSH_AUDIT_EVENTS
+       PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));
+#endif
+
+       packet_close();
+
+       if (use_privsep)
+               mm_terminate();
+
+       exit(0);
+}
+
+/*
+ * Decrypt session_key_int using our private server key and private host key
+ * (key with larger modulus first).
+ */
+int
+ssh1_session_key(BIGNUM *session_key_int)
+{
+       int rsafail = 0;
+
+       if (BN_cmp(sensitive_data.server_key->rsa->n,
+           sensitive_data.ssh1_host_key->rsa->n) > 0) {
+               /* Server key has bigger modulus. */
+               if (BN_num_bits(sensitive_data.server_key->rsa->n) <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) <= 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) <= 0)
+                       rsafail++;
+       } else {
+               /* Host key has bigger modulus (or they are equal). */
+               if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
+                   BN_num_bits(sensitive_data.server_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) < 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) < 0)
+                       rsafail++;
+       }
+       return (rsafail);
+}
+/*
+ * SSH1 key exchange
+ */
+static void
+do_ssh1_kex(void)
+{
+       int i, len;
+       int rsafail = 0;
+       BIGNUM *session_key_int;
+       u_char session_key[SSH_SESSION_KEY_LENGTH];
+       u_char cookie[8];
+       u_int cipher_type, auth_mask, protocol_flags;
+
+       /*
+        * Generate check bytes that the client must send back in the user
+        * packet in order for it to be accepted; this is used to defy ip
+        * spoofing attacks.  Note that this only works against somebody
+        * doing IP spoofing from a remote machine; any machine on the local
+        * network can still see outgoing packets and catch the random
+        * cookie.  This only affects rhosts authentication, and this is one
+        * of the reasons why it is inherently insecure.
+        */
+       arc4random_buf(cookie, sizeof(cookie));
+
+       /*
+        * Send our public key.  We include in the packet 64 bits of random
+        * data that must be matched in the reply in order to prevent IP
+        * spoofing.
+        */
+       packet_start(SSH_SMSG_PUBLIC_KEY);
+       for (i = 0; i < 8; i++)
+               packet_put_char(cookie[i]);
+
+       /* Store our public server RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
+       packet_put_bignum(sensitive_data.server_key->rsa->e);
+       packet_put_bignum(sensitive_data.server_key->rsa->n);
+
+       /* Store our public host RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
+
+       /* Put protocol flags. */
+       packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
+
+       /* Declare which ciphers we support. */
+       packet_put_int(cipher_mask_ssh1(0));
+
+       /* Declare supported authentication types. */
+       auth_mask = 0;
+       if (options.rhosts_rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
+       if (options.rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RSA;
+       if (options.challenge_response_authentication == 1)
+               auth_mask |= 1 << SSH_AUTH_TIS;
+       if (options.password_authentication)
+               auth_mask |= 1 << SSH_AUTH_PASSWORD;
+       packet_put_int(auth_mask);
+
+       /* Send the packet and wait for it to be sent. */
+       packet_send();
+       packet_write_wait();
+
+       debug("Sent %d bit server key and %d bit host key.",
+           BN_num_bits(sensitive_data.server_key->rsa->n),
+           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+
+       /* Read clients reply (cipher type and session key). */
+       packet_read_expect(SSH_CMSG_SESSION_KEY);
+
+       /* Get cipher type and check whether we accept this. */
+       cipher_type = packet_get_char();
+
+       if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
+               packet_disconnect("Warning: client selects unsupported cipher.");
+
+       /* Get check bytes from the packet.  These must match those we
+          sent earlier with the public key packet. */
+       for (i = 0; i < 8; i++)
+               if (cookie[i] != packet_get_char())
+                       packet_disconnect("IP Spoofing check bytes do not match.");
+
+       debug("Encryption type: %.200s", cipher_name(cipher_type));
+
+       /* Get the encrypted integer. */
+       if ((session_key_int = BN_new()) == NULL)
+               fatal("do_ssh1_kex: BN_new failed");
+       packet_get_bignum(session_key_int);
+
+       protocol_flags = packet_get_int();
+       packet_set_protocol_flags(protocol_flags);
+       packet_check_eom();
+
+       /* Decrypt session_key_int using host/server keys */
+       rsafail = PRIVSEP(ssh1_session_key(session_key_int));
+
+       /*
+        * Extract session key from the decrypted integer.  The key is in the
+        * least significant 256 bits of the integer; the first byte of the
+        * key is in the highest bits.
+        */
+       if (!rsafail) {
+               (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
+               len = BN_num_bytes(session_key_int);
+               if (len < 0 || (u_int)len > sizeof(session_key)) {
+                       error("do_ssh1_kex: bad session key len from %s: "
+                           "session_key_int %d > sizeof(session_key) %lu",
+                           get_remote_ipaddr(), len, (u_long)sizeof(session_key));
+                       rsafail++;
+               } else {
+                       memset(session_key, 0, sizeof(session_key));
+                       BN_bn2bin(session_key_int,
+                           session_key + sizeof(session_key) - len);
+
+                       derive_ssh1_session_id(
+                           sensitive_data.ssh1_host_key->rsa->n,
+                           sensitive_data.server_key->rsa->n,
+                           cookie, session_id);
+                       /*
+                        * Xor the first 16 bytes of the session key with the
+                        * session id.
+                        */
+                       for (i = 0; i < 16; i++)
+                               session_key[i] ^= session_id[i];
+               }
+       }
+       if (rsafail) {
+               int bytes = BN_num_bytes(session_key_int);
+               u_char *buf = xmalloc(bytes);
+               MD5_CTX md;
+
+               logit("do_connection: generating a fake encryption key");
+               BN_bn2bin(session_key_int, buf);
+               MD5_Init(&md);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key, &md);
+               MD5_Init(&md);
+               MD5_Update(&md, session_key, 16);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key + 16, &md);
+               memset(buf, 0, bytes);
+               xfree(buf);
+               for (i = 0; i < 16; i++)
+                       session_id[i] = session_key[i] ^ session_key[i + 16];
+       }
+       /* Destroy the private and public keys. No longer. */
+       destroy_sensitive_data();
+
+       if (use_privsep)
+               mm_ssh1_session_id(session_id);
+
+       /* Destroy the decrypted integer.  It is no longer needed. */
+       BN_clear_free(session_key_int);
+
+       /* Set the session key.  From this on all communications will be encrypted. */
+       packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);
+
+       /* Destroy our copy of the session key.  It is no longer needed. */
+       memset(session_key, 0, sizeof(session_key));
+
+       debug("Received session key; encryption turned on.");
+
+       /* Send an acknowledgment packet.  Note that this packet is sent encrypted. */
+       packet_start(SSH_SMSG_SUCCESS);
+       packet_send();
+       packet_write_wait();
+}
+
+/*
+ * SSH2 key exchange: diffie-hellman-group1-sha1
+ */
+static void
+do_ssh2_kex(void)
+{
+       Kex *kex;
+
+       if (options.ciphers != NULL) {
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       myproposal[PROPOSAL_ENC_ALGS_STOC] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
+
+       if (options.macs != NULL) {
+               myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+               myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+       }
+       if (options.compression == COMP_NONE) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
+       } else if (options.compression == COMP_DELAYED) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";
+       }
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+
+       myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
+
+#ifdef GSSAPI
+       {
+       char *orig;
+       char *gss = NULL;
+       char *newstr = NULL;
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+
+       /* 
+        * If we don't have a host key, then there's no point advertising
+        * the other key exchange algorithms
+        */
+
+       if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+               orig = NULL;
+
+       if (options.gss_keyex)
+               gss = ssh_gssapi_server_mechanisms();
+       else
+               gss = NULL;
+
+       if (gss && orig)
+               xasprintf(&newstr, "%s,%s", gss, orig);
+       else if (gss)
+               newstr = gss;
+       else if (orig)
+               newstr = orig;
+
+       /* 
+        * If we've got GSSAPI mechanisms, then we've got the 'null' host
+        * key alg, but we can't tell people about it unless its the only
+        * host key algorithm we support
+        */
+       if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+       if (newstr)
+               myproposal[PROPOSAL_KEX_ALGS] = newstr;
+       else
+               fatal("No supported key exchange algorithms");
+       }
+#endif
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
+#endif
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->load_host_public_key=&get_hostkey_public_by_type;
+       kex->load_host_private_key=&get_hostkey_private_by_type;
+       kex->host_key_index=&get_hostkey_index;
+
+       xxx_kex = kex;
+
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
+
+#ifdef DEBUG_KEXDH
+       /* send 1st encrypted/maced/compressed message */
+       packet_start(SSH2_MSG_IGNORE);
+       packet_put_cstring("markus");
+       packet_send();
+       packet_write_wait();
+#endif
+       debug("KEX done");
+}
+
+/* server specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       if (the_authctxt)
+               do_cleanup(the_authctxt);
+#ifdef SSH_AUDIT_EVENTS
+       /* done after do_cleanup so it can cancel the PAM auth 'thread' */
+       if (!use_privsep || mm_is_monitor())
+               audit_event(SSH_CONNECTION_ABANDON);
+#endif
+       _exit(i);
+}
diff --git a/.pc/package-versioning.patch/version.h b/.pc/package-versioning.patch/version.h
new file mode 100644 (file)
index 0000000..6a1acb3
--- /dev/null
@@ -0,0 +1,6 @@
+/* $OpenBSD: version.h,v 1.62 2011/08/02 23:13:01 djm Exp $ */
+
+#define SSH_VERSION    "OpenSSH_5.9"
+
+#define SSH_PORTABLE   "p1"
+#define SSH_RELEASE    SSH_VERSION SSH_PORTABLE
diff --git a/.pc/quieter-signals.patch/clientloop.c b/.pc/quieter-signals.patch/clientloop.c
new file mode 100644 (file)
index 0000000..22ece1e
--- /dev/null
@@ -0,0 +1,2193 @@
+/* $OpenBSD: clientloop.c,v 1.236 2011/06/22 22:08:42 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * The main loop for the interactive session (client side).
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ *
+ * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * SSH2 support added by Markus Friedl.
+ * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <errno.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "buffer.h"
+#include "compat.h"
+#include "channels.h"
+#include "dispatch.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "readconf.h"
+#include "clientloop.h"
+#include "sshconnect.h"
+#include "authfd.h"
+#include "atomicio.h"
+#include "sshpty.h"
+#include "misc.h"
+#include "match.h"
+#include "msg.h"
+#include "roaming.h"
+
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
+/* import options */
+extern Options options;
+
+/* Flag indicating that stdin should be redirected from /dev/null. */
+extern int stdin_null_flag;
+
+/* Flag indicating that no shell has been requested */
+extern int no_shell_flag;
+
+/* Control socket */
+extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
+
+/*
+ * Name of the host we are connecting to.  This is the name given on the
+ * command line, or the HostName specified for the user-supplied name in a
+ * configuration file.
+ */
+extern char *host;
+
+/*
+ * Flag to indicate that we have received a window change signal which has
+ * not yet been processed.  This will cause a message indicating the new
+ * window size to be sent to the server a little later.  This is volatile
+ * because this is updated in a signal handler.
+ */
+static volatile sig_atomic_t received_window_change_signal = 0;
+static volatile sig_atomic_t received_signal = 0;
+
+/* Flag indicating whether the user's terminal is in non-blocking mode. */
+static int in_non_blocking_mode = 0;
+
+/* Time when backgrounded control master using ControlPersist should exit */
+static time_t control_persist_exit_time = 0;
+
+/* Common data for the client loop code. */
+volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
+static int escape_char1;       /* Escape character. (proto1 only) */
+static int escape_pending1;    /* Last character was an escape (proto1 only) */
+static int last_was_cr;                /* Last character was a newline. */
+static int exit_status;                /* Used to store the command exit status. */
+static int stdin_eof;          /* EOF has been encountered on stderr. */
+static Buffer stdin_buffer;    /* Buffer for stdin data. */
+static Buffer stdout_buffer;   /* Buffer for stdout data. */
+static Buffer stderr_buffer;   /* Buffer for stderr data. */
+static u_int buffer_high;      /* Soft max buffer size. */
+static int connection_in;      /* Connection to server (input). */
+static int connection_out;     /* Connection to server (output). */
+static int need_rekeying;      /* Set to non-zero if rekeying is requested. */
+static int session_closed;     /* In SSH2: login session closed. */
+static int x11_refuse_time;    /* If >0, refuse x11 opens after this time. */
+
+static void client_init_dispatch(void);
+int    session_ident = -1;
+
+int    session_resumed = 0;
+
+/* Track escape per proto2 channel */
+struct escape_filter_ctx {
+       int escape_pending;
+       int escape_char;
+};
+
+/* Context for channel confirmation replies */
+struct channel_reply_ctx {
+       const char *request_type;
+       int id;
+       enum confirm_action action;
+};
+
+/* Global request success/failure callbacks */
+struct global_confirm {
+       TAILQ_ENTRY(global_confirm) entry;
+       global_confirm_cb *cb;
+       void *ctx;
+       int ref_count;
+};
+TAILQ_HEAD(global_confirms, global_confirm);
+static struct global_confirms global_confirms =
+    TAILQ_HEAD_INITIALIZER(global_confirms);
+
+/*XXX*/
+extern Kex *xxx_kex;
+
+void ssh_process_session2_setup(int, int, int, Buffer *);
+
+/* Restores stdin to blocking mode. */
+
+static void
+leave_non_blocking(void)
+{
+       if (in_non_blocking_mode) {
+               unset_nonblock(fileno(stdin));
+               in_non_blocking_mode = 0;
+       }
+}
+
+/* Puts stdin terminal in non-blocking mode. */
+
+static void
+enter_non_blocking(void)
+{
+       in_non_blocking_mode = 1;
+       set_nonblock(fileno(stdin));
+}
+
+/*
+ * Signal handler for the window change signal (SIGWINCH).  This just sets a
+ * flag indicating that the window has changed.
+ */
+/*ARGSUSED */
+static void
+window_change_handler(int sig)
+{
+       received_window_change_signal = 1;
+       signal(SIGWINCH, window_change_handler);
+}
+
+/*
+ * Signal handler for signals that cause the program to terminate.  These
+ * signals must be trapped to restore terminal modes.
+ */
+/*ARGSUSED */
+static void
+signal_handler(int sig)
+{
+       received_signal = sig;
+       quit_pending = 1;
+}
+
+/*
+ * Returns current time in seconds from Jan 1, 1970 with the maximum
+ * available resolution.
+ */
+
+static double
+get_current_time(void)
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+}
+
+/*
+ * Sets control_persist_exit_time to the absolute time when the
+ * backgrounded control master should exit due to expiry of the
+ * ControlPersist timeout.  Sets it to 0 if we are not a backgrounded
+ * control master process, or if there is no ControlPersist timeout.
+ */
+static void
+set_control_persist_exit_time(void)
+{
+       if (muxserver_sock == -1 || !options.control_persist
+           || options.control_persist_timeout == 0) {
+               /* not using a ControlPersist timeout */
+               control_persist_exit_time = 0;
+       } else if (channel_still_open()) {
+               /* some client connections are still open */
+               if (control_persist_exit_time > 0)
+                       debug2("%s: cancel scheduled exit", __func__);
+               control_persist_exit_time = 0;
+       } else if (control_persist_exit_time <= 0) {
+               /* a client connection has recently closed */
+               control_persist_exit_time = time(NULL) +
+                       (time_t)options.control_persist_timeout;
+               debug2("%s: schedule exit in %d seconds", __func__,
+                   options.control_persist_timeout);
+       }
+       /* else we are already counting down to the timeout */
+}
+
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+void
+client_x11_get_proto(const char *display, const char *xauth_path,
+    u_int trusted, u_int timeout, char **_proto, char **_data)
+{
+       char cmd[1024];
+       char line[512];
+       char xdisplay[512];
+       static char proto[512], data[512];
+       FILE *f;
+       int got_data = 0, generated = 0, do_unlink = 0, i;
+       char *xauthdir, *xauthfile;
+       struct stat st;
+       u_int now;
+
+       xauthdir = xauthfile = NULL;
+       *_proto = proto;
+       *_data = data;
+       proto[0] = data[0] = '\0';
+
+       if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
+               debug("No xauth program.");
+       } else {
+               if (display == NULL) {
+                       debug("x11_get_proto: DISPLAY not set");
+                       return;
+               }
+               /*
+                * Handle FamilyLocal case where $DISPLAY does
+                * not match an authorization entry.  For this we
+                * just try "xauth list unix:displaynum.screennum".
+                * XXX: "localhost" match to determine FamilyLocal
+                *      is not perfect.
+                */
+               if (strncmp(display, "localhost:", 10) == 0) {
+                       snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
+                           display + 10);
+                       display = xdisplay;
+               }
+               if (trusted == 0) {
+                       xauthdir = xmalloc(MAXPATHLEN);
+                       xauthfile = xmalloc(MAXPATHLEN);
+                       mktemp_proto(xauthdir, MAXPATHLEN);
+                       if (mkdtemp(xauthdir) != NULL) {
+                               do_unlink = 1;
+                               snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
+                                   xauthdir);
+                               snprintf(cmd, sizeof(cmd),
+                                   "%s -f %s generate %s " SSH_X11_PROTO
+                                   " untrusted timeout %u 2>" _PATH_DEVNULL,
+                                   xauth_path, xauthfile, display, timeout);
+                               debug2("x11_get_proto: %s", cmd);
+                               if (system(cmd) == 0)
+                                       generated = 1;
+                               if (x11_refuse_time == 0) {
+                                       now = time(NULL) + 1;
+                                       if (UINT_MAX - timeout < now)
+                                               x11_refuse_time = UINT_MAX;
+                                       else
+                                               x11_refuse_time = now + timeout;
+                               }
+                       }
+               }
+
+               /*
+                * When in untrusted mode, we read the cookie only if it was
+                * successfully generated as an untrusted one in the step
+                * above.
+                */
+               if (trusted || generated) {
+                       snprintf(cmd, sizeof(cmd),
+                           "%s %s%s list %s 2>" _PATH_DEVNULL,
+                           xauth_path,
+                           generated ? "-f " : "" ,
+                           generated ? xauthfile : "",
+                           display);
+                       debug2("x11_get_proto: %s", cmd);
+                       f = popen(cmd, "r");
+                       if (f && fgets(line, sizeof(line), f) &&
+                           sscanf(line, "%*s %511s %511s", proto, data) == 2)
+                               got_data = 1;
+                       if (f)
+                               pclose(f);
+               } else
+                       error("Warning: untrusted X11 forwarding setup failed: "
+                           "xauth key data not generated");
+       }
+
+       if (do_unlink) {
+               unlink(xauthfile);
+               rmdir(xauthdir);
+       }
+       if (xauthdir)
+               xfree(xauthdir);
+       if (xauthfile)
+               xfree(xauthfile);
+
+       /*
+        * If we didn't get authentication data, just make up some
+        * data.  The forwarding code will check the validity of the
+        * response anyway, and substitute this data.  The X11
+        * server, however, will ignore this fake data and use
+        * whatever authentication mechanisms it was using otherwise
+        * for the local connection.
+        */
+       if (!got_data) {
+               u_int32_t rnd = 0;
+
+               logit("Warning: No xauth data; "
+                   "using fake authentication data for X11 forwarding.");
+               strlcpy(proto, SSH_X11_PROTO, sizeof proto);
+               for (i = 0; i < 16; i++) {
+                       if (i % 4 == 0)
+                               rnd = arc4random();
+                       snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
+                           rnd & 0xff);
+                       rnd >>= 8;
+               }
+       }
+}
+
+/*
+ * This is called when the interactive is entered.  This checks if there is
+ * an EOF coming on stdin.  We must check this explicitly, as select() does
+ * not appear to wake up when redirecting from /dev/null.
+ */
+
+static void
+client_check_initial_eof_on_stdin(void)
+{
+       int len;
+       char buf[1];
+
+       /*
+        * If standard input is to be "redirected from /dev/null", we simply
+        * mark that we have seen an EOF and send an EOF message to the
+        * server. Otherwise, we try to read a single character; it appears
+        * that for some files, such /dev/null, select() never wakes up for
+        * read for this descriptor, which means that we never get EOF.  This
+        * way we will get the EOF if stdin comes from /dev/null or similar.
+        */
+       if (stdin_null_flag) {
+               /* Fake EOF on stdin. */
+               debug("Sending eof.");
+               stdin_eof = 1;
+               packet_start(SSH_CMSG_EOF);
+               packet_send();
+       } else {
+               enter_non_blocking();
+
+               /* Check for immediate EOF on stdin. */
+               len = read(fileno(stdin), buf, 1);
+               if (len == 0) {
+                       /*
+                        * EOF.  Record that we have seen it and send
+                        * EOF to server.
+                        */
+                       debug("Sending eof.");
+                       stdin_eof = 1;
+                       packet_start(SSH_CMSG_EOF);
+                       packet_send();
+               } else if (len > 0) {
+                       /*
+                        * Got data.  We must store the data in the buffer,
+                        * and also process it as an escape character if
+                        * appropriate.
+                        */
+                       if ((u_char) buf[0] == escape_char1)
+                               escape_pending1 = 1;
+                       else
+                               buffer_append(&stdin_buffer, buf, 1);
+               }
+               leave_non_blocking();
+       }
+}
+
+
+/*
+ * Make packets from buffered stdin data, and buffer them for sending to the
+ * connection.
+ */
+
+static void
+client_make_packets_from_stdin_data(void)
+{
+       u_int len;
+
+       /* Send buffered stdin data to the server. */
+       while (buffer_len(&stdin_buffer) > 0 &&
+           packet_not_very_much_data_to_write()) {
+               len = buffer_len(&stdin_buffer);
+               /* Keep the packets at reasonable size. */
+               if (len > packet_get_maxsize())
+                       len = packet_get_maxsize();
+               packet_start(SSH_CMSG_STDIN_DATA);
+               packet_put_string(buffer_ptr(&stdin_buffer), len);
+               packet_send();
+               buffer_consume(&stdin_buffer, len);
+               /* If we have a pending EOF, send it now. */
+               if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
+                       packet_start(SSH_CMSG_EOF);
+                       packet_send();
+               }
+       }
+}
+
+/*
+ * Checks if the client window has changed, and sends a packet about it to
+ * the server if so.  The actual change is detected elsewhere (by a software
+ * interrupt on Unix); this just checks the flag and sends a message if
+ * appropriate.
+ */
+
+static void
+client_check_window_change(void)
+{
+       struct winsize ws;
+
+       if (! received_window_change_signal)
+               return;
+       /** XXX race */
+       received_window_change_signal = 0;
+
+       debug2("client_check_window_change: changed");
+
+       if (compat20) {
+               channel_send_window_changes();
+       } else {
+               if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
+                       return;
+               packet_start(SSH_CMSG_WINDOW_SIZE);
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+               packet_send();
+       }
+}
+
+static void
+client_global_request_reply(int type, u_int32_t seq, void *ctxt)
+{
+       struct global_confirm *gc;
+
+       if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
+               return;
+       if (gc->cb != NULL)
+               gc->cb(type, seq, gc->ctx);
+       if (--gc->ref_count <= 0) {
+               TAILQ_REMOVE(&global_confirms, gc, entry);
+               bzero(gc, sizeof(*gc));
+               xfree(gc);
+       }
+
+       packet_set_alive_timeouts(0);
+}
+
+static void
+server_alive_check(void)
+{
+       if (compat20) {
+               if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
+                       logit("Timeout, server %s not responding.", host);
+                       cleanup_exit(255);
+               }
+               packet_start(SSH2_MSG_GLOBAL_REQUEST);
+               packet_put_cstring("keepalive@openssh.com");
+               packet_put_char(1);     /* boolean: want reply */
+               packet_send();
+               /* Insert an empty placeholder to maintain ordering */
+               client_register_global_confirm(NULL, NULL);
+       } else {
+               packet_send_ignore(0);
+               packet_send();
+       }
+}
+
+/*
+ * Waits until the client can do something (some data becomes available on
+ * one of the file descriptors).
+ */
+static void
+client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
+    int *maxfdp, u_int *nallocp, int rekeying)
+{
+       struct timeval tv, *tvp;
+       int timeout_secs;
+       int ret;
+
+       /* Add any selections by the channel mechanism. */
+       channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
+
+       if (!compat20) {
+               /* Read from the connection, unless our buffers are full. */
+               if (buffer_len(&stdout_buffer) < buffer_high &&
+                   buffer_len(&stderr_buffer) < buffer_high &&
+                   channel_not_very_much_buffered_data())
+                       FD_SET(connection_in, *readsetp);
+               /*
+                * Read from stdin, unless we have seen EOF or have very much
+                * buffered data to send to the server.
+                */
+               if (!stdin_eof && packet_not_very_much_data_to_write())
+                       FD_SET(fileno(stdin), *readsetp);
+
+               /* Select stdout/stderr if have data in buffer. */
+               if (buffer_len(&stdout_buffer) > 0)
+                       FD_SET(fileno(stdout), *writesetp);
+               if (buffer_len(&stderr_buffer) > 0)
+                       FD_SET(fileno(stderr), *writesetp);
+       } else {
+               /* channel_prepare_select could have closed the last channel */
+               if (session_closed && !channel_still_open() &&
+                   !packet_have_data_to_write()) {
+                       /* clear mask since we did not call select() */
+                       memset(*readsetp, 0, *nallocp);
+                       memset(*writesetp, 0, *nallocp);
+                       return;
+               } else {
+                       FD_SET(connection_in, *readsetp);
+               }
+       }
+
+       /* Select server connection if have data to write to the server. */
+       if (packet_have_data_to_write())
+               FD_SET(connection_out, *writesetp);
+
+       /*
+        * Wait for something to happen.  This will suspend the process until
+        * some selected descriptor can be read, written, or has some other
+        * event pending, or a timeout expires.
+        */
+
+       timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
+       if (options.server_alive_interval > 0)
+               timeout_secs = options.server_alive_interval;
+       set_control_persist_exit_time();
+       if (control_persist_exit_time > 0) {
+               timeout_secs = MIN(timeout_secs,
+                       control_persist_exit_time - time(NULL));
+               if (timeout_secs < 0)
+                       timeout_secs = 0;
+       }
+       if (timeout_secs == INT_MAX)
+               tvp = NULL;
+       else {
+               tv.tv_sec = timeout_secs;
+               tv.tv_usec = 0;
+               tvp = &tv;
+       }
+
+       ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+       if (ret < 0) {
+               char buf[100];
+
+               /*
+                * We have to clear the select masks, because we return.
+                * We have to return, because the mainloop checks for the flags
+                * set by the signal handlers.
+                */
+               memset(*readsetp, 0, *nallocp);
+               memset(*writesetp, 0, *nallocp);
+
+               if (errno == EINTR)
+                       return;
+               /* Note: we might still have data in the buffers. */
+               snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
+               buffer_append(&stderr_buffer, buf, strlen(buf));
+               quit_pending = 1;
+       } else if (ret == 0)
+               server_alive_check();
+}
+
+static void
+client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
+{
+       /* Flush stdout and stderr buffers. */
+       if (buffer_len(bout) > 0)
+               atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
+                   buffer_len(bout));
+       if (buffer_len(berr) > 0)
+               atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
+                   buffer_len(berr));
+
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       /*
+        * Free (and clear) the buffer to reduce the amount of data that gets
+        * written to swap.
+        */
+       buffer_free(bin);
+       buffer_free(bout);
+       buffer_free(berr);
+
+       /* Send the suspend signal to the program itself. */
+       kill(getpid(), SIGTSTP);
+
+       /* Reset window sizes in case they have changed */
+       received_window_change_signal = 1;
+
+       /* OK, we have been continued by the user. Reinitialize buffers. */
+       buffer_init(bin);
+       buffer_init(bout);
+       buffer_init(berr);
+
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+}
+
+static void
+client_process_net_input(fd_set *readset)
+{
+       int len, cont = 0;
+       char buf[SSH_IOBUFSZ];
+
+       /*
+        * Read input from the server, and add any such data to the buffer of
+        * the packet subsystem.
+        */
+       if (FD_ISSET(connection_in, readset)) {
+               /* Read as much as possible. */
+               len = roaming_read(connection_in, buf, sizeof(buf), &cont);
+               if (len == 0 && cont == 0) {
+                       /*
+                        * Received EOF.  The remote host has closed the
+                        * connection.
+                        */
+                       snprintf(buf, sizeof buf,
+                           "Connection to %.300s closed by remote host.\r\n",
+                           host);
+                       buffer_append(&stderr_buffer, buf, strlen(buf));
+                       quit_pending = 1;
+                       return;
+               }
+               /*
+                * There is a kernel bug on Solaris that causes select to
+                * sometimes wake up even though there is no data available.
+                */
+               if (len < 0 &&
+                   (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
+                       len = 0;
+
+               if (len < 0) {
+                       /*
+                        * An error has encountered.  Perhaps there is a
+                        * network problem.
+                        */
+                       snprintf(buf, sizeof buf,
+                           "Read from remote host %.300s: %.100s\r\n",
+                           host, strerror(errno));
+                       buffer_append(&stderr_buffer, buf, strlen(buf));
+                       quit_pending = 1;
+                       return;
+               }
+               packet_process_incoming(buf, len);
+       }
+}
+
+static void
+client_status_confirm(int type, Channel *c, void *ctx)
+{
+       struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
+       char errmsg[256];
+       int tochan;
+
+       /*
+        * If a TTY was explicitly requested, then a failure to allocate
+        * one is fatal.
+        */
+       if (cr->action == CONFIRM_TTY &&
+           (options.request_tty == REQUEST_TTY_FORCE ||
+           options.request_tty == REQUEST_TTY_YES))
+               cr->action = CONFIRM_CLOSE;
+
+       /* XXX supress on mux _client_ quietmode */
+       tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
+           c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
+
+       if (type == SSH2_MSG_CHANNEL_SUCCESS) {
+               debug2("%s request accepted on channel %d",
+                   cr->request_type, c->self);
+       } else if (type == SSH2_MSG_CHANNEL_FAILURE) {
+               if (tochan) {
+                       snprintf(errmsg, sizeof(errmsg),
+                           "%s request failed\r\n", cr->request_type);
+               } else {
+                       snprintf(errmsg, sizeof(errmsg),
+                           "%s request failed on channel %d",
+                           cr->request_type, c->self);
+               }
+               /* If error occurred on primary session channel, then exit */
+               if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
+                       fatal("%s", errmsg);
+               /*
+                * If error occurred on mux client, append to
+                * their stderr.
+                */
+               if (tochan) {
+                       buffer_append(&c->extended, errmsg,
+                           strlen(errmsg));
+               } else
+                       error("%s", errmsg);
+               if (cr->action == CONFIRM_TTY) {
+                       /*
+                        * If a TTY allocation error occurred, then arrange
+                        * for the correct TTY to leave raw mode.
+                        */
+                       if (c->self == session_ident)
+                               leave_raw_mode(0);
+                       else
+                               mux_tty_alloc_failed(c);
+               } else if (cr->action == CONFIRM_CLOSE) {
+                       chan_read_failed(c);
+                       chan_write_failed(c);
+               }
+       }
+       xfree(cr);
+}
+
+static void
+client_abandon_status_confirm(Channel *c, void *ctx)
+{
+       xfree(ctx);
+}
+
+void
+client_expect_confirm(int id, const char *request,
+    enum confirm_action action)
+{
+       struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
+
+       cr->request_type = request;
+       cr->action = action;
+
+       channel_register_status_confirm(id, client_status_confirm,
+           client_abandon_status_confirm, cr);
+}
+
+void
+client_register_global_confirm(global_confirm_cb *cb, void *ctx)
+{
+       struct global_confirm *gc, *last_gc;
+
+       /* Coalesce identical callbacks */
+       last_gc = TAILQ_LAST(&global_confirms, global_confirms);
+       if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
+               if (++last_gc->ref_count >= INT_MAX)
+                       fatal("%s: last_gc->ref_count = %d",
+                           __func__, last_gc->ref_count);
+               return;
+       }
+
+       gc = xmalloc(sizeof(*gc));
+       gc->cb = cb;
+       gc->ctx = ctx;
+       gc->ref_count = 1;
+       TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
+}
+
+static void
+process_cmdline(void)
+{
+       void (*handler)(int);
+       char *s, *cmd, *cancel_host;
+       int delete = 0;
+       int local = 0, remote = 0, dynamic = 0;
+       int cancel_port;
+       Forward fwd;
+
+       bzero(&fwd, sizeof(fwd));
+       fwd.listen_host = fwd.connect_host = NULL;
+
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       handler = signal(SIGINT, SIG_IGN);
+       cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
+       if (s == NULL)
+               goto out;
+       while (isspace(*s))
+               s++;
+       if (*s == '-')
+               s++;    /* Skip cmdline '-', if any */
+       if (*s == '\0')
+               goto out;
+
+       if (*s == 'h' || *s == 'H' || *s == '?') {
+               logit("Commands:");
+               logit("      -L[bind_address:]port:host:hostport    "
+                   "Request local forward");
+               logit("      -R[bind_address:]port:host:hostport    "
+                   "Request remote forward");
+               logit("      -D[bind_address:]port                  "
+                   "Request dynamic forward");
+               logit("      -KR[bind_address:]port                 "
+                   "Cancel remote forward");
+               if (!options.permit_local_command)
+                       goto out;
+               logit("      !args                                  "
+                   "Execute local command");
+               goto out;
+       }
+
+       if (*s == '!' && options.permit_local_command) {
+               s++;
+               ssh_local_cmd(s);
+               goto out;
+       }
+
+       if (*s == 'K') {
+               delete = 1;
+               s++;
+       }
+       if (*s == 'L')
+               local = 1;
+       else if (*s == 'R')
+               remote = 1;
+       else if (*s == 'D')
+               dynamic = 1;
+       else {
+               logit("Invalid command.");
+               goto out;
+       }
+
+       if ((local || dynamic) && delete) {
+               logit("Not supported.");
+               goto out;
+       }
+       if (remote && delete && !compat20) {
+               logit("Not supported for SSH protocol version 1.");
+               goto out;
+       }
+
+       while (isspace(*++s))
+               ;
+
+       /* XXX update list of forwards in options */
+       if (delete) {
+               cancel_port = 0;
+               cancel_host = hpdelim(&s);      /* may be NULL */
+               if (s != NULL) {
+                       cancel_port = a2port(s);
+                       cancel_host = cleanhostname(cancel_host);
+               } else {
+                       cancel_port = a2port(cancel_host);
+                       cancel_host = NULL;
+               }
+               if (cancel_port <= 0) {
+                       logit("Bad forwarding close port");
+                       goto out;
+               }
+               channel_request_rforward_cancel(cancel_host, cancel_port);
+       } else {
+               if (!parse_forward(&fwd, s, dynamic, remote)) {
+                       logit("Bad forwarding specification.");
+                       goto out;
+               }
+               if (local || dynamic) {
+                       if (channel_setup_local_fwd_listener(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port, options.gateway_ports) < 0) {
+                               logit("Port forwarding failed.");
+                               goto out;
+                       }
+               } else {
+                       if (channel_request_remote_forwarding(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port) < 0) {
+                               logit("Port forwarding failed.");
+                               goto out;
+                       }
+               }
+
+               logit("Forwarding port.");
+       }
+
+out:
+       signal(SIGINT, handler);
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       if (cmd)
+               xfree(cmd);
+       if (fwd.listen_host != NULL)
+               xfree(fwd.listen_host);
+       if (fwd.connect_host != NULL)
+               xfree(fwd.connect_host);
+}
+
+/* 
+ * Process the characters one by one, call with c==NULL for proto1 case.
+ */
+static int
+process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
+    char *buf, int len)
+{
+       char string[1024];
+       pid_t pid;
+       int bytes = 0;
+       u_int i;
+       u_char ch;
+       char *s;
+       int *escape_pendingp, escape_char;
+       struct escape_filter_ctx *efc;
+
+       if (c == NULL) {
+               escape_pendingp = &escape_pending1;
+               escape_char = escape_char1;
+       } else {
+               if (c->filter_ctx == NULL)
+                       return 0;
+               efc = (struct escape_filter_ctx *)c->filter_ctx;
+               escape_pendingp = &efc->escape_pending;
+               escape_char = efc->escape_char;
+       }
+       
+       if (len <= 0)
+               return (0);
+
+       for (i = 0; i < (u_int)len; i++) {
+               /* Get one character at a time. */
+               ch = buf[i];
+
+               if (*escape_pendingp) {
+                       /* We have previously seen an escape character. */
+                       /* Clear the flag now. */
+                       *escape_pendingp = 0;
+
+                       /* Process the escaped character. */
+                       switch (ch) {
+                       case '.':
+                               /* Terminate the connection. */
+                               snprintf(string, sizeof string, "%c.\r\n",
+                                   escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               if (c && c->ctl_chan != -1) {
+                                       chan_read_failed(c);
+                                       chan_write_failed(c);
+                                       return 0;
+                               } else
+                                       quit_pending = 1;
+                               return -1;
+
+                       case 'Z' - 64:
+                               /* XXX support this for mux clients */
+                               if (c && c->ctl_chan != -1) {
+ noescape:
+                                       snprintf(string, sizeof string,
+                                           "%c%c escape not available to "
+                                           "multiplexed sessions\r\n",
+                                           escape_char, ch);
+                                       buffer_append(berr, string,
+                                           strlen(string));
+                                       continue;
+                               }
+                               /* Suspend the program. Inform the user */
+                               snprintf(string, sizeof string,
+                                   "%c^Z [suspend ssh]\r\n", escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               /* Restore terminal modes and suspend. */
+                               client_suspend_self(bin, bout, berr);
+
+                               /* We have been continued. */
+                               continue;
+
+                       case 'B':
+                               if (compat20) {
+                                       snprintf(string, sizeof string,
+                                           "%cB\r\n", escape_char);
+                                       buffer_append(berr, string,
+                                           strlen(string));
+                                       channel_request_start(session_ident,
+                                           "break", 0);
+                                       packet_put_int(1000);
+                                       packet_send();
+                               }
+                               continue;
+
+                       case 'R':
+                               if (compat20) {
+                                       if (datafellows & SSH_BUG_NOREKEY)
+                                               logit("Server does not "
+                                                   "support re-keying");
+                                       else
+                                               need_rekeying = 1;
+                               }
+                               continue;
+
+                       case '&':
+                               if (c && c->ctl_chan != -1)
+                                       goto noescape;
+                               /*
+                                * Detach the program (continue to serve
+                                * connections, but put in background and no
+                                * more new connections).
+                                */
+                               /* Restore tty modes. */
+                               leave_raw_mode(
+                                   options.request_tty == REQUEST_TTY_FORCE);
+
+                               /* Stop listening for new connections. */
+                               channel_stop_listening();
+
+                               snprintf(string, sizeof string,
+                                   "%c& [backgrounded]\n", escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               /* Fork into background. */
+                               pid = fork();
+                               if (pid < 0) {
+                                       error("fork: %.100s", strerror(errno));
+                                       continue;
+                               }
+                               if (pid != 0) { /* This is the parent. */
+                                       /* The parent just exits. */
+                                       exit(0);
+                               }
+                               /* The child continues serving connections. */
+                               if (compat20) {
+                                       buffer_append(bin, "\004", 1);
+                                       /* fake EOF on stdin */
+                                       return -1;
+                               } else if (!stdin_eof) {
+                                       /*
+                                        * Sending SSH_CMSG_EOF alone does not
+                                        * always appear to be enough.  So we
+                                        * try to send an EOF character first.
+                                        */
+                                       packet_start(SSH_CMSG_STDIN_DATA);
+                                       packet_put_string("\004", 1);
+                                       packet_send();
+                                       /* Close stdin. */
+                                       stdin_eof = 1;
+                                       if (buffer_len(bin) == 0) {
+                                               packet_start(SSH_CMSG_EOF);
+                                               packet_send();
+                                       }
+                               }
+                               continue;
+
+                       case '?':
+                               if (c && c->ctl_chan != -1) {
+                                       snprintf(string, sizeof string,
+"%c?\r\n\
+Supported escape sequences:\r\n\
+  %c.  - terminate session\r\n\
+  %cB  - send a BREAK to the remote system\r\n\
+  %cR  - Request rekey (SSH protocol 2 only)\r\n\
+  %c#  - list forwarded connections\r\n\
+  %c?  - this message\r\n\
+  %c%c  - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char);
+                               } else {
+                                       snprintf(string, sizeof string,
+"%c?\r\n\
+Supported escape sequences:\r\n\
+  %c.  - terminate connection (and any multiplexed sessions)\r\n\
+  %cB  - send a BREAK to the remote system\r\n\
+  %cC  - open a command line\r\n\
+  %cR  - Request rekey (SSH protocol 2 only)\r\n\
+  %c^Z - suspend ssh\r\n\
+  %c#  - list forwarded connections\r\n\
+  %c&  - background ssh (when waiting for connections to terminate)\r\n\
+  %c?  - this message\r\n\
+  %c%c  - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char);
+                               }
+                               buffer_append(berr, string, strlen(string));
+                               continue;
+
+                       case '#':
+                               snprintf(string, sizeof string, "%c#\r\n",
+                                   escape_char);
+                               buffer_append(berr, string, strlen(string));
+                               s = channel_open_message();
+                               buffer_append(berr, s, strlen(s));
+                               xfree(s);
+                               continue;
+
+                       case 'C':
+                               if (c && c->ctl_chan != -1)
+                                       goto noescape;
+                               process_cmdline();
+                               continue;
+
+                       default:
+                               if (ch != escape_char) {
+                                       buffer_put_char(bin, escape_char);
+                                       bytes++;
+                               }
+                               /* Escaped characters fall through here */
+                               break;
+                       }
+               } else {
+                       /*
+                        * The previous character was not an escape char.
+                        * Check if this is an escape.
+                        */
+                       if (last_was_cr && ch == escape_char) {
+                               /*
+                                * It is. Set the flag and continue to
+                                * next character.
+                                */
+                               *escape_pendingp = 1;
+                               continue;
+                       }
+               }
+
+               /*
+                * Normal character.  Record whether it was a newline,
+                * and append it to the buffer.
+                */
+               last_was_cr = (ch == '\r' || ch == '\n');
+               buffer_put_char(bin, ch);
+               bytes++;
+       }
+       return bytes;
+}
+
+static void
+client_process_input(fd_set *readset)
+{
+       int len;
+       char buf[SSH_IOBUFSZ];
+
+       /* Read input from stdin. */
+       if (FD_ISSET(fileno(stdin), readset)) {
+               /* Read as much as possible. */
+               len = read(fileno(stdin), buf, sizeof(buf));
+               if (len < 0 &&
+                   (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
+                       return;         /* we'll try again later */
+               if (len <= 0) {
+                       /*
+                        * Received EOF or error.  They are treated
+                        * similarly, except that an error message is printed
+                        * if it was an error condition.
+                        */
+                       if (len < 0) {
+                               snprintf(buf, sizeof buf, "read: %.100s\r\n",
+                                   strerror(errno));
+                               buffer_append(&stderr_buffer, buf, strlen(buf));
+                       }
+                       /* Mark that we have seen EOF. */
+                       stdin_eof = 1;
+                       /*
+                        * Send an EOF message to the server unless there is
+                        * data in the buffer.  If there is data in the
+                        * buffer, no message will be sent now.  Code
+                        * elsewhere will send the EOF when the buffer
+                        * becomes empty if stdin_eof is set.
+                        */
+                       if (buffer_len(&stdin_buffer) == 0) {
+                               packet_start(SSH_CMSG_EOF);
+                               packet_send();
+                       }
+               } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
+                       /*
+                        * Normal successful read, and no escape character.
+                        * Just append the data to buffer.
+                        */
+                       buffer_append(&stdin_buffer, buf, len);
+               } else {
+                       /*
+                        * Normal, successful read.  But we have an escape
+                        * character and have to process the characters one
+                        * by one.
+                        */
+                       if (process_escapes(NULL, &stdin_buffer,
+                           &stdout_buffer, &stderr_buffer, buf, len) == -1)
+                               return;
+               }
+       }
+}
+
+static void
+client_process_output(fd_set *writeset)
+{
+       int len;
+       char buf[100];
+
+       /* Write buffered output to stdout. */
+       if (FD_ISSET(fileno(stdout), writeset)) {
+               /* Write as much data as possible. */
+               len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
+                   buffer_len(&stdout_buffer));
+               if (len <= 0) {
+                       if (errno == EINTR || errno == EAGAIN ||
+                           errno == EWOULDBLOCK)
+                               len = 0;
+                       else {
+                               /*
+                                * An error or EOF was encountered.  Put an
+                                * error message to stderr buffer.
+                                */
+                               snprintf(buf, sizeof buf,
+                                   "write stdout: %.50s\r\n", strerror(errno));
+                               buffer_append(&stderr_buffer, buf, strlen(buf));
+                               quit_pending = 1;
+                               return;
+                       }
+               }
+               /* Consume printed data from the buffer. */
+               buffer_consume(&stdout_buffer, len);
+       }
+       /* Write buffered output to stderr. */
+       if (FD_ISSET(fileno(stderr), writeset)) {
+               /* Write as much data as possible. */
+               len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
+                   buffer_len(&stderr_buffer));
+               if (len <= 0) {
+                       if (errno == EINTR || errno == EAGAIN ||
+                           errno == EWOULDBLOCK)
+                               len = 0;
+                       else {
+                               /*
+                                * EOF or error, but can't even print
+                                * error message.
+                                */
+                               quit_pending = 1;
+                               return;
+                       }
+               }
+               /* Consume printed characters from the buffer. */
+               buffer_consume(&stderr_buffer, len);
+       }
+}
+
+/*
+ * Get packets from the connection input buffer, and process them as long as
+ * there are packets available.
+ *
+ * Any unknown packets received during the actual
+ * session cause the session to terminate.  This is
+ * intended to make debugging easier since no
+ * confirmations are sent.  Any compatible protocol
+ * extensions must be negotiated during the
+ * preparatory phase.
+ */
+
+static void
+client_process_buffered_input_packets(void)
+{
+       dispatch_run(DISPATCH_NONBLOCK, &quit_pending,
+           compat20 ? xxx_kex : NULL);
+}
+
+/* scan buf[] for '~' before sending data to the peer */
+
+/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
+void *
+client_new_escape_filter_ctx(int escape_char)
+{
+       struct escape_filter_ctx *ret;
+
+       ret = xmalloc(sizeof(*ret));
+       ret->escape_pending = 0;
+       ret->escape_char = escape_char;
+       return (void *)ret;
+}
+
+/* Free the escape filter context on channel free */
+void
+client_filter_cleanup(int cid, void *ctx)
+{
+       xfree(ctx);
+}
+
+int
+client_simple_escape_filter(Channel *c, char *buf, int len)
+{
+       if (c->extended_usage != CHAN_EXTENDED_WRITE)
+               return 0;
+
+       return process_escapes(c, &c->input, &c->output, &c->extended,
+           buf, len);
+}
+
+static void
+client_channel_closed(int id, void *arg)
+{
+       channel_cancel_cleanup(id);
+       session_closed = 1;
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+}
+
+/*
+ * Implements the interactive session with the server.  This is called after
+ * the user has been authenticated, and a command has been started on the
+ * remote host.  If escape_char != SSH_ESCAPECHAR_NONE, it is the character
+ * used as an escape character for terminating or suspending the session.
+ */
+
+int
+client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
+{
+       fd_set *readset = NULL, *writeset = NULL;
+       double start_time, total_time;
+       int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
+       u_int64_t ibytes, obytes;
+       u_int nalloc = 0;
+       char buf[100];
+
+       debug("Entering interactive session.");
+
+       start_time = get_current_time();
+
+       /* Initialize variables. */
+       escape_pending1 = 0;
+       last_was_cr = 1;
+       exit_status = -1;
+       stdin_eof = 0;
+       buffer_high = 64 * 1024;
+       connection_in = packet_get_connection_in();
+       connection_out = packet_get_connection_out();
+       max_fd = MAX(connection_in, connection_out);
+
+       if (!compat20) {
+               /* enable nonblocking unless tty */
+               if (!isatty(fileno(stdin)))
+                       set_nonblock(fileno(stdin));
+               if (!isatty(fileno(stdout)))
+                       set_nonblock(fileno(stdout));
+               if (!isatty(fileno(stderr)))
+                       set_nonblock(fileno(stderr));
+               max_fd = MAX(max_fd, fileno(stdin));
+               max_fd = MAX(max_fd, fileno(stdout));
+               max_fd = MAX(max_fd, fileno(stderr));
+       }
+       quit_pending = 0;
+       escape_char1 = escape_char_arg;
+
+       /* Initialize buffers. */
+       buffer_init(&stdin_buffer);
+       buffer_init(&stdout_buffer);
+       buffer_init(&stderr_buffer);
+
+       client_init_dispatch();
+
+       /*
+        * Set signal handlers, (e.g. to restore non-blocking mode)
+        * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
+        */
+       if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+               signal(SIGHUP, signal_handler);
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, signal_handler);
+       if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+               signal(SIGQUIT, signal_handler);
+       if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+               signal(SIGTERM, signal_handler);
+       signal(SIGWINCH, window_change_handler);
+
+       if (have_pty)
+               enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       if (compat20) {
+               session_ident = ssh2_chan_id;
+               if (session_ident != -1) {
+                       if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
+                               channel_register_filter(session_ident,
+                                   client_simple_escape_filter, NULL,
+                                   client_filter_cleanup,
+                                   client_new_escape_filter_ctx(
+                                   escape_char_arg));
+                       }
+                       channel_register_cleanup(session_ident,
+                           client_channel_closed, 0);
+               }
+       } else {
+               /* Check if we should immediately send eof on stdin. */
+               client_check_initial_eof_on_stdin();
+       }
+
+       /* Main loop of the client for the interactive session mode. */
+       while (!quit_pending) {
+
+               /* Process buffered packets sent by the server. */
+               client_process_buffered_input_packets();
+
+               if (compat20 && session_closed && !channel_still_open())
+                       break;
+
+               rekeying = (xxx_kex != NULL && !xxx_kex->done);
+
+               if (rekeying) {
+                       debug("rekeying in progress");
+               } else {
+                       /*
+                        * Make packets of buffered stdin data, and buffer
+                        * them for sending to the server.
+                        */
+                       if (!compat20)
+                               client_make_packets_from_stdin_data();
+
+                       /*
+                        * Make packets from buffered channel data, and
+                        * enqueue them for sending to the server.
+                        */
+                       if (packet_not_very_much_data_to_write())
+                               channel_output_poll();
+
+                       /*
+                        * Check if the window size has changed, and buffer a
+                        * message about it to the server if so.
+                        */
+                       client_check_window_change();
+
+                       if (quit_pending)
+                               break;
+               }
+               /*
+                * Wait until we have something to do (something becomes
+                * available on one of the descriptors).
+                */
+               max_fd2 = max_fd;
+               client_wait_until_can_do_something(&readset, &writeset,
+                   &max_fd2, &nalloc, rekeying);
+
+               if (quit_pending)
+                       break;
+
+               /* Do channel operations unless rekeying in progress. */
+               if (!rekeying) {
+                       channel_after_select(readset, writeset);
+
+#ifdef GSSAPI
+                       if (options.gss_renewal_rekey &&
+                           ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) {
+                               debug("credentials updated - forcing rekey");
+                               need_rekeying = 1;
+                       }
+#endif
+
+                       if (need_rekeying || packet_need_rekeying()) {
+                               debug("need rekeying");
+                               xxx_kex->done = 0;
+                               kex_send_kexinit(xxx_kex);
+                               need_rekeying = 0;
+                       }
+               }
+
+               /* Buffer input from the connection.  */
+               client_process_net_input(readset);
+
+               if (quit_pending)
+                       break;
+
+               if (!compat20) {
+                       /* Buffer data from stdin */
+                       client_process_input(readset);
+                       /*
+                        * Process output to stdout and stderr.  Output to
+                        * the connection is processed elsewhere (above).
+                        */
+                       client_process_output(writeset);
+               }
+
+               if (session_resumed) {
+                       connection_in = packet_get_connection_in();
+                       connection_out = packet_get_connection_out();
+                       max_fd = MAX(max_fd, connection_out);
+                       max_fd = MAX(max_fd, connection_in);
+                       session_resumed = 0;
+               }
+
+               /*
+                * Send as much buffered packet data as possible to the
+                * sender.
+                */
+               if (FD_ISSET(connection_out, writeset))
+                       packet_write_poll();
+
+               /*
+                * If we are a backgrounded control master, and the
+                * timeout has expired without any active client
+                * connections, then quit.
+                */
+               if (control_persist_exit_time > 0) {
+                       if (time(NULL) >= control_persist_exit_time) {
+                               debug("ControlPersist timeout expired");
+                               break;
+                       }
+               }
+       }
+       if (readset)
+               xfree(readset);
+       if (writeset)
+               xfree(writeset);
+
+       /* Terminate the session. */
+
+       /* Stop watching for window change. */
+       signal(SIGWINCH, SIG_DFL);
+
+       if (compat20) {
+               packet_start(SSH2_MSG_DISCONNECT);
+               packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
+               packet_put_cstring("disconnected by user");
+               packet_put_cstring(""); /* language tag */
+               packet_send();
+               packet_write_wait();
+       }
+
+       channel_free_all();
+
+       if (have_pty)
+               leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       /* restore blocking io */
+       if (!isatty(fileno(stdin)))
+               unset_nonblock(fileno(stdin));
+       if (!isatty(fileno(stdout)))
+               unset_nonblock(fileno(stdout));
+       if (!isatty(fileno(stderr)))
+               unset_nonblock(fileno(stderr));
+
+       /*
+        * If there was no shell or command requested, there will be no remote
+        * exit status to be returned.  In that case, clear error code if the
+        * connection was deliberately terminated at this end.
+        */
+       if (no_shell_flag && received_signal == SIGTERM) {
+               received_signal = 0;
+               exit_status = 0;
+       }
+
+       if (received_signal)
+               fatal("Killed by signal %d.", (int) received_signal);
+
+       /*
+        * In interactive mode (with pseudo tty) display a message indicating
+        * that the connection has been closed.
+        */
+       if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
+               snprintf(buf, sizeof buf,
+                   "Connection to %.64s closed.\r\n", host);
+               buffer_append(&stderr_buffer, buf, strlen(buf));
+       }
+
+       /* Output any buffered data for stdout. */
+       if (buffer_len(&stdout_buffer) > 0) {
+               len = atomicio(vwrite, fileno(stdout),
+                   buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer));
+               if (len < 0 || (u_int)len != buffer_len(&stdout_buffer))
+                       error("Write failed flushing stdout buffer.");
+               else
+                       buffer_consume(&stdout_buffer, len);
+       }
+
+       /* Output any buffered data for stderr. */
+       if (buffer_len(&stderr_buffer) > 0) {
+               len = atomicio(vwrite, fileno(stderr),
+                   buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer));
+               if (len < 0 || (u_int)len != buffer_len(&stderr_buffer))
+                       error("Write failed flushing stderr buffer.");
+               else
+                       buffer_consume(&stderr_buffer, len);
+       }
+
+       /* Clear and free any buffers. */
+       memset(buf, 0, sizeof(buf));
+       buffer_free(&stdin_buffer);
+       buffer_free(&stdout_buffer);
+       buffer_free(&stderr_buffer);
+
+       /* Report bytes transferred, and transfer rates. */
+       total_time = get_current_time() - start_time;
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
+           (unsigned long long)obytes, (unsigned long long)ibytes, total_time);
+       if (total_time > 0)
+               verbose("Bytes per second: sent %.1f, received %.1f",
+                   obytes / total_time, ibytes / total_time);
+       /* Return the exit status of the program. */
+       debug("Exit status %d", exit_status);
+       return exit_status;
+}
+
+/*********/
+
+static void
+client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
+{
+       u_int data_len;
+       char *data = packet_get_string(&data_len);
+       packet_check_eom();
+       buffer_append(&stdout_buffer, data, data_len);
+       memset(data, 0, data_len);
+       xfree(data);
+}
+static void
+client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
+{
+       u_int data_len;
+       char *data = packet_get_string(&data_len);
+       packet_check_eom();
+       buffer_append(&stderr_buffer, data, data_len);
+       memset(data, 0, data_len);
+       xfree(data);
+}
+static void
+client_input_exit_status(int type, u_int32_t seq, void *ctxt)
+{
+       exit_status = packet_get_int();
+       packet_check_eom();
+       /* Acknowledge the exit. */
+       packet_start(SSH_CMSG_EXIT_CONFIRMATION);
+       packet_send();
+       /*
+        * Must wait for packet to be sent since we are
+        * exiting the loop.
+        */
+       packet_write_wait();
+       /* Flag that we want to exit. */
+       quit_pending = 1;
+}
+static void
+client_input_agent_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       int remote_id, sock;
+
+       /* Read the remote channel number from the message. */
+       remote_id = packet_get_int();
+       packet_check_eom();
+
+       /*
+        * Get a connection to the local authentication agent (this may again
+        * get forwarded).
+        */
+       sock = ssh_get_authentication_socket();
+
+       /*
+        * If we could not connect the agent, send an error message back to
+        * the server. This should never happen unless the agent dies,
+        * because authentication forwarding is only enabled if we have an
+        * agent.
+        */
+       if (sock >= 0) {
+               c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
+                   -1, 0, 0, 0, "authentication agent connection", 1);
+               c->remote_id = remote_id;
+               c->force_drain = 1;
+       }
+       if (c == NULL) {
+               packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(remote_id);
+       } else {
+               /* Send a confirmation to the remote host. */
+               debug("Forwarding authentication connection.");
+               packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+               packet_put_int(remote_id);
+               packet_put_int(c->self);
+       }
+       packet_send();
+}
+
+static Channel *
+client_request_forwarded_tcpip(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       char *listen_address, *originator_address;
+       u_short listen_port, originator_port;
+
+       /* Get rest of the packet */
+       listen_address = packet_get_string(NULL);
+       listen_port = packet_get_int();
+       originator_address = packet_get_string(NULL);
+       originator_port = packet_get_int();
+       packet_check_eom();
+
+       debug("client_request_forwarded_tcpip: listen %s port %d, "
+           "originator %s port %d", listen_address, listen_port,
+           originator_address, originator_port);
+
+       c = channel_connect_by_listen_address(listen_port,
+           "forwarded-tcpip", originator_address);
+
+       xfree(originator_address);
+       xfree(listen_address);
+       return c;
+}
+
+static Channel *
+client_request_x11(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       char *originator;
+       u_short originator_port;
+       int sock;
+
+       if (!options.forward_x11) {
+               error("Warning: ssh server tried X11 forwarding.");
+               error("Warning: this is probably a break-in attempt by a "
+                   "malicious server.");
+               return NULL;
+       }
+       if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) {
+               verbose("Rejected X11 connection after ForwardX11Timeout "
+                   "expired");
+               return NULL;
+       }
+       originator = packet_get_string(NULL);
+       if (datafellows & SSH_BUG_X11FWD) {
+               debug2("buggy server: x11 request w/o originator_port");
+               originator_port = 0;
+       } else {
+               originator_port = packet_get_int();
+       }
+       packet_check_eom();
+       /* XXX check permission */
+       debug("client_request_x11: request from %s %d", originator,
+           originator_port);
+       xfree(originator);
+       sock = x11_connect_display();
+       if (sock < 0)
+               return NULL;
+       c = channel_new("x11",
+           SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+           CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
+       c->force_drain = 1;
+       return c;
+}
+
+static Channel *
+client_request_agent(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       int sock;
+
+       if (!options.forward_agent) {
+               error("Warning: ssh server tried agent forwarding.");
+               error("Warning: this is probably a break-in attempt by a "
+                   "malicious server.");
+               return NULL;
+       }
+       sock = ssh_get_authentication_socket();
+       if (sock < 0)
+               return NULL;
+       c = channel_new("authentication agent connection",
+           SSH_CHANNEL_OPEN, sock, sock, -1,
+           CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
+           "authentication agent connection", 1);
+       c->force_drain = 1;
+       return c;
+}
+
+int
+client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
+{
+       Channel *c;
+       int fd;
+
+       if (tun_mode == SSH_TUNMODE_NO)
+               return 0;
+
+       if (!compat20) {
+               error("Tunnel forwarding is not supported for protocol 1");
+               return -1;
+       }
+
+       debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
+
+       /* Open local tunnel device */
+       if ((fd = tun_open(local_tun, tun_mode)) == -1) {
+               error("Tunnel device open failed.");
+               return -1;
+       }
+
+       c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+           CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+       c->datagram = 1;
+
+#if defined(SSH_TUN_FILTER)
+       if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
+               channel_register_filter(c->self, sys_tun_infilter,
+                   sys_tun_outfilter, NULL, NULL);
+#endif
+
+       packet_start(SSH2_MSG_CHANNEL_OPEN);
+       packet_put_cstring("tun@openssh.com");
+       packet_put_int(c->self);
+       packet_put_int(c->local_window_max);
+       packet_put_int(c->local_maxpacket);
+       packet_put_int(tun_mode);
+       packet_put_int(remote_tun);
+       packet_send();
+
+       return 0;
+}
+
+/* XXXX move to generic input handler */
+static void
+client_input_channel_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       char *ctype;
+       int rchan;
+       u_int rmaxpack, rwindow, len;
+
+       ctype = packet_get_string(&len);
+       rchan = packet_get_int();
+       rwindow = packet_get_int();
+       rmaxpack = packet_get_int();
+
+       debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
+           ctype, rchan, rwindow, rmaxpack);
+
+       if (strcmp(ctype, "forwarded-tcpip") == 0) {
+               c = client_request_forwarded_tcpip(ctype, rchan);
+       } else if (strcmp(ctype, "x11") == 0) {
+               c = client_request_x11(ctype, rchan);
+       } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
+               c = client_request_agent(ctype, rchan);
+       }
+/* XXX duplicate : */
+       if (c != NULL) {
+               debug("confirm %s", ctype);
+               c->remote_id = rchan;
+               c->remote_window = rwindow;
+               c->remote_maxpacket = rmaxpack;
+               if (c->type != SSH_CHANNEL_CONNECTING) {
+                       packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
+                       packet_put_int(c->remote_id);
+                       packet_put_int(c->self);
+                       packet_put_int(c->local_window);
+                       packet_put_int(c->local_maxpacket);
+                       packet_send();
+               }
+       } else {
+               debug("failure %s", ctype);
+               packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(rchan);
+               packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
+               if (!(datafellows & SSH_BUG_OPENFAILURE)) {
+                       packet_put_cstring("open failed");
+                       packet_put_cstring("");
+               }
+               packet_send();
+       }
+       xfree(ctype);
+}
+static void
+client_input_channel_req(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       int exitval, id, reply, success = 0;
+       char *rtype;
+
+       id = packet_get_int();
+       rtype = packet_get_string(NULL);
+       reply = packet_get_char();
+
+       debug("client_input_channel_req: channel %d rtype %s reply %d",
+           id, rtype, reply);
+
+       if (id == -1) {
+               error("client_input_channel_req: request for channel -1");
+       } else if ((c = channel_lookup(id)) == NULL) {
+               error("client_input_channel_req: channel %d: "
+                   "unknown channel", id);
+       } else if (strcmp(rtype, "eow@openssh.com") == 0) {
+               packet_check_eom();
+               chan_rcvd_eow(c);
+       } else if (strcmp(rtype, "exit-status") == 0) {
+               exitval = packet_get_int();
+               if (c->ctl_chan != -1) {
+                       mux_exit_message(c, exitval);
+                       success = 1;
+               } else if (id == session_ident) {
+                       /* Record exit value of local session */
+                       success = 1;
+                       exit_status = exitval;
+               } else {
+                       /* Probably for a mux channel that has already closed */
+                       debug("%s: no sink for exit-status on channel %d",
+                           __func__, id);
+               }
+               packet_check_eom();
+       }
+       if (reply && c != NULL) {
+               packet_start(success ?
+                   SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
+               packet_put_int(c->remote_id);
+               packet_send();
+       }
+       xfree(rtype);
+}
+static void
+client_input_global_request(int type, u_int32_t seq, void *ctxt)
+{
+       char *rtype;
+       int want_reply;
+       int success = 0;
+
+       rtype = packet_get_string(NULL);
+       want_reply = packet_get_char();
+       debug("client_input_global_request: rtype %s want_reply %d",
+           rtype, want_reply);
+       if (want_reply) {
+               packet_start(success ?
+                   SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
+               packet_send();
+               packet_write_wait();
+       }
+       xfree(rtype);
+}
+
+void
+client_session2_setup(int id, int want_tty, int want_subsystem,
+    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
+{
+       int len;
+       Channel *c = NULL;
+
+       debug2("%s: id %d", __func__, id);
+
+       if ((c = channel_lookup(id)) == NULL)
+               fatal("client_session2_setup: channel %d: unknown channel", id);
+
+       packet_set_interactive(want_tty,
+           options.ip_qos_interactive, options.ip_qos_bulk);
+
+       if (want_tty) {
+               struct winsize ws;
+
+               /* Store window size in the packet. */
+               if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
+                       memset(&ws, 0, sizeof(ws));
+
+               channel_request_start(id, "pty-req", 1);
+               client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
+               packet_put_cstring(term != NULL ? term : "");
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+               if (tiop == NULL)
+                       tiop = get_saved_tio();
+               tty_make_modes(-1, tiop);
+               packet_send();
+               /* XXX wait for reply */
+               c->client_tty = 1;
+       }
+
+       /* Transfer any environment variables from client to server */
+       if (options.num_send_env != 0 && env != NULL) {
+               int i, j, matched;
+               char *name, *val;
+
+               debug("Sending environment.");
+               for (i = 0; env[i] != NULL; i++) {
+                       /* Split */
+                       name = xstrdup(env[i]);
+                       if ((val = strchr(name, '=')) == NULL) {
+                               xfree(name);
+                               continue;
+                       }
+                       *val++ = '\0';
+
+                       matched = 0;
+                       for (j = 0; j < options.num_send_env; j++) {
+                               if (match_pattern(name, options.send_env[j])) {
+                                       matched = 1;
+                                       break;
+                               }
+                       }
+                       if (!matched) {
+                               debug3("Ignored env %s", name);
+                               xfree(name);
+                               continue;
+                       }
+
+                       debug("Sending env %s = %s", name, val);
+                       channel_request_start(id, "env", 0);
+                       packet_put_cstring(name);
+                       packet_put_cstring(val);
+                       packet_send();
+                       xfree(name);
+               }
+       }
+
+       len = buffer_len(cmd);
+       if (len > 0) {
+               if (len > 900)
+                       len = 900;
+               if (want_subsystem) {
+                       debug("Sending subsystem: %.*s",
+                           len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "subsystem", 1);
+                       client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
+               } else {
+                       debug("Sending command: %.*s",
+                           len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "exec", 1);
+                       client_expect_confirm(id, "exec", CONFIRM_CLOSE);
+               }
+               packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
+               packet_send();
+       } else {
+               channel_request_start(id, "shell", 1);
+               client_expect_confirm(id, "shell", CONFIRM_CLOSE);
+               packet_send();
+       }
+}
+
+static void
+client_init_dispatch_20(void)
+{
+       dispatch_init(&dispatch_protocol_error);
+
+       dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+       dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+       dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
+       dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+       dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
+       dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
+       dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
+
+       /* rekeying */
+       dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+
+       /* global request reply messages */
+       dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
+       dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
+}
+
+static void
+client_init_dispatch_13(void)
+{
+       dispatch_init(NULL);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
+       dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
+       dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
+       dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
+
+       dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
+           &client_input_agent_open : &deny_input_open);
+       dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
+           &x11_input_open : &deny_input_open);
+}
+
+static void
+client_init_dispatch_15(void)
+{
+       client_init_dispatch_13();
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
+}
+
+static void
+client_init_dispatch(void)
+{
+       if (compat20)
+               client_init_dispatch_20();
+       else if (compat13)
+               client_init_dispatch_13();
+       else
+               client_init_dispatch_15();
+}
+
+void
+client_stop_mux(void)
+{
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+       /*
+        * If we are in persist mode, signal that we should close when all
+        * active channels are closed.
+        */
+       if (options.control_persist) {
+               session_closed = 1;
+               setproctitle("[stopped mux]");
+       }
+}
+
+/* client specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       leave_non_blocking();
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+       ssh_kill_proxy_command();
+       _exit(i);
+}
diff --git a/.pc/scp-quoting.patch/scp.c b/.pc/scp-quoting.patch/scp.c
new file mode 100644 (file)
index 0000000..18b2597
--- /dev/null
@@ -0,0 +1,1329 @@
+/* $OpenBSD: scp.c,v 1.170 2010/12/09 14:13:33 jmc Exp $ */
+/*
+ * scp - secure remote copy.  This is basically patched BSD rcp which
+ * uses ssh to do the data transfer (instead of using rcmd).
+ *
+ * NOTE: This version should NOT be suid root.  (This uses ssh to
+ * do the transfer and ssh has the necessary privileges.)
+ *
+ * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+/*
+ * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+ * Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Parts from:
+ *
+ * Copyright (c) 1983, 1990, 1992, 1993, 1995
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+# endif
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/wait.h>
+#include <sys/uio.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
+#include <vis.h>
+#endif
+
+#include "xmalloc.h"
+#include "atomicio.h"
+#include "pathnames.h"
+#include "log.h"
+#include "misc.h"
+#include "progressmeter.h"
+
+extern char *__progname;
+
+#define COPY_BUFLEN    16384
+
+int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
+int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout);
+
+/* Struct for addargs */
+arglist args;
+arglist remote_remote_args;
+
+/* Bandwidth limit */
+long long limit_kbps = 0;
+struct bwlimit bwlimit;
+
+/* Name of current file being transferred. */
+char *curfile;
+
+/* This is set to non-zero to enable verbose mode. */
+int verbose_mode = 0;
+
+/* This is set to zero if the progressmeter is not desired. */
+int showprogress = 1;
+
+/*
+ * This is set to non-zero if remote-remote copy should be piped
+ * through this process.
+ */
+int throughlocal = 0;
+
+/* This is the program to execute for the secured connection. ("ssh" or -S) */
+char *ssh_program = _PATH_SSH_PROGRAM;
+
+/* This is used to store the pid of ssh_program */
+pid_t do_cmd_pid = -1;
+
+static void
+killchild(int signo)
+{
+       if (do_cmd_pid > 1) {
+               kill(do_cmd_pid, signo ? signo : SIGTERM);
+               waitpid(do_cmd_pid, NULL, 0);
+       }
+
+       if (signo)
+               _exit(1);
+       exit(1);
+}
+
+static void
+suspchild(int signo)
+{
+       int status;
+
+       if (do_cmd_pid > 1) {
+               kill(do_cmd_pid, signo);
+               while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 &&
+                   errno == EINTR)
+                       ;
+               kill(getpid(), SIGSTOP);
+       }
+}
+
+static int
+do_local_cmd(arglist *a)
+{
+       u_int i;
+       int status;
+       pid_t pid;
+
+       if (a->num == 0)
+               fatal("do_local_cmd: no arguments");
+
+       if (verbose_mode) {
+               fprintf(stderr, "Executing:");
+               for (i = 0; i < a->num; i++)
+                       fprintf(stderr, " %s", a->list[i]);
+               fprintf(stderr, "\n");
+       }
+       if ((pid = fork()) == -1)
+               fatal("do_local_cmd: fork: %s", strerror(errno));
+
+       if (pid == 0) {
+               execvp(a->list[0], a->list);
+               perror(a->list[0]);
+               exit(1);
+       }
+
+       do_cmd_pid = pid;
+       signal(SIGTERM, killchild);
+       signal(SIGINT, killchild);
+       signal(SIGHUP, killchild);
+
+       while (waitpid(pid, &status, 0) == -1)
+               if (errno != EINTR)
+                       fatal("do_local_cmd: waitpid: %s", strerror(errno));
+
+       do_cmd_pid = -1;
+
+       if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+               return (-1);
+
+       return (0);
+}
+
+/*
+ * This function executes the given command as the specified user on the
+ * given host.  This returns < 0 if execution fails, and >= 0 otherwise. This
+ * assigns the input and output file descriptors on success.
+ */
+
+int
+do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
+{
+       int pin[2], pout[2], reserved[2];
+
+       if (verbose_mode)
+               fprintf(stderr,
+                   "Executing: program %s host %s, user %s, command %s\n",
+                   ssh_program, host,
+                   remuser ? remuser : "(unspecified)", cmd);
+
+       /*
+        * Reserve two descriptors so that the real pipes won't get
+        * descriptors 0 and 1 because that will screw up dup2 below.
+        */
+       if (pipe(reserved) < 0)
+               fatal("pipe: %s", strerror(errno));
+
+       /* Create a socket pair for communicating with ssh. */
+       if (pipe(pin) < 0)
+               fatal("pipe: %s", strerror(errno));
+       if (pipe(pout) < 0)
+               fatal("pipe: %s", strerror(errno));
+
+       /* Free the reserved descriptors. */
+       close(reserved[0]);
+       close(reserved[1]);
+
+       signal(SIGTSTP, suspchild);
+       signal(SIGTTIN, suspchild);
+       signal(SIGTTOU, suspchild);
+
+       /* Fork a child to execute the command on the remote host using ssh. */
+       do_cmd_pid = fork();
+       if (do_cmd_pid == 0) {
+               /* Child. */
+               close(pin[1]);
+               close(pout[0]);
+               dup2(pin[0], 0);
+               dup2(pout[1], 1);
+               close(pin[0]);
+               close(pout[1]);
+
+               replacearg(&args, 0, "%s", ssh_program);
+               if (remuser != NULL) {
+                       addargs(&args, "-l");
+                       addargs(&args, "%s", remuser);
+               }
+               addargs(&args, "--");
+               addargs(&args, "%s", host);
+               addargs(&args, "%s", cmd);
+
+               execvp(ssh_program, args.list);
+               perror(ssh_program);
+               exit(1);
+       } else if (do_cmd_pid == -1) {
+               fatal("fork: %s", strerror(errno));
+       }
+       /* Parent.  Close the other side, and return the local side. */
+       close(pin[0]);
+       *fdout = pin[1];
+       close(pout[1]);
+       *fdin = pout[0];
+       signal(SIGTERM, killchild);
+       signal(SIGINT, killchild);
+       signal(SIGHUP, killchild);
+       return 0;
+}
+
+/*
+ * This functions executes a command simlar to do_cmd(), but expects the
+ * input and output descriptors to be setup by a previous call to do_cmd().
+ * This way the input and output of two commands can be connected.
+ */
+int
+do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
+{
+       pid_t pid;
+       int status;
+
+       if (verbose_mode)
+               fprintf(stderr,
+                   "Executing: 2nd program %s host %s, user %s, command %s\n",
+                   ssh_program, host,
+                   remuser ? remuser : "(unspecified)", cmd);
+
+       /* Fork a child to execute the command on the remote host using ssh. */
+       pid = fork();
+       if (pid == 0) {
+               dup2(fdin, 0);
+               dup2(fdout, 1);
+
+               replacearg(&args, 0, "%s", ssh_program);
+               if (remuser != NULL) {
+                       addargs(&args, "-l");
+                       addargs(&args, "%s", remuser);
+               }
+               addargs(&args, "--");
+               addargs(&args, "%s", host);
+               addargs(&args, "%s", cmd);
+
+               execvp(ssh_program, args.list);
+               perror(ssh_program);
+               exit(1);
+       } else if (pid == -1) {
+               fatal("fork: %s", strerror(errno));
+       }
+       while (waitpid(pid, &status, 0) == -1)
+               if (errno != EINTR)
+                       fatal("do_cmd2: waitpid: %s", strerror(errno));
+       return 0;
+}
+
+typedef struct {
+       size_t cnt;
+       char *buf;
+} BUF;
+
+BUF *allocbuf(BUF *, int, int);
+void lostconn(int);
+int okname(char *);
+void run_err(const char *,...);
+void verifydir(char *);
+
+struct passwd *pwd;
+uid_t userid;
+int errs, remin, remout;
+int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+
+#define        CMDNEEDS        64
+char cmd[CMDNEEDS];            /* must hold "rcp -r -p -d\0" */
+
+int response(void);
+void rsource(char *, struct stat *);
+void sink(int, char *[]);
+void source(int, char *[]);
+void tolocal(int, char *[]);
+void toremote(char *, int, char *[]);
+void usage(void);
+
+int
+main(int argc, char **argv)
+{
+       int ch, fflag, tflag, status, n;
+       char *targ, **newargv;
+       const char *errstr;
+       extern char *optarg;
+       extern int optind;
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       /* Copy argv, because we modify it */
+       newargv = xcalloc(MAX(argc + 1, 1), sizeof(*newargv));
+       for (n = 0; n < argc; n++)
+               newargv[n] = xstrdup(argv[n]);
+       argv = newargv;
+
+       __progname = ssh_get_progname(argv[0]);
+
+       memset(&args, '\0', sizeof(args));
+       memset(&remote_remote_args, '\0', sizeof(remote_remote_args));
+       args.list = remote_remote_args.list = NULL;
+       addargs(&args, "%s", ssh_program);
+       addargs(&args, "-x");
+       addargs(&args, "-oForwardAgent=no");
+       addargs(&args, "-oPermitLocalCommand=no");
+       addargs(&args, "-oClearAllForwardings=yes");
+
+       fflag = tflag = 0;
+       while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
+               switch (ch) {
+               /* User-visible flags. */
+               case '1':
+               case '2':
+               case '4':
+               case '6':
+               case 'C':
+                       addargs(&args, "-%c", ch);
+                       addargs(&remote_remote_args, "-%c", ch);
+                       break;
+               case '3':
+                       throughlocal = 1;
+                       break;
+               case 'o':
+               case 'c':
+               case 'i':
+               case 'F':
+                       addargs(&remote_remote_args, "-%c", ch);
+                       addargs(&remote_remote_args, "%s", optarg);
+                       addargs(&args, "-%c", ch);
+                       addargs(&args, "%s", optarg);
+                       break;
+               case 'P':
+                       addargs(&remote_remote_args, "-p");
+                       addargs(&remote_remote_args, "%s", optarg);
+                       addargs(&args, "-p");
+                       addargs(&args, "%s", optarg);
+                       break;
+               case 'B':
+                       addargs(&remote_remote_args, "-oBatchmode=yes");
+                       addargs(&args, "-oBatchmode=yes");
+                       break;
+               case 'l':
+                       limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
+                           &errstr);
+                       if (errstr != NULL)
+                               usage();
+                       limit_kbps *= 1024; /* kbps */
+                       bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN);
+                       break;
+               case 'p':
+                       pflag = 1;
+                       break;
+               case 'r':
+                       iamrecursive = 1;
+                       break;
+               case 'S':
+                       ssh_program = xstrdup(optarg);
+                       break;
+               case 'v':
+                       addargs(&args, "-v");
+                       addargs(&remote_remote_args, "-v");
+                       verbose_mode = 1;
+                       break;
+               case 'q':
+                       addargs(&args, "-q");
+                       addargs(&remote_remote_args, "-q");
+                       showprogress = 0;
+                       break;
+
+               /* Server options. */
+               case 'd':
+                       targetshouldbedirectory = 1;
+                       break;
+               case 'f':       /* "from" */
+                       iamremote = 1;
+                       fflag = 1;
+                       break;
+               case 't':       /* "to" */
+                       iamremote = 1;
+                       tflag = 1;
+#ifdef HAVE_CYGWIN
+                       setmode(0, O_BINARY);
+#endif
+                       break;
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if ((pwd = getpwuid(userid = getuid())) == NULL)
+               fatal("unknown user %u", (u_int) userid);
+
+       if (!isatty(STDOUT_FILENO))
+               showprogress = 0;
+
+       remin = STDIN_FILENO;
+       remout = STDOUT_FILENO;
+
+       if (fflag) {
+               /* Follow "protocol", send data. */
+               (void) response();
+               source(argc, argv);
+               exit(errs != 0);
+       }
+       if (tflag) {
+               /* Receive data. */
+               sink(argc, argv);
+               exit(errs != 0);
+       }
+       if (argc < 2)
+               usage();
+       if (argc > 2)
+               targetshouldbedirectory = 1;
+
+       remin = remout = -1;
+       do_cmd_pid = -1;
+       /* Command to be executed on remote system using "ssh". */
+       (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
+           verbose_mode ? " -v" : "",
+           iamrecursive ? " -r" : "", pflag ? " -p" : "",
+           targetshouldbedirectory ? " -d" : "");
+
+       (void) signal(SIGPIPE, lostconn);
+
+       if ((targ = colon(argv[argc - 1])))     /* Dest is remote host. */
+               toremote(targ, argc, argv);
+       else {
+               if (targetshouldbedirectory)
+                       verifydir(argv[argc - 1]);
+               tolocal(argc, argv);    /* Dest is local host. */
+       }
+       /*
+        * Finally check the exit status of the ssh process, if one was forked
+        * and no error has occurred yet
+        */
+       if (do_cmd_pid != -1 && errs == 0) {
+               if (remin != -1)
+                   (void) close(remin);
+               if (remout != -1)
+                   (void) close(remout);
+               if (waitpid(do_cmd_pid, &status, 0) == -1)
+                       errs = 1;
+               else {
+                       if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+                               errs = 1;
+               }
+       }
+       exit(errs != 0);
+}
+
+/* Callback from atomicio6 to update progress meter and limit bandwidth */
+static int
+scpio(void *_cnt, size_t s)
+{
+       off_t *cnt = (off_t *)_cnt;
+
+       *cnt += s;
+       if (limit_kbps > 0)
+               bandwidth_limit(&bwlimit, s);
+       return 0;
+}
+
+void
+toremote(char *targ, int argc, char **argv)
+{
+       char *bp, *host, *src, *suser, *thost, *tuser, *arg;
+       arglist alist;
+       int i;
+       u_int j;
+
+       memset(&alist, '\0', sizeof(alist));
+       alist.list = NULL;
+
+       *targ++ = 0;
+       if (*targ == 0)
+               targ = ".";
+
+       arg = xstrdup(argv[argc - 1]);
+       if ((thost = strrchr(arg, '@'))) {
+               /* user@host */
+               *thost++ = 0;
+               tuser = arg;
+               if (*tuser == '\0')
+                       tuser = NULL;
+       } else {
+               thost = arg;
+               tuser = NULL;
+       }
+
+       if (tuser != NULL && !okname(tuser)) {
+               xfree(arg);
+               return;
+       }
+
+       for (i = 0; i < argc - 1; i++) {
+               src = colon(argv[i]);
+               if (src && throughlocal) {      /* extended remote to remote */
+                       *src++ = 0;
+                       if (*src == 0)
+                               src = ".";
+                       host = strrchr(argv[i], '@');
+                       if (host) {
+                               *host++ = 0;
+                               host = cleanhostname(host);
+                               suser = argv[i];
+                               if (*suser == '\0')
+                                       suser = pwd->pw_name;
+                               else if (!okname(suser))
+                                       continue;
+                       } else {
+                               host = cleanhostname(argv[i]);
+                               suser = NULL;
+                       }
+                       xasprintf(&bp, "%s -f -- %s", cmd, src);
+                       if (do_cmd(host, suser, bp, &remin, &remout) < 0)
+                               exit(1);
+                       (void) xfree(bp);
+                       host = cleanhostname(thost);
+                       xasprintf(&bp, "%s -t -- %s", cmd, targ);
+                       if (do_cmd2(host, tuser, bp, remin, remout) < 0)
+                               exit(1);
+                       (void) xfree(bp);
+                       (void) close(remin);
+                       (void) close(remout);
+                       remin = remout = -1;
+               } else if (src) {       /* standard remote to remote */
+                       freeargs(&alist);
+                       addargs(&alist, "%s", ssh_program);
+                       addargs(&alist, "-x");
+                       addargs(&alist, "-oClearAllForwardings=yes");
+                       addargs(&alist, "-n");
+                       for (j = 0; j < remote_remote_args.num; j++) {
+                               addargs(&alist, "%s",
+                                   remote_remote_args.list[j]);
+                       }
+                       *src++ = 0;
+                       if (*src == 0)
+                               src = ".";
+                       host = strrchr(argv[i], '@');
+
+                       if (host) {
+                               *host++ = 0;
+                               host = cleanhostname(host);
+                               suser = argv[i];
+                               if (*suser == '\0')
+                                       suser = pwd->pw_name;
+                               else if (!okname(suser))
+                                       continue;
+                               addargs(&alist, "-l");
+                               addargs(&alist, "%s", suser);
+                       } else {
+                               host = cleanhostname(argv[i]);
+                       }
+                       addargs(&alist, "--");
+                       addargs(&alist, "%s", host);
+                       addargs(&alist, "%s", cmd);
+                       addargs(&alist, "%s", src);
+                       addargs(&alist, "%s%s%s:%s",
+                           tuser ? tuser : "", tuser ? "@" : "",
+                           thost, targ);
+                       if (do_local_cmd(&alist) != 0)
+                               errs = 1;
+               } else {        /* local to remote */
+                       if (remin == -1) {
+                               xasprintf(&bp, "%s -t -- %s", cmd, targ);
+                               host = cleanhostname(thost);
+                               if (do_cmd(host, tuser, bp, &remin,
+                                   &remout) < 0)
+                                       exit(1);
+                               if (response() < 0)
+                                       exit(1);
+                               (void) xfree(bp);
+                       }
+                       source(1, argv + i);
+               }
+       }
+       xfree(arg);
+}
+
+void
+tolocal(int argc, char **argv)
+{
+       char *bp, *host, *src, *suser;
+       arglist alist;
+       int i;
+
+       memset(&alist, '\0', sizeof(alist));
+       alist.list = NULL;
+
+       for (i = 0; i < argc - 1; i++) {
+               if (!(src = colon(argv[i]))) {  /* Local to local. */
+                       freeargs(&alist);
+                       addargs(&alist, "%s", _PATH_CP);
+                       if (iamrecursive)
+                               addargs(&alist, "-r");
+                       if (pflag)
+                               addargs(&alist, "-p");
+                       addargs(&alist, "--");
+                       addargs(&alist, "%s", argv[i]);
+                       addargs(&alist, "%s", argv[argc-1]);
+                       if (do_local_cmd(&alist))
+                               ++errs;
+                       continue;
+               }
+               *src++ = 0;
+               if (*src == 0)
+                       src = ".";
+               if ((host = strrchr(argv[i], '@')) == NULL) {
+                       host = argv[i];
+                       suser = NULL;
+               } else {
+                       *host++ = 0;
+                       suser = argv[i];
+                       if (*suser == '\0')
+                               suser = pwd->pw_name;
+               }
+               host = cleanhostname(host);
+               xasprintf(&bp, "%s -f -- %s", cmd, src);
+               if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
+                       (void) xfree(bp);
+                       ++errs;
+                       continue;
+               }
+               xfree(bp);
+               sink(1, argv + argc - 1);
+               (void) close(remin);
+               remin = remout = -1;
+       }
+}
+
+void
+source(int argc, char **argv)
+{
+       struct stat stb;
+       static BUF buffer;
+       BUF *bp;
+       off_t i, statbytes;
+       size_t amt;
+       int fd = -1, haderr, indx;
+       char *last, *name, buf[2048], encname[MAXPATHLEN];
+       int len;
+
+       for (indx = 0; indx < argc; ++indx) {
+               name = argv[indx];
+               statbytes = 0;
+               len = strlen(name);
+               while (len > 1 && name[len-1] == '/')
+                       name[--len] = '\0';
+               if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
+                       goto syserr;
+               if (strchr(name, '\n') != NULL) {
+                       strnvis(encname, name, sizeof(encname), VIS_NL);
+                       name = encname;
+               }
+               if (fstat(fd, &stb) < 0) {
+syserr:                        run_err("%s: %s", name, strerror(errno));
+                       goto next;
+               }
+               if (stb.st_size < 0) {
+                       run_err("%s: %s", name, "Negative file size");
+                       goto next;
+               }
+               unset_nonblock(fd);
+               switch (stb.st_mode & S_IFMT) {
+               case S_IFREG:
+                       break;
+               case S_IFDIR:
+                       if (iamrecursive) {
+                               rsource(name, &stb);
+                               goto next;
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       run_err("%s: not a regular file", name);
+                       goto next;
+               }
+               if ((last = strrchr(name, '/')) == NULL)
+                       last = name;
+               else
+                       ++last;
+               curfile = last;
+               if (pflag) {
+                       /*
+                        * Make it compatible with possible future
+                        * versions expecting microseconds.
+                        */
+                       (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",
+                           (u_long) (stb.st_mtime < 0 ? 0 : stb.st_mtime),
+                           (u_long) (stb.st_atime < 0 ? 0 : stb.st_atime));
+                       if (verbose_mode) {
+                               fprintf(stderr, "File mtime %ld atime %ld\n",
+                                   (long)stb.st_mtime, (long)stb.st_atime);
+                               fprintf(stderr, "Sending file timestamps: %s",
+                                   buf);
+                       }
+                       (void) atomicio(vwrite, remout, buf, strlen(buf));
+                       if (response() < 0)
+                               goto next;
+               }
+#define        FILEMODEMASK    (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+               snprintf(buf, sizeof buf, "C%04o %lld %s\n",
+                   (u_int) (stb.st_mode & FILEMODEMASK),
+                   (long long)stb.st_size, last);
+               if (verbose_mode) {
+                       fprintf(stderr, "Sending file modes: %s", buf);
+               }
+               (void) atomicio(vwrite, remout, buf, strlen(buf));
+               if (response() < 0)
+                       goto next;
+               if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
+next:                  if (fd != -1) {
+                               (void) close(fd);
+                               fd = -1;
+                       }
+                       continue;
+               }
+               if (showprogress)
+                       start_progress_meter(curfile, stb.st_size, &statbytes);
+               set_nonblock(remout);
+               for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
+                       amt = bp->cnt;
+                       if (i + (off_t)amt > stb.st_size)
+                               amt = stb.st_size - i;
+                       if (!haderr) {
+                               if (atomicio(read, fd, bp->buf, amt) != amt)
+                                       haderr = errno;
+                       }
+                       /* Keep writing after error to retain sync */
+                       if (haderr) {
+                               (void)atomicio(vwrite, remout, bp->buf, amt);
+                               continue;
+                       }
+                       if (atomicio6(vwrite, remout, bp->buf, amt, scpio,
+                           &statbytes) != amt)
+                               haderr = errno;
+               }
+               unset_nonblock(remout);
+               if (showprogress)
+                       stop_progress_meter();
+
+               if (fd != -1) {
+                       if (close(fd) < 0 && !haderr)
+                               haderr = errno;
+                       fd = -1;
+               }
+               if (!haderr)
+                       (void) atomicio(vwrite, remout, "", 1);
+               else
+                       run_err("%s: %s", name, strerror(haderr));
+               (void) response();
+       }
+}
+
+void
+rsource(char *name, struct stat *statp)
+{
+       DIR *dirp;
+       struct dirent *dp;
+       char *last, *vect[1], path[1100];
+
+       if (!(dirp = opendir(name))) {
+               run_err("%s: %s", name, strerror(errno));
+               return;
+       }
+       last = strrchr(name, '/');
+       if (last == 0)
+               last = name;
+       else
+               last++;
+       if (pflag) {
+               (void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n",
+                   (u_long) statp->st_mtime,
+                   (u_long) statp->st_atime);
+               (void) atomicio(vwrite, remout, path, strlen(path));
+               if (response() < 0) {
+                       closedir(dirp);
+                       return;
+               }
+       }
+       (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
+           (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
+       if (verbose_mode)
+               fprintf(stderr, "Entering directory: %s", path);
+       (void) atomicio(vwrite, remout, path, strlen(path));
+       if (response() < 0) {
+               closedir(dirp);
+               return;
+       }
+       while ((dp = readdir(dirp)) != NULL) {
+               if (dp->d_ino == 0)
+                       continue;
+               if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+                       continue;
+               if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
+                       run_err("%s/%s: name too long", name, dp->d_name);
+                       continue;
+               }
+               (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
+               vect[0] = path;
+               source(1, vect);
+       }
+       (void) closedir(dirp);
+       (void) atomicio(vwrite, remout, "E\n", 2);
+       (void) response();
+}
+
+void
+sink(int argc, char **argv)
+{
+       static BUF buffer;
+       struct stat stb;
+       enum {
+               YES, NO, DISPLAYED
+       } wrerr;
+       BUF *bp;
+       off_t i;
+       size_t j, count;
+       int amt, exists, first, ofd;
+       mode_t mode, omode, mask;
+       off_t size, statbytes;
+       int setimes, targisdir, wrerrno = 0;
+       char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
+       struct timeval tv[2];
+
+#define        atime   tv[0]
+#define        mtime   tv[1]
+#define        SCREWUP(str)    { why = str; goto screwup; }
+
+       setimes = targisdir = 0;
+       mask = umask(0);
+       if (!pflag)
+               (void) umask(mask);
+       if (argc != 1) {
+               run_err("ambiguous target");
+               exit(1);
+       }
+       targ = *argv;
+       if (targetshouldbedirectory)
+               verifydir(targ);
+
+       (void) atomicio(vwrite, remout, "", 1);
+       if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
+               targisdir = 1;
+       for (first = 1;; first = 0) {
+               cp = buf;
+               if (atomicio(read, remin, cp, 1) != 1)
+                       return;
+               if (*cp++ == '\n')
+                       SCREWUP("unexpected <newline>");
+               do {
+                       if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
+                               SCREWUP("lost connection");
+                       *cp++ = ch;
+               } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
+               *cp = 0;
+               if (verbose_mode)
+                       fprintf(stderr, "Sink: %s", buf);
+
+               if (buf[0] == '\01' || buf[0] == '\02') {
+                       if (iamremote == 0)
+                               (void) atomicio(vwrite, STDERR_FILENO,
+                                   buf + 1, strlen(buf + 1));
+                       if (buf[0] == '\02')
+                               exit(1);
+                       ++errs;
+                       continue;
+               }
+               if (buf[0] == 'E') {
+                       (void) atomicio(vwrite, remout, "", 1);
+                       return;
+               }
+               if (ch == '\n')
+                       *--cp = 0;
+
+               cp = buf;
+               if (*cp == 'T') {
+                       setimes++;
+                       cp++;
+                       mtime.tv_sec = strtol(cp, &cp, 10);
+                       if (!cp || *cp++ != ' ')
+                               SCREWUP("mtime.sec not delimited");
+                       mtime.tv_usec = strtol(cp, &cp, 10);
+                       if (!cp || *cp++ != ' ')
+                               SCREWUP("mtime.usec not delimited");
+                       atime.tv_sec = strtol(cp, &cp, 10);
+                       if (!cp || *cp++ != ' ')
+                               SCREWUP("atime.sec not delimited");
+                       atime.tv_usec = strtol(cp, &cp, 10);
+                       if (!cp || *cp++ != '\0')
+                               SCREWUP("atime.usec not delimited");
+                       (void) atomicio(vwrite, remout, "", 1);
+                       continue;
+               }
+               if (*cp != 'C' && *cp != 'D') {
+                       /*
+                        * Check for the case "rcp remote:foo\* local:bar".
+                        * In this case, the line "No match." can be returned
+                        * by the shell before the rcp command on the remote is
+                        * executed so the ^Aerror_message convention isn't
+                        * followed.
+                        */
+                       if (first) {
+                               run_err("%s", cp);
+                               exit(1);
+                       }
+                       SCREWUP("expected control record");
+               }
+               mode = 0;
+               for (++cp; cp < buf + 5; cp++) {
+                       if (*cp < '0' || *cp > '7')
+                               SCREWUP("bad mode");
+                       mode = (mode << 3) | (*cp - '0');
+               }
+               if (*cp++ != ' ')
+                       SCREWUP("mode not delimited");
+
+               for (size = 0; isdigit(*cp);)
+                       size = size * 10 + (*cp++ - '0');
+               if (*cp++ != ' ')
+                       SCREWUP("size not delimited");
+               if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
+                       run_err("error: unexpected filename: %s", cp);
+                       exit(1);
+               }
+               if (targisdir) {
+                       static char *namebuf;
+                       static size_t cursize;
+                       size_t need;
+
+                       need = strlen(targ) + strlen(cp) + 250;
+                       if (need > cursize) {
+                               if (namebuf)
+                                       xfree(namebuf);
+                               namebuf = xmalloc(need);
+                               cursize = need;
+                       }
+                       (void) snprintf(namebuf, need, "%s%s%s", targ,
+                           strcmp(targ, "/") ? "/" : "", cp);
+                       np = namebuf;
+               } else
+                       np = targ;
+               curfile = cp;
+               exists = stat(np, &stb) == 0;
+               if (buf[0] == 'D') {
+                       int mod_flag = pflag;
+                       if (!iamrecursive)
+                               SCREWUP("received directory without -r");
+                       if (exists) {
+                               if (!S_ISDIR(stb.st_mode)) {
+                                       errno = ENOTDIR;
+                                       goto bad;
+                               }
+                               if (pflag)
+                                       (void) chmod(np, mode);
+                       } else {
+                               /* Handle copying from a read-only
+                                  directory */
+                               mod_flag = 1;
+                               if (mkdir(np, mode | S_IRWXU) < 0)
+                                       goto bad;
+                       }
+                       vect[0] = xstrdup(np);
+                       sink(1, vect);
+                       if (setimes) {
+                               setimes = 0;
+                               if (utimes(vect[0], tv) < 0)
+                                       run_err("%s: set times: %s",
+                                           vect[0], strerror(errno));
+                       }
+                       if (mod_flag)
+                               (void) chmod(vect[0], mode);
+                       if (vect[0])
+                               xfree(vect[0]);
+                       continue;
+               }
+               omode = mode;
+               mode |= S_IWRITE;
+               if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
+bad:                   run_err("%s: %s", np, strerror(errno));
+                       continue;
+               }
+               (void) atomicio(vwrite, remout, "", 1);
+               if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
+                       (void) close(ofd);
+                       continue;
+               }
+               cp = bp->buf;
+               wrerr = NO;
+
+               statbytes = 0;
+               if (showprogress)
+                       start_progress_meter(curfile, size, &statbytes);
+               set_nonblock(remin);
+               for (count = i = 0; i < size; i += bp->cnt) {
+                       amt = bp->cnt;
+                       if (i + amt > size)
+                               amt = size - i;
+                       count += amt;
+                       do {
+                               j = atomicio6(read, remin, cp, amt,
+                                   scpio, &statbytes);
+                               if (j == 0) {
+                                       run_err("%s", j != EPIPE ?
+                                           strerror(errno) :
+                                           "dropped connection");
+                                       exit(1);
+                               }
+                               amt -= j;
+                               cp += j;
+                       } while (amt > 0);
+
+                       if (count == bp->cnt) {
+                               /* Keep reading so we stay sync'd up. */
+                               if (wrerr == NO) {
+                                       if (atomicio(vwrite, ofd, bp->buf,
+                                           count) != count) {
+                                               wrerr = YES;
+                                               wrerrno = errno;
+                                       }
+                               }
+                               count = 0;
+                               cp = bp->buf;
+                       }
+               }
+               unset_nonblock(remin);
+               if (showprogress)
+                       stop_progress_meter();
+               if (count != 0 && wrerr == NO &&
+                   atomicio(vwrite, ofd, bp->buf, count) != count) {
+                       wrerr = YES;
+                       wrerrno = errno;
+               }
+               if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) &&
+                   ftruncate(ofd, size) != 0) {
+                       run_err("%s: truncate: %s", np, strerror(errno));
+                       wrerr = DISPLAYED;
+               }
+               if (pflag) {
+                       if (exists || omode != mode)
+#ifdef HAVE_FCHMOD
+                               if (fchmod(ofd, omode)) {
+#else /* HAVE_FCHMOD */
+                               if (chmod(np, omode)) {
+#endif /* HAVE_FCHMOD */
+                                       run_err("%s: set mode: %s",
+                                           np, strerror(errno));
+                                       wrerr = DISPLAYED;
+                               }
+               } else {
+                       if (!exists && omode != mode)
+#ifdef HAVE_FCHMOD
+                               if (fchmod(ofd, omode & ~mask)) {
+#else /* HAVE_FCHMOD */
+                               if (chmod(np, omode & ~mask)) {
+#endif /* HAVE_FCHMOD */
+                                       run_err("%s: set mode: %s",
+                                           np, strerror(errno));
+                                       wrerr = DISPLAYED;
+                               }
+               }
+               if (close(ofd) == -1) {
+                       wrerr = YES;
+                       wrerrno = errno;
+               }
+               (void) response();
+               if (setimes && wrerr == NO) {
+                       setimes = 0;
+                       if (utimes(np, tv) < 0) {
+                               run_err("%s: set times: %s",
+                                   np, strerror(errno));
+                               wrerr = DISPLAYED;
+                       }
+               }
+               switch (wrerr) {
+               case YES:
+                       run_err("%s: %s", np, strerror(wrerrno));
+                       break;
+               case NO:
+                       (void) atomicio(vwrite, remout, "", 1);
+                       break;
+               case DISPLAYED:
+                       break;
+               }
+       }
+screwup:
+       run_err("protocol error: %s", why);
+       exit(1);
+}
+
+int
+response(void)
+{
+       char ch, *cp, resp, rbuf[2048];
+
+       if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
+               lostconn(0);
+
+       cp = rbuf;
+       switch (resp) {
+       case 0:         /* ok */
+               return (0);
+       default:
+               *cp++ = resp;
+               /* FALLTHROUGH */
+       case 1:         /* error, followed by error msg */
+       case 2:         /* fatal error, "" */
+               do {
+                       if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
+                               lostconn(0);
+                       *cp++ = ch;
+               } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
+
+               if (!iamremote)
+                       (void) atomicio(vwrite, STDERR_FILENO, rbuf, cp - rbuf);
+               ++errs;
+               if (resp == 1)
+                       return (-1);
+               exit(1);
+       }
+       /* NOTREACHED */
+}
+
+void
+usage(void)
+{
+       (void) fprintf(stderr,
+           "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
+           "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
+           "           [[user@]host1:]file1 ... [[user@]host2:]file2\n");
+       exit(1);
+}
+
+void
+run_err(const char *fmt,...)
+{
+       static FILE *fp;
+       va_list ap;
+
+       ++errs;
+       if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) {
+               (void) fprintf(fp, "%c", 0x01);
+               (void) fprintf(fp, "scp: ");
+               va_start(ap, fmt);
+               (void) vfprintf(fp, fmt, ap);
+               va_end(ap);
+               (void) fprintf(fp, "\n");
+               (void) fflush(fp);
+       }
+
+       if (!iamremote) {
+               va_start(ap, fmt);
+               vfprintf(stderr, fmt, ap);
+               va_end(ap);
+               fprintf(stderr, "\n");
+       }
+}
+
+void
+verifydir(char *cp)
+{
+       struct stat stb;
+
+       if (!stat(cp, &stb)) {
+               if (S_ISDIR(stb.st_mode))
+                       return;
+               errno = ENOTDIR;
+       }
+       run_err("%s: %s", cp, strerror(errno));
+       killchild(0);
+}
+
+int
+okname(char *cp0)
+{
+       int c;
+       char *cp;
+
+       cp = cp0;
+       do {
+               c = (int)*cp;
+               if (c & 0200)
+                       goto bad;
+               if (!isalpha(c) && !isdigit(c)) {
+                       switch (c) {
+                       case '\'':
+                       case '"':
+                       case '`':
+                       case ' ':
+                       case '#':
+                               goto bad;
+                       default:
+                               break;
+                       }
+               }
+       } while (*++cp);
+       return (1);
+
+bad:   fprintf(stderr, "%s: invalid user name\n", cp0);
+       return (0);
+}
+
+BUF *
+allocbuf(BUF *bp, int fd, int blksize)
+{
+       size_t size;
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+       struct stat stb;
+
+       if (fstat(fd, &stb) < 0) {
+               run_err("fstat: %s", strerror(errno));
+               return (0);
+       }
+       size = roundup(stb.st_blksize, blksize);
+       if (size == 0)
+               size = blksize;
+#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
+       size = blksize;
+#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
+       if (bp->cnt >= size)
+               return (bp);
+       if (bp->buf == NULL)
+               bp->buf = xmalloc(size);
+       else
+               bp->buf = xrealloc(bp->buf, 1, size);
+       memset(bp->buf, 0, size);
+       bp->cnt = size;
+       return (bp);
+}
+
+void
+lostconn(int signo)
+{
+       if (!iamremote)
+               write(STDERR_FILENO, "lost connection\n", 16);
+       if (signo)
+               _exit(1);
+       else
+               exit(1);
+}
diff --git a/.pc/selinux-role.patch/auth.h b/.pc/selinux-role.patch/auth.h
new file mode 100644 (file)
index 0000000..0d786c4
--- /dev/null
@@ -0,0 +1,206 @@
+/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */
+
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef AUTH_H
+#define AUTH_H
+
+#include <signal.h>
+
+#include <openssl/rsa.h>
+
+#ifdef HAVE_LOGIN_CAP
+#include <login_cap.h>
+#endif
+#ifdef BSD_AUTH
+#include <bsd_auth.h>
+#endif
+#ifdef KRB5
+#include <krb5.h>
+#endif
+
+typedef struct Authctxt Authctxt;
+typedef struct Authmethod Authmethod;
+typedef struct KbdintDevice KbdintDevice;
+
+struct Authctxt {
+       sig_atomic_t     success;
+       int              authenticated; /* authenticated and alarms cancelled */
+       int              postponed;     /* authentication needs another step */
+       int              valid;         /* user exists and is allowed to login */
+       int              attempt;
+       int              failures;
+       int              server_caused_failure; 
+       int              force_pwchange;
+       char            *user;          /* username sent by the client */
+       char            *service;
+       struct passwd   *pw;            /* set if 'valid' */
+       char            *style;
+       void            *kbdintctxt;
+       void            *jpake_ctx;
+#ifdef BSD_AUTH
+       auth_session_t  *as;
+#endif
+#ifdef KRB5
+       krb5_context     krb5_ctx;
+       krb5_ccache      krb5_fwd_ccache;
+       krb5_principal   krb5_user;
+       char            *krb5_ticket_file;
+       char            *krb5_ccname;
+#endif
+       Buffer          *loginmsg;
+       void            *methoddata;
+};
+/*
+ * Every authentication method has to handle authentication requests for
+ * non-existing users, or for users that are not allowed to login. In this
+ * case 'valid' is set to 0, but 'user' points to the username requested by
+ * the client.
+ */
+
+struct Authmethod {
+       char    *name;
+       int     (*userauth)(Authctxt *authctxt);
+       int     *enabled;
+};
+
+/*
+ * Keyboard interactive device:
+ * init_ctx    returns: non NULL upon success
+ * query       returns: 0 - success, otherwise failure
+ * respond     returns: 0 - success, 1 - need further interaction,
+ *             otherwise - failure
+ */
+struct KbdintDevice
+{
+       const char *name;
+       void*   (*init_ctx)(Authctxt*);
+       int     (*query)(void *ctx, char **name, char **infotxt,
+                   u_int *numprompts, char ***prompts, u_int **echo_on);
+       int     (*respond)(void *ctx, u_int numresp, char **responses);
+       void    (*free_ctx)(void *ctx);
+};
+
+int      auth_rhosts(struct passwd *, const char *);
+int
+auth_rhosts2(struct passwd *, const char *, const char *, const char *);
+
+int     auth_rhosts_rsa(Authctxt *, char *, Key *);
+int      auth_password(Authctxt *, const char *);
+int      auth_rsa(Authctxt *, BIGNUM *);
+int      auth_rsa_challenge_dialog(Key *);
+BIGNUM *auth_rsa_generate_challenge(Key *);
+int     auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
+int     auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
+
+int     auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
+int     hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
+int     user_key_allowed(struct passwd *, Key *);
+
+#ifdef KRB5
+int    auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
+int    auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
+int    auth_krb5_password(Authctxt *authctxt, const char *password);
+void   krb5_cleanup_proc(Authctxt *authctxt);
+#endif /* KRB5 */
+
+#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
+#include <shadow.h>
+int auth_shadow_acctexpired(struct spwd *);
+int auth_shadow_pwexpired(Authctxt *);
+#endif
+
+#include "auth-pam.h"
+#include "audit.h"
+void remove_kbdint_device(const char *);
+
+void disable_forwarding(void);
+
+void   do_authentication(Authctxt *);
+void   do_authentication2(Authctxt *);
+
+void   auth_log(Authctxt *, int, char *, char *);
+void   userauth_finish(Authctxt *, int, char *);
+void   userauth_send_banner(const char *);
+int    auth_root_allowed(char *);
+
+char   *auth2_read_banner(void);
+
+void   privsep_challenge_enable(void);
+
+int    auth2_challenge(Authctxt *, char *);
+void   auth2_challenge_stop(Authctxt *);
+int    bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
+int    bsdauth_respond(void *, u_int, char **);
+int    skey_query(void *, char **, char **, u_int *, char ***, u_int **);
+int    skey_respond(void *, u_int, char **);
+
+void   auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **);
+void   auth2_jpake_stop(Authctxt *);
+
+int    allowed_user(struct passwd *);
+struct passwd * getpwnamallow(const char *user);
+
+char   *get_challenge(Authctxt *);
+int    verify_response(Authctxt *, const char *);
+void   abandon_challenge_response(Authctxt *);
+
+char   *expand_authorized_keys(const char *, struct passwd *pw);
+char   *authorized_principals_file(struct passwd *);
+
+FILE   *auth_openkeyfile(const char *, struct passwd *, int);
+FILE   *auth_openprincipals(const char *, struct passwd *, int);
+int     auth_key_is_revoked(Key *);
+
+HostStatus
+check_key_in_hostfiles(struct passwd *, Key *, const char *,
+    const char *, const char *);
+
+/* hostkey handling */
+Key    *get_hostkey_by_index(int);
+Key    *get_hostkey_public_by_type(int);
+Key    *get_hostkey_private_by_type(int);
+int     get_hostkey_index(Key *);
+int     ssh1_session_key(BIGNUM *);
+
+/* debug messages during authentication */
+void    auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
+void    auth_debug_send(void);
+void    auth_debug_reset(void);
+
+struct passwd *fakepw(void);
+
+int     sys_auth_passwd(Authctxt *, const char *);
+
+#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
+
+#define SKEY_PROMPT "\nS/Key Password: "
+
+#if defined(KRB5) && !defined(HEIMDAL)
+#include <krb5.h>
+krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
+#endif
+#endif
diff --git a/.pc/selinux-role.patch/auth1.c b/.pc/selinux-role.patch/auth1.c
new file mode 100644 (file)
index 0000000..cc85aec
--- /dev/null
@@ -0,0 +1,437 @@
+/* $OpenBSD: auth1.c,v 1.75 2010/08/31 09:58:37 djm Exp $ */
+/*
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "rsa.h"
+#include "ssh1.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "channels.h"
+#include "session.h"
+#include "uidswap.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "buffer.h"
+
+/* import */
+extern ServerOptions options;
+extern Buffer loginmsg;
+
+static int auth1_process_password(Authctxt *, char *, size_t);
+static int auth1_process_rsa(Authctxt *, char *, size_t);
+static int auth1_process_rhosts_rsa(Authctxt *, char *, size_t);
+static int auth1_process_tis_challenge(Authctxt *, char *, size_t);
+static int auth1_process_tis_response(Authctxt *, char *, size_t);
+
+static char *client_user = NULL;    /* Used to fill in remote user for PAM */
+
+struct AuthMethod1 {
+       int type;
+       char *name;
+       int *enabled;
+       int (*method)(Authctxt *, char *, size_t);
+};
+
+const struct AuthMethod1 auth1_methods[] = {
+       {
+               SSH_CMSG_AUTH_PASSWORD, "password",
+               &options.password_authentication, auth1_process_password
+       },
+       {
+               SSH_CMSG_AUTH_RSA, "rsa",
+               &options.rsa_authentication, auth1_process_rsa
+       },
+       {
+               SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
+               &options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
+       },
+       {
+               SSH_CMSG_AUTH_TIS, "challenge-response",
+               &options.challenge_response_authentication,
+               auth1_process_tis_challenge
+       },
+       {
+               SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
+               &options.challenge_response_authentication,
+               auth1_process_tis_response
+       },
+       { -1, NULL, NULL, NULL}
+};
+
+static const struct AuthMethod1
+*lookup_authmethod1(int type)
+{
+       int i;
+
+       for (i = 0; auth1_methods[i].name != NULL; i++)
+               if (auth1_methods[i].type == type)
+                       return (&(auth1_methods[i]));
+
+       return (NULL);
+}
+
+static char *
+get_authname(int type)
+{
+       const struct AuthMethod1 *a;
+       static char buf[64];
+
+       if ((a = lookup_authmethod1(type)) != NULL)
+               return (a->name);
+       snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
+       return (buf);
+}
+
+/*ARGSUSED*/
+static int
+auth1_process_password(Authctxt *authctxt, char *info, size_t infolen)
+{
+       int authenticated = 0;
+       char *password;
+       u_int dlen;
+
+       /*
+        * Read user password.  It is in plain text, but was
+        * transmitted over the encrypted channel so it is
+        * not visible to an outside observer.
+        */
+       password = packet_get_string(&dlen);
+       packet_check_eom();
+
+       /* Try authentication with the password. */
+       authenticated = PRIVSEP(auth_password(authctxt, password));
+
+       memset(password, 0, dlen);
+       xfree(password);
+
+       return (authenticated);
+}
+
+/*ARGSUSED*/
+static int
+auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen)
+{
+       int authenticated = 0;
+       BIGNUM *n;
+
+       /* RSA authentication requested. */
+       if ((n = BN_new()) == NULL)
+               fatal("do_authloop: BN_new failed");
+       packet_get_bignum(n);
+       packet_check_eom();
+       authenticated = auth_rsa(authctxt, n);
+       BN_clear_free(n);
+
+       return (authenticated);
+}
+
+/*ARGSUSED*/
+static int
+auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
+{
+       int keybits, authenticated = 0;
+       u_int bits;
+       Key *client_host_key;
+       u_int ulen;
+
+       /*
+        * Get client user name.  Note that we just have to
+        * trust the client; root on the client machine can
+        * claim to be any user.
+        */
+       client_user = packet_get_cstring(&ulen);
+
+       /* Get the client host key. */
+       client_host_key = key_new(KEY_RSA1);
+       bits = packet_get_int();
+       packet_get_bignum(client_host_key->rsa->e);
+       packet_get_bignum(client_host_key->rsa->n);
+
+       keybits = BN_num_bits(client_host_key->rsa->n);
+       if (keybits < 0 || bits != (u_int)keybits) {
+               verbose("Warning: keysize mismatch for client_host_key: "
+                   "actual %d, announced %d",
+                   BN_num_bits(client_host_key->rsa->n), bits);
+       }
+       packet_check_eom();
+
+       authenticated = auth_rhosts_rsa(authctxt, client_user,
+           client_host_key);
+       key_free(client_host_key);
+
+       snprintf(info, infolen, " ruser %.100s", client_user);
+
+       return (authenticated);
+}
+
+/*ARGSUSED*/
+static int
+auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
+{
+       char *challenge;
+
+       if ((challenge = get_challenge(authctxt)) == NULL)
+               return (0);
+
+       debug("sending challenge '%s'", challenge);
+       packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
+       packet_put_cstring(challenge);
+       xfree(challenge);
+       packet_send();
+       packet_write_wait();
+
+       return (-1);
+}
+
+/*ARGSUSED*/
+static int
+auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
+{
+       int authenticated = 0;
+       char *response;
+       u_int dlen;
+
+       response = packet_get_string(&dlen);
+       packet_check_eom();
+       authenticated = verify_response(authctxt, response);
+       memset(response, 'r', dlen);
+       xfree(response);
+
+       return (authenticated);
+}
+
+/*
+ * read packets, try to authenticate the user and
+ * return only if authentication is successful
+ */
+static void
+do_authloop(Authctxt *authctxt)
+{
+       int authenticated = 0;
+       char info[1024];
+       int prev = 0, type = 0;
+       const struct AuthMethod1 *meth;
+
+       debug("Attempting authentication for %s%.100s.",
+           authctxt->valid ? "" : "invalid user ", authctxt->user);
+
+       /* If the user has no password, accept authentication immediately. */
+       if (options.permit_empty_passwd && options.password_authentication &&
+#ifdef KRB5
+           (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
+#endif
+           PRIVSEP(auth_password(authctxt, ""))) {
+#ifdef USE_PAM
+               if (options.use_pam && (PRIVSEP(do_pam_account())))
+#endif
+               {
+                       auth_log(authctxt, 1, "without authentication", "");
+                       return;
+               }
+       }
+
+       /* Indicate that authentication is needed. */
+       packet_start(SSH_SMSG_FAILURE);
+       packet_send();
+       packet_write_wait();
+
+       for (;;) {
+               /* default to fail */
+               authenticated = 0;
+
+               info[0] = '\0';
+
+               /* Get a packet from the client. */
+               prev = type;
+               type = packet_read();
+
+               /*
+                * If we started challenge-response authentication but the
+                * next packet is not a response to our challenge, release
+                * the resources allocated by get_challenge() (which would
+                * normally have been released by verify_response() had we
+                * received such a response)
+                */
+               if (prev == SSH_CMSG_AUTH_TIS &&
+                   type != SSH_CMSG_AUTH_TIS_RESPONSE)
+                       abandon_challenge_response(authctxt);
+
+               if (authctxt->failures >= options.max_authtries)
+                       goto skip;
+               if ((meth = lookup_authmethod1(type)) == NULL) {
+                       logit("Unknown message during authentication: "
+                           "type %d", type);
+                       goto skip;
+               }
+
+               if (!*(meth->enabled)) {
+                       verbose("%s authentication disabled.", meth->name);
+                       goto skip;
+               }
+
+               authenticated = meth->method(authctxt, info, sizeof(info));
+               if (authenticated == -1)
+                       continue; /* "postponed" */
+
+#ifdef BSD_AUTH
+               if (authctxt->as) {
+                       auth_close(authctxt->as);
+                       authctxt->as = NULL;
+               }
+#endif
+               if (!authctxt->valid && authenticated)
+                       fatal("INTERNAL ERROR: authenticated invalid user %s",
+                           authctxt->user);
+
+#ifdef _UNICOS
+               if (authenticated && cray_access_denied(authctxt->user)) {
+                       authenticated = 0;
+                       fatal("Access denied for user %s.",authctxt->user);
+               }
+#endif /* _UNICOS */
+
+#ifndef HAVE_CYGWIN
+               /* Special handling for root */
+               if (authenticated && authctxt->pw->pw_uid == 0 &&
+                   !auth_root_allowed(meth->name)) {
+                       authenticated = 0;
+# ifdef SSH_AUDIT_EVENTS
+                       PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
+# endif
+               }
+#endif
+
+#ifdef USE_PAM
+               if (options.use_pam && authenticated &&
+                   !PRIVSEP(do_pam_account())) {
+                       char *msg;
+                       size_t len;
+
+                       error("Access denied for user %s by PAM account "
+                           "configuration", authctxt->user);
+                       len = buffer_len(&loginmsg);
+                       buffer_append(&loginmsg, "\0", 1);
+                       msg = buffer_ptr(&loginmsg);
+                       /* strip trailing newlines */
+                       if (len > 0)
+                               while (len > 0 && msg[--len] == '\n')
+                                       msg[len] = '\0';
+                       else
+                               msg = "Access denied.";
+                       packet_disconnect("%s", msg);
+               }
+#endif
+
+ skip:
+               /* Log before sending the reply */
+               auth_log(authctxt, authenticated, get_authname(type), info);
+
+               if (client_user != NULL) {
+                       xfree(client_user);
+                       client_user = NULL;
+               }
+
+               if (authenticated)
+                       return;
+
+               if (++authctxt->failures >= options.max_authtries) {
+#ifdef SSH_AUDIT_EVENTS
+                       PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
+#endif
+                       packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+               }
+
+               packet_start(SSH_SMSG_FAILURE);
+               packet_send();
+               packet_write_wait();
+       }
+}
+
+/*
+ * Performs authentication of an incoming connection.  Session key has already
+ * been exchanged and encryption is enabled.
+ */
+void
+do_authentication(Authctxt *authctxt)
+{
+       u_int ulen;
+       char *user, *style = NULL;
+
+       /* Get the name of the user that we wish to log in as. */
+       packet_read_expect(SSH_CMSG_USER);
+
+       /* Get the user name. */
+       user = packet_get_cstring(&ulen);
+       packet_check_eom();
+
+       if ((style = strchr(user, ':')) != NULL)
+               *style++ = '\0';
+
+       authctxt->user = user;
+       authctxt->style = style;
+
+       /* Verify that the user is a valid user. */
+       if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
+               authctxt->valid = 1;
+       else {
+               debug("do_authentication: invalid user %s", user);
+               authctxt->pw = fakepw();
+       }
+
+       setproctitle("%s%s", authctxt->valid ? user : "unknown",
+           use_privsep ? " [net]" : "");
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               PRIVSEP(start_pam(authctxt));
+#endif
+
+       /*
+        * If we are not running as root, the user must have the same uid as
+        * the server.
+        */
+#ifndef HAVE_CYGWIN
+       if (!use_privsep && getuid() != 0 && authctxt->pw &&
+           authctxt->pw->pw_uid != getuid())
+               packet_disconnect("Cannot change user when server not running as root.");
+#endif
+
+       /*
+        * Loop until the user has been authenticated or the connection is
+        * closed, do_authloop() returns only if authentication is successful
+        */
+       do_authloop(authctxt);
+
+       /* The user has been authenticated and accepted. */
+       packet_start(SSH_SMSG_SUCCESS);
+       packet_send();
+       packet_write_wait();
+}
diff --git a/.pc/selinux-role.patch/auth2.c b/.pc/selinux-role.patch/auth2.c
new file mode 100644 (file)
index 0000000..f73ac18
--- /dev/null
@@ -0,0 +1,411 @@
+/* $OpenBSD: auth2.c,v 1.123 2011/03/10 02:52:57 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "atomicio.h"
+#include "xmalloc.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "compat.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "dispatch.h"
+#include "pathnames.h"
+#include "buffer.h"
+
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern u_int session_id2_len;
+extern Buffer loginmsg;
+
+/* methods */
+
+extern Authmethod method_none;
+extern Authmethod method_pubkey;
+extern Authmethod method_passwd;
+extern Authmethod method_kbdint;
+extern Authmethod method_hostbased;
+#ifdef GSSAPI
+extern Authmethod method_gsskeyex;
+extern Authmethod method_gssapi;
+#endif
+#ifdef JPAKE
+extern Authmethod method_jpake;
+#endif
+
+Authmethod *authmethods[] = {
+       &method_none,
+       &method_pubkey,
+#ifdef GSSAPI
+       &method_gsskeyex,
+       &method_gssapi,
+#endif
+#ifdef JPAKE
+       &method_jpake,
+#endif
+       &method_passwd,
+       &method_kbdint,
+       &method_hostbased,
+       NULL
+};
+
+/* protocol */
+
+static void input_service_request(int, u_int32_t, void *);
+static void input_userauth_request(int, u_int32_t, void *);
+
+/* helper */
+static Authmethod *authmethod_lookup(const char *);
+static char *authmethods_get(void);
+
+char *
+auth2_read_banner(void)
+{
+       struct stat st;
+       char *banner = NULL;
+       size_t len, n;
+       int fd;
+
+       if ((fd = open(options.banner, O_RDONLY)) == -1)
+               return (NULL);
+       if (fstat(fd, &st) == -1) {
+               close(fd);
+               return (NULL);
+       }
+       if (st.st_size > 1*1024*1024) {
+               close(fd);
+               return (NULL);
+       }
+
+       len = (size_t)st.st_size;               /* truncate */
+       banner = xmalloc(len + 1);
+       n = atomicio(read, fd, banner, len);
+       close(fd);
+
+       if (n != len) {
+               xfree(banner);
+               return (NULL);
+       }
+       banner[n] = '\0';
+
+       return (banner);
+}
+
+void
+userauth_send_banner(const char *msg)
+{
+       if (datafellows & SSH_BUG_BANNER)
+               return;
+
+       packet_start(SSH2_MSG_USERAUTH_BANNER);
+       packet_put_cstring(msg);
+       packet_put_cstring("");         /* language, unused */
+       packet_send();
+       debug("%s: sent", __func__);
+}
+
+static void
+userauth_banner(void)
+{
+       char *banner = NULL;
+
+       if (options.banner == NULL ||
+           strcasecmp(options.banner, "none") == 0 ||
+           (datafellows & SSH_BUG_BANNER) != 0)
+               return;
+
+       if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
+               goto done;
+       userauth_send_banner(banner);
+
+done:
+       if (banner)
+               xfree(banner);
+}
+
+/*
+ * loop until authctxt->success == TRUE
+ */
+void
+do_authentication2(Authctxt *authctxt)
+{
+       dispatch_init(&dispatch_protocol_error);
+       dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
+       dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
+}
+
+/*ARGSUSED*/
+static void
+input_service_request(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       u_int len;
+       int acceptit = 0;
+       char *service = packet_get_cstring(&len);
+       packet_check_eom();
+
+       if (authctxt == NULL)
+               fatal("input_service_request: no authctxt");
+
+       if (strcmp(service, "ssh-userauth") == 0) {
+               if (!authctxt->success) {
+                       acceptit = 1;
+                       /* now we can handle user-auth requests */
+                       dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
+               }
+       }
+       /* XXX all other service requests are denied */
+
+       if (acceptit) {
+               packet_start(SSH2_MSG_SERVICE_ACCEPT);
+               packet_put_cstring(service);
+               packet_send();
+               packet_write_wait();
+       } else {
+               debug("bad service request %s", service);
+               packet_disconnect("bad service request %s", service);
+       }
+       xfree(service);
+}
+
+/*ARGSUSED*/
+static void
+input_userauth_request(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Authmethod *m = NULL;
+       char *user, *service, *method, *style = NULL;
+       int authenticated = 0;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_request: no authctxt");
+
+       user = packet_get_cstring(NULL);
+       service = packet_get_cstring(NULL);
+       method = packet_get_cstring(NULL);
+       debug("userauth-request for user %s service %s method %s", user, service, method);
+       debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
+
+       if ((style = strchr(user, ':')) != NULL)
+               *style++ = 0;
+
+       if (authctxt->attempt++ == 0) {
+               /* setup auth context */
+               authctxt->pw = PRIVSEP(getpwnamallow(user));
+               authctxt->user = xstrdup(user);
+               if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
+                       authctxt->valid = 1;
+                       debug2("input_userauth_request: setting up authctxt for %s", user);
+               } else {
+                       logit("input_userauth_request: invalid user %s", user);
+                       authctxt->pw = fakepw();
+#ifdef SSH_AUDIT_EVENTS
+                       PRIVSEP(audit_event(SSH_INVALID_USER));
+#endif
+               }
+#ifdef USE_PAM
+               if (options.use_pam)
+                       PRIVSEP(start_pam(authctxt));
+#endif
+               setproctitle("%s%s", authctxt->valid ? user : "unknown",
+                   use_privsep ? " [net]" : "");
+               authctxt->service = xstrdup(service);
+               authctxt->style = style ? xstrdup(style) : NULL;
+               if (use_privsep)
+                       mm_inform_authserv(service, style);
+               userauth_banner();
+       } else if (strcmp(user, authctxt->user) != 0 ||
+           strcmp(service, authctxt->service) != 0) {
+               packet_disconnect("Change of username or service not allowed: "
+                   "(%s,%s) -> (%s,%s)",
+                   authctxt->user, authctxt->service, user, service);
+       }
+       /* reset state */
+       auth2_challenge_stop(authctxt);
+#ifdef JPAKE
+       auth2_jpake_stop(authctxt);
+#endif
+
+#ifdef GSSAPI
+       /* XXX move to auth2_gssapi_stop() */
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+#endif
+
+       authctxt->postponed = 0;
+       authctxt->server_caused_failure = 0;
+
+       /* try to authenticate user */
+       m = authmethod_lookup(method);
+       if (m != NULL && authctxt->failures < options.max_authtries) {
+               debug2("input_userauth_request: try method %s", method);
+               authenticated = m->userauth(authctxt);
+       }
+       userauth_finish(authctxt, authenticated, method);
+
+       xfree(service);
+       xfree(user);
+       xfree(method);
+}
+
+void
+userauth_finish(Authctxt *authctxt, int authenticated, char *method)
+{
+       char *methods;
+
+       if (!authctxt->valid && authenticated)
+               fatal("INTERNAL ERROR: authenticated invalid user %s",
+                   authctxt->user);
+
+       /* Special handling for root */
+       if (authenticated && authctxt->pw->pw_uid == 0 &&
+           !auth_root_allowed(method)) {
+               authenticated = 0;
+#ifdef SSH_AUDIT_EVENTS
+               PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
+#endif
+       }
+
+#ifdef USE_PAM
+       if (options.use_pam && authenticated) {
+               if (!PRIVSEP(do_pam_account())) {
+                       /* if PAM returned a message, send it to the user */
+                       if (buffer_len(&loginmsg) > 0) {
+                               buffer_append(&loginmsg, "\0", 1);
+                               userauth_send_banner(buffer_ptr(&loginmsg));
+                               packet_write_wait();
+                       }
+                       fatal("Access denied for user %s by PAM account "
+                           "configuration", authctxt->user);
+               }
+       }
+#endif
+
+#ifdef _UNICOS
+       if (authenticated && cray_access_denied(authctxt->user)) {
+               authenticated = 0;
+               fatal("Access denied for user %s.",authctxt->user);
+       }
+#endif /* _UNICOS */
+
+       /* Log before sending the reply */
+       auth_log(authctxt, authenticated, method, " ssh2");
+
+       if (authctxt->postponed)
+               return;
+
+       /* XXX todo: check if multiple auth methods are needed */
+       if (authenticated == 1) {
+               /* turn off userauth */
+               dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
+               packet_start(SSH2_MSG_USERAUTH_SUCCESS);
+               packet_send();
+               packet_write_wait();
+               /* now we can break out */
+               authctxt->success = 1;
+       } else {
+
+               /* Allow initial try of "none" auth without failure penalty */
+               if (!authctxt->server_caused_failure &&
+                   (authctxt->attempt > 1 || strcmp(method, "none") != 0))
+                       authctxt->failures++;
+               if (authctxt->failures >= options.max_authtries) {
+#ifdef SSH_AUDIT_EVENTS
+                       PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
+#endif
+                       packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+               }
+               methods = authmethods_get();
+               packet_start(SSH2_MSG_USERAUTH_FAILURE);
+               packet_put_cstring(methods);
+               packet_put_char(0);     /* XXX partial success, unused */
+               packet_send();
+               packet_write_wait();
+               xfree(methods);
+       }
+}
+
+static char *
+authmethods_get(void)
+{
+       Buffer b;
+       char *list;
+       int i;
+
+       buffer_init(&b);
+       for (i = 0; authmethods[i] != NULL; i++) {
+               if (strcmp(authmethods[i]->name, "none") == 0)
+                       continue;
+               if (authmethods[i]->enabled != NULL &&
+                   *(authmethods[i]->enabled) != 0) {
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       buffer_append(&b, authmethods[i]->name,
+                           strlen(authmethods[i]->name));
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       list = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       return list;
+}
+
+static Authmethod *
+authmethod_lookup(const char *name)
+{
+       int i;
+
+       if (name != NULL)
+               for (i = 0; authmethods[i] != NULL; i++)
+                       if (authmethods[i]->enabled != NULL &&
+                           *(authmethods[i]->enabled) != 0 &&
+                           strcmp(name, authmethods[i]->name) == 0)
+                               return authmethods[i];
+       debug2("Unrecognized authentication method name: %s",
+           name ? name : "NULL");
+       return NULL;
+}
+
diff --git a/.pc/selinux-role.patch/monitor.c b/.pc/selinux-role.patch/monitor.c
new file mode 100644 (file)
index 0000000..2d46b7b
--- /dev/null
@@ -0,0 +1,2414 @@
+/* $OpenBSD: monitor.c,v 1.115 2011/06/23 23:35:42 djm Exp $ */
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright 2002 Markus Friedl <markus@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include "openbsd-compat/sys-tree.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+# endif
+#endif
+
+#ifdef SKEY
+#include <skey.h>
+#endif
+
+#include <openssl/dh.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "atomicio.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "key.h"
+#include "buffer.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "cipher.h"
+#include "kex.h"
+#include "dh.h"
+#ifdef TARGET_OS_MAC   /* XXX Broken krb5 headers on Mac */
+#undef TARGET_OS_MAC
+#include "zlib.h"
+#define TARGET_OS_MAC 1
+#else
+#include "zlib.h"
+#endif
+#include "packet.h"
+#include "auth-options.h"
+#include "sshpty.h"
+#include "channels.h"
+#include "session.h"
+#include "sshlogin.h"
+#include "canohost.h"
+#include "log.h"
+#include "servconf.h"
+#include "monitor.h"
+#include "monitor_mm.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "monitor_fdpass.h"
+#include "misc.h"
+#include "compat.h"
+#include "ssh2.h"
+#include "jpake.h"
+#include "roaming.h"
+
+#ifdef GSSAPI
+static Gssctxt *gsscontext = NULL;
+#endif
+
+/* Imports */
+extern ServerOptions options;
+extern u_int utmp_len;
+extern Newkeys *current_keys[];
+extern z_stream incoming_stream;
+extern z_stream outgoing_stream;
+extern u_char session_id[];
+extern Buffer auth_debug;
+extern int auth_debug_init;
+extern Buffer loginmsg;
+
+/* State exported from the child */
+
+struct {
+       z_stream incoming;
+       z_stream outgoing;
+       u_char *keyin;
+       u_int keyinlen;
+       u_char *keyout;
+       u_int keyoutlen;
+       u_char *ivin;
+       u_int ivinlen;
+       u_char *ivout;
+       u_int ivoutlen;
+       u_char *ssh1key;
+       u_int ssh1keylen;
+       int ssh1cipher;
+       int ssh1protoflags;
+       u_char *input;
+       u_int ilen;
+       u_char *output;
+       u_int olen;
+       u_int64_t sent_bytes;
+       u_int64_t recv_bytes;
+} child_state;
+
+/* Functions on the monitor that answer unprivileged requests */
+
+int mm_answer_moduli(int, Buffer *);
+int mm_answer_sign(int, Buffer *);
+int mm_answer_pwnamallow(int, Buffer *);
+int mm_answer_auth2_read_banner(int, Buffer *);
+int mm_answer_authserv(int, Buffer *);
+int mm_answer_authpassword(int, Buffer *);
+int mm_answer_bsdauthquery(int, Buffer *);
+int mm_answer_bsdauthrespond(int, Buffer *);
+int mm_answer_skeyquery(int, Buffer *);
+int mm_answer_skeyrespond(int, Buffer *);
+int mm_answer_keyallowed(int, Buffer *);
+int mm_answer_keyverify(int, Buffer *);
+int mm_answer_pty(int, Buffer *);
+int mm_answer_pty_cleanup(int, Buffer *);
+int mm_answer_term(int, Buffer *);
+int mm_answer_rsa_keyallowed(int, Buffer *);
+int mm_answer_rsa_challenge(int, Buffer *);
+int mm_answer_rsa_response(int, Buffer *);
+int mm_answer_sesskey(int, Buffer *);
+int mm_answer_sessid(int, Buffer *);
+int mm_answer_jpake_get_pwdata(int, Buffer *);
+int mm_answer_jpake_step1(int, Buffer *);
+int mm_answer_jpake_step2(int, Buffer *);
+int mm_answer_jpake_key_confirm(int, Buffer *);
+int mm_answer_jpake_check_confirm(int, Buffer *);
+
+#ifdef USE_PAM
+int mm_answer_pam_start(int, Buffer *);
+int mm_answer_pam_account(int, Buffer *);
+int mm_answer_pam_init_ctx(int, Buffer *);
+int mm_answer_pam_query(int, Buffer *);
+int mm_answer_pam_respond(int, Buffer *);
+int mm_answer_pam_free_ctx(int, Buffer *);
+#endif
+
+#ifdef GSSAPI
+int mm_answer_gss_setup_ctx(int, Buffer *);
+int mm_answer_gss_accept_ctx(int, Buffer *);
+int mm_answer_gss_userok(int, Buffer *);
+int mm_answer_gss_checkmic(int, Buffer *);
+int mm_answer_gss_sign(int, Buffer *);
+int mm_answer_gss_updatecreds(int, Buffer *);
+#endif
+
+#ifdef SSH_AUDIT_EVENTS
+int mm_answer_audit_event(int, Buffer *);
+int mm_answer_audit_command(int, Buffer *);
+#endif
+
+static int monitor_read_log(struct monitor *);
+
+static Authctxt *authctxt;
+static BIGNUM *ssh1_challenge = NULL;  /* used for ssh1 rsa auth */
+
+/* local state for key verify */
+static u_char *key_blob = NULL;
+static u_int key_bloblen = 0;
+static int key_blobtype = MM_NOKEY;
+static char *hostbased_cuser = NULL;
+static char *hostbased_chost = NULL;
+static char *auth_method = "unknown";
+static u_int session_id2_len = 0;
+static u_char *session_id2 = NULL;
+static pid_t monitor_child_pid;
+
+struct mon_table {
+       enum monitor_reqtype type;
+       int flags;
+       int (*f)(int, Buffer *);
+};
+
+#define MON_ISAUTH     0x0004  /* Required for Authentication */
+#define MON_AUTHDECIDE 0x0008  /* Decides Authentication */
+#define MON_ONCE       0x0010  /* Disable after calling */
+#define MON_ALOG       0x0020  /* Log auth attempt without authenticating */
+
+#define MON_AUTH       (MON_ISAUTH|MON_AUTHDECIDE)
+
+#define MON_PERMIT     0x1000  /* Request is permitted */
+
+struct mon_table mon_dispatch_proto20[] = {
+    {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
+    {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
+    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+    {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+    {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
+    {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+#ifdef USE_PAM
+    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
+    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
+    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
+    {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
+    {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
+#endif
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+#endif
+#ifdef BSD_AUTH
+    {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
+    {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
+#endif
+#ifdef SKEY
+    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
+    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
+#endif
+    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
+    {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+#endif
+#ifdef JPAKE
+    {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
+    {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1},
+    {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2},
+    {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm},
+    {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_postauth20[] = {
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
+#endif
+    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
+    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
+    {MONITOR_REQ_PTY, 0, mm_answer_pty},
+    {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
+    {MONITOR_REQ_TERM, 0, mm_answer_term},
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_proto15[] = {
+    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+    {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
+    {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
+    {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+    {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed},
+    {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed},
+    {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
+    {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
+#ifdef BSD_AUTH
+    {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
+    {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
+#endif
+#ifdef SKEY
+    {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
+    {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
+#endif
+#ifdef USE_PAM
+    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
+    {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
+    {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
+    {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
+    {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
+#endif
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table mon_dispatch_postauth15[] = {
+    {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
+    {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
+    {MONITOR_REQ_TERM, 0, mm_answer_term},
+#ifdef SSH_AUDIT_EVENTS
+    {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+    {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
+#endif
+    {0, 0, NULL}
+};
+
+struct mon_table *mon_dispatch;
+
+/* Specifies if a certain message is allowed at the moment */
+
+static void
+monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
+{
+       while (ent->f != NULL) {
+               if (ent->type == type) {
+                       ent->flags &= ~MON_PERMIT;
+                       ent->flags |= permit ? MON_PERMIT : 0;
+                       return;
+               }
+               ent++;
+       }
+}
+
+static void
+monitor_permit_authentications(int permit)
+{
+       struct mon_table *ent = mon_dispatch;
+
+       while (ent->f != NULL) {
+               if (ent->flags & MON_AUTH) {
+                       ent->flags &= ~MON_PERMIT;
+                       ent->flags |= permit ? MON_PERMIT : 0;
+               }
+               ent++;
+       }
+}
+
+void
+monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
+{
+       struct mon_table *ent;
+       int authenticated = 0;
+
+       debug3("preauth child monitor started");
+
+       close(pmonitor->m_recvfd);
+       close(pmonitor->m_log_sendfd);
+       pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
+
+       authctxt = _authctxt;
+       memset(authctxt, 0, sizeof(*authctxt));
+
+       authctxt->loginmsg = &loginmsg;
+
+       if (compat20) {
+               mon_dispatch = mon_dispatch_proto20;
+
+               /* Permit requests for moduli and signatures */
+               monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+#ifdef GSSAPI
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+#endif
+       } else {
+               mon_dispatch = mon_dispatch_proto15;
+
+               monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
+       }
+
+       /* The first few requests do not require asynchronous access */
+       while (!authenticated) {
+               auth_method = "unknown";
+               authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
+               if (authenticated) {
+                       if (!(ent->flags & MON_AUTHDECIDE))
+                               fatal("%s: unexpected authentication from %d",
+                                   __func__, ent->type);
+                       if (authctxt->pw->pw_uid == 0 &&
+                           !auth_root_allowed(auth_method))
+                               authenticated = 0;
+#ifdef USE_PAM
+                       /* PAM needs to perform account checks after auth */
+                       if (options.use_pam && authenticated) {
+                               Buffer m;
+
+                               buffer_init(&m);
+                               mm_request_receive_expect(pmonitor->m_sendfd,
+                                   MONITOR_REQ_PAM_ACCOUNT, &m);
+                               authenticated = mm_answer_pam_account(pmonitor->m_sendfd, &m);
+                               buffer_free(&m);
+                       }
+#endif
+               }
+
+               if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
+                       auth_log(authctxt, authenticated, auth_method,
+                           compat20 ? " ssh2" : "");
+                       if (!authenticated)
+                               authctxt->failures++;
+               }
+#ifdef JPAKE
+               /* Cleanup JPAKE context after authentication */
+               if (ent->flags & MON_AUTHDECIDE) {
+                       if (authctxt->jpake_ctx != NULL) {
+                               jpake_free(authctxt->jpake_ctx);
+                               authctxt->jpake_ctx = NULL;
+                       }
+               }
+#endif
+       }
+
+       /* Drain any buffered messages from the child */
+       while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
+               ;
+
+       if (!authctxt->valid)
+               fatal("%s: authenticated invalid user", __func__);
+       if (strcmp(auth_method, "unknown") == 0)
+               fatal("%s: authentication method name unknown", __func__);
+
+       debug("%s: %s has been authenticated by privileged process",
+           __func__, authctxt->user);
+
+       mm_get_keystate(pmonitor);
+
+       close(pmonitor->m_sendfd);
+       close(pmonitor->m_log_recvfd);
+       pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
+}
+
+static void
+monitor_set_child_handler(pid_t pid)
+{
+       monitor_child_pid = pid;
+}
+
+static void
+monitor_child_handler(int sig)
+{
+       kill(monitor_child_pid, sig);
+}
+
+void
+monitor_child_postauth(struct monitor *pmonitor)
+{
+       close(pmonitor->m_recvfd);
+       pmonitor->m_recvfd = -1;
+
+       monitor_set_child_handler(pmonitor->m_pid);
+       signal(SIGHUP, &monitor_child_handler);
+       signal(SIGTERM, &monitor_child_handler);
+       signal(SIGINT, &monitor_child_handler);
+
+       if (compat20) {
+               mon_dispatch = mon_dispatch_postauth20;
+
+               /* Permit requests for moduli and signatures */
+               monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+#ifdef GSSAPI
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+#endif         
+       } else {
+               mon_dispatch = mon_dispatch_postauth15;
+               monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+       }
+       if (!no_pty_flag) {
+               monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
+       }
+
+       for (;;)
+               monitor_read(pmonitor, mon_dispatch, NULL);
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
+}
+
+void
+monitor_sync(struct monitor *pmonitor)
+{
+       if (options.compression) {
+               /* The member allocation is not visible, so sync it */
+               mm_share_sync(&pmonitor->m_zlib, &pmonitor->m_zback);
+       }
+}
+
+static int
+monitor_read_log(struct monitor *pmonitor)
+{
+       Buffer logmsg;
+       u_int len, level;
+       char *msg;
+
+       buffer_init(&logmsg);
+
+       /* Read length */
+       buffer_append_space(&logmsg, 4);
+       if (atomicio(read, pmonitor->m_log_recvfd,
+           buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
+               if (errno == EPIPE) {
+                       debug("%s: child log fd closed", __func__);
+                       close(pmonitor->m_log_recvfd);
+                       pmonitor->m_log_recvfd = -1;
+                       return -1;
+               }
+               fatal("%s: log fd read: %s", __func__, strerror(errno));
+       }
+       len = buffer_get_int(&logmsg);
+       if (len <= 4 || len > 8192)
+               fatal("%s: invalid log message length %u", __func__, len);
+
+       /* Read severity, message */
+       buffer_clear(&logmsg);
+       buffer_append_space(&logmsg, len);
+       if (atomicio(read, pmonitor->m_log_recvfd,
+           buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg))
+               fatal("%s: log fd read: %s", __func__, strerror(errno));
+
+       /* Log it */
+       level = buffer_get_int(&logmsg);
+       msg = buffer_get_string(&logmsg, NULL);
+       if (log_level_name(level) == NULL)
+               fatal("%s: invalid log level %u (corrupted message?)",
+                   __func__, level);
+       do_log2(level, "%s [preauth]", msg);
+
+       buffer_free(&logmsg);
+       xfree(msg);
+
+       return 0;
+}
+
+int
+monitor_read(struct monitor *pmonitor, struct mon_table *ent,
+    struct mon_table **pent)
+{
+       Buffer m;
+       int ret;
+       u_char type;
+       struct pollfd pfd[2];
+
+       for (;;) {
+               bzero(&pfd, sizeof(pfd));
+               pfd[0].fd = pmonitor->m_sendfd;
+               pfd[0].events = POLLIN;
+               pfd[1].fd = pmonitor->m_log_recvfd;
+               pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN;
+               if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) {
+                       if (errno == EINTR || errno == EAGAIN)
+                               continue;
+                       fatal("%s: poll: %s", __func__, strerror(errno));
+               }
+               if (pfd[1].revents) {
+                       /*
+                        * Drain all log messages before processing next
+                        * monitor request.
+                        */
+                       monitor_read_log(pmonitor);
+                       continue;
+               }
+               if (pfd[0].revents)
+                       break;  /* Continues below */
+       }
+
+       buffer_init(&m);
+
+       mm_request_receive(pmonitor->m_sendfd, &m);
+       type = buffer_get_char(&m);
+
+       debug3("%s: checking request %d", __func__, type);
+
+       while (ent->f != NULL) {
+               if (ent->type == type)
+                       break;
+               ent++;
+       }
+
+       if (ent->f != NULL) {
+               if (!(ent->flags & MON_PERMIT))
+                       fatal("%s: unpermitted request %d", __func__,
+                           type);
+               ret = (*ent->f)(pmonitor->m_sendfd, &m);
+               buffer_free(&m);
+
+               /* The child may use this request only once, disable it */
+               if (ent->flags & MON_ONCE) {
+                       debug2("%s: %d used once, disabling now", __func__,
+                           type);
+                       ent->flags &= ~MON_PERMIT;
+               }
+
+               if (pent != NULL)
+                       *pent = ent;
+
+               return ret;
+       }
+
+       fatal("%s: unsupported request: %d", __func__, type);
+
+       /* NOTREACHED */
+       return (-1);
+}
+
+/* allowed key state */
+static int
+monitor_allowed_key(u_char *blob, u_int bloblen)
+{
+       /* make sure key is allowed */
+       if (key_blob == NULL || key_bloblen != bloblen ||
+           timingsafe_bcmp(key_blob, blob, key_bloblen))
+               return (0);
+       return (1);
+}
+
+static void
+monitor_reset_key_state(void)
+{
+       /* reset state */
+       if (key_blob != NULL)
+               xfree(key_blob);
+       if (hostbased_cuser != NULL)
+               xfree(hostbased_cuser);
+       if (hostbased_chost != NULL)
+               xfree(hostbased_chost);
+       key_blob = NULL;
+       key_bloblen = 0;
+       key_blobtype = MM_NOKEY;
+       hostbased_cuser = NULL;
+       hostbased_chost = NULL;
+}
+
+int
+mm_answer_moduli(int sock, Buffer *m)
+{
+       DH *dh;
+       int min, want, max;
+
+       min = buffer_get_int(m);
+       want = buffer_get_int(m);
+       max = buffer_get_int(m);
+
+       debug3("%s: got parameters: %d %d %d",
+           __func__, min, want, max);
+       /* We need to check here, too, in case the child got corrupted */
+       if (max < min || want < min || max < want)
+               fatal("%s: bad parameters: %d %d %d",
+                   __func__, min, want, max);
+
+       buffer_clear(m);
+
+       dh = choose_dh(min, want, max);
+       if (dh == NULL) {
+               buffer_put_char(m, 0);
+               return (0);
+       } else {
+               /* Send first bignum */
+               buffer_put_char(m, 1);
+               buffer_put_bignum2(m, dh->p);
+               buffer_put_bignum2(m, dh->g);
+
+               DH_free(dh);
+       }
+       mm_request_send(sock, MONITOR_ANS_MODULI, m);
+       return (0);
+}
+
+int
+mm_answer_sign(int sock, Buffer *m)
+{
+       Key *key;
+       u_char *p;
+       u_char *signature;
+       u_int siglen, datlen;
+       int keyid;
+
+       debug3("%s", __func__);
+
+       keyid = buffer_get_int(m);
+       p = buffer_get_string(m, &datlen);
+
+       /*
+        * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
+        * SHA384 (48 bytes) and SHA512 (64 bytes).
+        */
+       if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64)
+               fatal("%s: data length incorrect: %u", __func__, datlen);
+
+       /* save session id, it will be passed on the first call */
+       if (session_id2_len == 0) {
+               session_id2_len = datlen;
+               session_id2 = xmalloc(session_id2_len);
+               memcpy(session_id2, p, session_id2_len);
+       }
+
+       if ((key = get_hostkey_by_index(keyid)) == NULL)
+               fatal("%s: no hostkey from index %d", __func__, keyid);
+       if (key_sign(key, &signature, &siglen, p, datlen) < 0)
+               fatal("%s: key_sign failed", __func__);
+
+       debug3("%s: signature %p(%u)", __func__, signature, siglen);
+
+       buffer_clear(m);
+       buffer_put_string(m, signature, siglen);
+
+       xfree(p);
+       xfree(signature);
+
+       mm_request_send(sock, MONITOR_ANS_SIGN, m);
+
+       /* Turn on permissions for getpwnam */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+
+       return (0);
+}
+
+/* Retrieves the password entry and also checks if the user is permitted */
+
+int
+mm_answer_pwnamallow(int sock, Buffer *m)
+{
+       char *username;
+       struct passwd *pwent;
+       int allowed = 0;
+       u_int i;
+
+       debug3("%s", __func__);
+
+       if (authctxt->attempt++ != 0)
+               fatal("%s: multiple attempts for getpwnam", __func__);
+
+       username = buffer_get_string(m, NULL);
+
+       pwent = getpwnamallow(username);
+
+       authctxt->user = xstrdup(username);
+       setproctitle("%s [priv]", pwent ? username : "unknown");
+       xfree(username);
+
+       buffer_clear(m);
+
+       if (pwent == NULL) {
+               buffer_put_char(m, 0);
+               authctxt->pw = fakepw();
+               goto out;
+       }
+
+       allowed = 1;
+       authctxt->pw = pwent;
+       authctxt->valid = 1;
+
+       buffer_put_char(m, 1);
+       buffer_put_string(m, pwent, sizeof(struct passwd));
+       buffer_put_cstring(m, pwent->pw_name);
+       buffer_put_cstring(m, "*");
+       buffer_put_cstring(m, pwent->pw_gecos);
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+       buffer_put_cstring(m, pwent->pw_class);
+#endif
+       buffer_put_cstring(m, pwent->pw_dir);
+       buffer_put_cstring(m, pwent->pw_shell);
+
+ out:
+       buffer_put_string(m, &options, sizeof(options));
+
+#define M_CP_STROPT(x) do { \
+               if (options.x != NULL) \
+                       buffer_put_cstring(m, options.x); \
+       } while (0)
+#define M_CP_STRARRAYOPT(x, nx) do { \
+               for (i = 0; i < options.nx; i++) \
+                       buffer_put_cstring(m, options.x[i]); \
+       } while (0)
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+       
+       debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
+       mm_request_send(sock, MONITOR_ANS_PWNAM, m);
+
+       /* For SSHv1 allow authentication now */
+       if (!compat20)
+               monitor_permit_authentications(1);
+       else {
+               /* Allow service/style information on the auth context */
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
+       }
+#ifdef USE_PAM
+       if (options.use_pam)
+               monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
+#endif
+
+       return (0);
+}
+
+int mm_answer_auth2_read_banner(int sock, Buffer *m)
+{
+       char *banner;
+
+       buffer_clear(m);
+       banner = auth2_read_banner();
+       buffer_put_cstring(m, banner != NULL ? banner : "");
+       mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
+
+       if (banner != NULL)
+               xfree(banner);
+
+       return (0);
+}
+
+int
+mm_answer_authserv(int sock, Buffer *m)
+{
+       monitor_permit_authentications(1);
+
+       authctxt->service = buffer_get_string(m, NULL);
+       authctxt->style = buffer_get_string(m, NULL);
+       debug3("%s: service=%s, style=%s",
+           __func__, authctxt->service, authctxt->style);
+
+       if (strlen(authctxt->style) == 0) {
+               xfree(authctxt->style);
+               authctxt->style = NULL;
+       }
+
+       return (0);
+}
+
+int
+mm_answer_authpassword(int sock, Buffer *m)
+{
+       static int call_count;
+       char *passwd;
+       int authenticated;
+       u_int plen;
+
+       passwd = buffer_get_string(m, &plen);
+       /* Only authenticate if the context is valid */
+       authenticated = options.password_authentication &&
+           auth_password(authctxt, passwd);
+       memset(passwd, 0, strlen(passwd));
+       xfree(passwd);
+
+       buffer_clear(m);
+       buffer_put_int(m, authenticated);
+
+       debug3("%s: sending result %d", __func__, authenticated);
+       mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
+
+       call_count++;
+       if (plen == 0 && call_count == 1)
+               auth_method = "none";
+       else
+               auth_method = "password";
+
+       /* Causes monitor loop to terminate if authenticated */
+       return (authenticated);
+}
+
+#ifdef BSD_AUTH
+int
+mm_answer_bsdauthquery(int sock, Buffer *m)
+{
+       char *name, *infotxt;
+       u_int numprompts;
+       u_int *echo_on;
+       char **prompts;
+       u_int success;
+
+       success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
+           &prompts, &echo_on) < 0 ? 0 : 1;
+
+       buffer_clear(m);
+       buffer_put_int(m, success);
+       if (success)
+               buffer_put_cstring(m, prompts[0]);
+
+       debug3("%s: sending challenge success: %u", __func__, success);
+       mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
+
+       if (success) {
+               xfree(name);
+               xfree(infotxt);
+               xfree(prompts);
+               xfree(echo_on);
+       }
+
+       return (0);
+}
+
+int
+mm_answer_bsdauthrespond(int sock, Buffer *m)
+{
+       char *response;
+       int authok;
+
+       if (authctxt->as == 0)
+               fatal("%s: no bsd auth session", __func__);
+
+       response = buffer_get_string(m, NULL);
+       authok = options.challenge_response_authentication &&
+           auth_userresponse(authctxt->as, response, 0);
+       authctxt->as = NULL;
+       debug3("%s: <%s> = <%d>", __func__, response, authok);
+       xfree(response);
+
+       buffer_clear(m);
+       buffer_put_int(m, authok);
+
+       debug3("%s: sending authenticated: %d", __func__, authok);
+       mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
+
+       auth_method = "bsdauth";
+
+       return (authok != 0);
+}
+#endif
+
+#ifdef SKEY
+int
+mm_answer_skeyquery(int sock, Buffer *m)
+{
+       struct skey skey;
+       char challenge[1024];
+       u_int success;
+
+       success = _compat_skeychallenge(&skey, authctxt->user, challenge,
+           sizeof(challenge)) < 0 ? 0 : 1;
+
+       buffer_clear(m);
+       buffer_put_int(m, success);
+       if (success)
+               buffer_put_cstring(m, challenge);
+
+       debug3("%s: sending challenge success: %u", __func__, success);
+       mm_request_send(sock, MONITOR_ANS_SKEYQUERY, m);
+
+       return (0);
+}
+
+int
+mm_answer_skeyrespond(int sock, Buffer *m)
+{
+       char *response;
+       int authok;
+
+       response = buffer_get_string(m, NULL);
+
+       authok = (options.challenge_response_authentication &&
+           authctxt->valid &&
+           skey_haskey(authctxt->pw->pw_name) == 0 &&
+           skey_passcheck(authctxt->pw->pw_name, response) != -1);
+
+       xfree(response);
+
+       buffer_clear(m);
+       buffer_put_int(m, authok);
+
+       debug3("%s: sending authenticated: %d", __func__, authok);
+       mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m);
+
+       auth_method = "skey";
+
+       return (authok != 0);
+}
+#endif
+
+#ifdef USE_PAM
+int
+mm_answer_pam_start(int sock, Buffer *m)
+{
+       if (!options.use_pam)
+               fatal("UsePAM not set, but ended up in %s anyway", __func__);
+
+       start_pam(authctxt);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1);
+
+       return (0);
+}
+
+int
+mm_answer_pam_account(int sock, Buffer *m)
+{
+       u_int ret;
+
+       if (!options.use_pam)
+               fatal("UsePAM not set, but ended up in %s anyway", __func__);
+
+       ret = do_pam_account();
+
+       buffer_put_int(m, ret);
+       buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
+
+       mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m);
+
+       return (ret);
+}
+
+static void *sshpam_ctxt, *sshpam_authok;
+extern KbdintDevice sshpam_device;
+
+int
+mm_answer_pam_init_ctx(int sock, Buffer *m)
+{
+
+       debug3("%s", __func__);
+       authctxt->user = buffer_get_string(m, NULL);
+       sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
+       sshpam_authok = NULL;
+       buffer_clear(m);
+       if (sshpam_ctxt != NULL) {
+               monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1);
+               buffer_put_int(m, 1);
+       } else {
+               buffer_put_int(m, 0);
+       }
+       mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
+       return (0);
+}
+
+int
+mm_answer_pam_query(int sock, Buffer *m)
+{
+       char *name = NULL, *info = NULL, **prompts = NULL;
+       u_int i, num = 0, *echo_on = 0;
+       int ret;
+
+       debug3("%s", __func__);
+       sshpam_authok = NULL;
+       ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on);
+       if (ret == 0 && num == 0)
+               sshpam_authok = sshpam_ctxt;
+       if (num > 1 || name == NULL || info == NULL)
+               ret = -1;
+       buffer_clear(m);
+       buffer_put_int(m, ret);
+       buffer_put_cstring(m, name);
+       xfree(name);
+       buffer_put_cstring(m, info);
+       xfree(info);
+       buffer_put_int(m, num);
+       for (i = 0; i < num; ++i) {
+               buffer_put_cstring(m, prompts[i]);
+               xfree(prompts[i]);
+               buffer_put_int(m, echo_on[i]);
+       }
+       if (prompts != NULL)
+               xfree(prompts);
+       if (echo_on != NULL)
+               xfree(echo_on);
+       auth_method = "keyboard-interactive/pam";
+       mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
+       return (0);
+}
+
+int
+mm_answer_pam_respond(int sock, Buffer *m)
+{
+       char **resp;
+       u_int i, num;
+       int ret;
+
+       debug3("%s", __func__);
+       sshpam_authok = NULL;
+       num = buffer_get_int(m);
+       if (num > 0) {
+               resp = xcalloc(num, sizeof(char *));
+               for (i = 0; i < num; ++i)
+                       resp[i] = buffer_get_string(m, NULL);
+               ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
+               for (i = 0; i < num; ++i)
+                       xfree(resp[i]);
+               xfree(resp);
+       } else {
+               ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
+       }
+       buffer_clear(m);
+       buffer_put_int(m, ret);
+       mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
+       auth_method = "keyboard-interactive/pam";
+       if (ret == 0)
+               sshpam_authok = sshpam_ctxt;
+       return (0);
+}
+
+int
+mm_answer_pam_free_ctx(int sock, Buffer *m)
+{
+
+       debug3("%s", __func__);
+       (sshpam_device.free_ctx)(sshpam_ctxt);
+       buffer_clear(m);
+       mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
+       auth_method = "keyboard-interactive/pam";
+       return (sshpam_authok == sshpam_ctxt);
+}
+#endif
+
+int
+mm_answer_keyallowed(int sock, Buffer *m)
+{
+       Key *key;
+       char *cuser, *chost;
+       u_char *blob;
+       u_int bloblen;
+       enum mm_keytype type = 0;
+       int allowed = 0;
+
+       debug3("%s entering", __func__);
+
+       type = buffer_get_int(m);
+       cuser = buffer_get_string(m, NULL);
+       chost = buffer_get_string(m, NULL);
+       blob = buffer_get_string(m, &bloblen);
+
+       key = key_from_blob(blob, bloblen);
+
+       if ((compat20 && type == MM_RSAHOSTKEY) ||
+           (!compat20 && type != MM_RSAHOSTKEY))
+               fatal("%s: key type and protocol mismatch", __func__);
+
+       debug3("%s: key_from_blob: %p", __func__, key);
+
+       if (key != NULL && authctxt->valid) {
+               switch (type) {
+               case MM_USERKEY:
+                       allowed = options.pubkey_authentication &&
+                           user_key_allowed(authctxt->pw, key);
+                       auth_method = "publickey";
+                       if (options.pubkey_authentication && allowed != 1)
+                               auth_clear_options();
+                       break;
+               case MM_HOSTKEY:
+                       allowed = options.hostbased_authentication &&
+                           hostbased_key_allowed(authctxt->pw,
+                           cuser, chost, key);
+                       auth_method = "hostbased";
+                       break;
+               case MM_RSAHOSTKEY:
+                       key->type = KEY_RSA1; /* XXX */
+                       allowed = options.rhosts_rsa_authentication &&
+                           auth_rhosts_rsa_key_allowed(authctxt->pw,
+                           cuser, chost, key);
+                       if (options.rhosts_rsa_authentication && allowed != 1)
+                               auth_clear_options();
+                       auth_method = "rsa";
+                       break;
+               default:
+                       fatal("%s: unknown key type %d", __func__, type);
+                       break;
+               }
+       }
+       if (key != NULL)
+               key_free(key);
+
+       /* clear temporarily storage (used by verify) */
+       monitor_reset_key_state();
+
+       if (allowed) {
+               /* Save temporarily for comparison in verify */
+               key_blob = blob;
+               key_bloblen = bloblen;
+               key_blobtype = type;
+               hostbased_cuser = cuser;
+               hostbased_chost = chost;
+       } else {
+               /* Log failed attempt */
+               auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
+               xfree(blob);
+               xfree(cuser);
+               xfree(chost);
+       }
+
+       debug3("%s: key %p is %s",
+           __func__, key, allowed ? "allowed" : "not allowed");
+
+       buffer_clear(m);
+       buffer_put_int(m, allowed);
+       buffer_put_int(m, forced_command != NULL);
+
+       mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
+
+       if (type == MM_RSAHOSTKEY)
+               monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
+
+       return (0);
+}
+
+static int
+monitor_valid_userblob(u_char *data, u_int datalen)
+{
+       Buffer b;
+       char *p;
+       u_int len;
+       int fail = 0;
+
+       buffer_init(&b);
+       buffer_append(&b, data, datalen);
+
+       if (datafellows & SSH_OLD_SESSIONID) {
+               p = buffer_ptr(&b);
+               len = buffer_len(&b);
+               if ((session_id2 == NULL) ||
+                   (len < session_id2_len) ||
+                   (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
+                       fail++;
+               buffer_consume(&b, session_id2_len);
+       } else {
+               p = buffer_get_string(&b, &len);
+               if ((session_id2 == NULL) ||
+                   (len != session_id2_len) ||
+                   (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
+                       fail++;
+               xfree(p);
+       }
+       if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+               fail++;
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(authctxt->user, p) != 0) {
+               logit("wrong user name passed to monitor: expected %s != %.100s",
+                   authctxt->user, p);
+               fail++;
+       }
+       xfree(p);
+       buffer_skip_string(&b);
+       if (datafellows & SSH_BUG_PKAUTH) {
+               if (!buffer_get_char(&b))
+                       fail++;
+       } else {
+               p = buffer_get_string(&b, NULL);
+               if (strcmp("publickey", p) != 0)
+                       fail++;
+               xfree(p);
+               if (!buffer_get_char(&b))
+                       fail++;
+               buffer_skip_string(&b);
+       }
+       buffer_skip_string(&b);
+       if (buffer_len(&b) != 0)
+               fail++;
+       buffer_free(&b);
+       return (fail == 0);
+}
+
+static int
+monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
+    char *chost)
+{
+       Buffer b;
+       char *p;
+       u_int len;
+       int fail = 0;
+
+       buffer_init(&b);
+       buffer_append(&b, data, datalen);
+
+       p = buffer_get_string(&b, &len);
+       if ((session_id2 == NULL) ||
+           (len != session_id2_len) ||
+           (timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
+               fail++;
+       xfree(p);
+
+       if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+               fail++;
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(authctxt->user, p) != 0) {
+               logit("wrong user name passed to monitor: expected %s != %.100s",
+                   authctxt->user, p);
+               fail++;
+       }
+       xfree(p);
+       buffer_skip_string(&b); /* service */
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(p, "hostbased") != 0)
+               fail++;
+       xfree(p);
+       buffer_skip_string(&b); /* pkalg */
+       buffer_skip_string(&b); /* pkblob */
+
+       /* verify client host, strip trailing dot if necessary */
+       p = buffer_get_string(&b, NULL);
+       if (((len = strlen(p)) > 0) && p[len - 1] == '.')
+               p[len - 1] = '\0';
+       if (strcmp(p, chost) != 0)
+               fail++;
+       xfree(p);
+
+       /* verify client user */
+       p = buffer_get_string(&b, NULL);
+       if (strcmp(p, cuser) != 0)
+               fail++;
+       xfree(p);
+
+       if (buffer_len(&b) != 0)
+               fail++;
+       buffer_free(&b);
+       return (fail == 0);
+}
+
+int
+mm_answer_keyverify(int sock, Buffer *m)
+{
+       Key *key;
+       u_char *signature, *data, *blob;
+       u_int signaturelen, datalen, bloblen;
+       int verified = 0;
+       int valid_data = 0;
+
+       blob = buffer_get_string(m, &bloblen);
+       signature = buffer_get_string(m, &signaturelen);
+       data = buffer_get_string(m, &datalen);
+
+       if (hostbased_cuser == NULL || hostbased_chost == NULL ||
+         !monitor_allowed_key(blob, bloblen))
+               fatal("%s: bad key, not previously allowed", __func__);
+
+       key = key_from_blob(blob, bloblen);
+       if (key == NULL)
+               fatal("%s: bad public key blob", __func__);
+
+       switch (key_blobtype) {
+       case MM_USERKEY:
+               valid_data = monitor_valid_userblob(data, datalen);
+               break;
+       case MM_HOSTKEY:
+               valid_data = monitor_valid_hostbasedblob(data, datalen,
+                   hostbased_cuser, hostbased_chost);
+               break;
+       default:
+               valid_data = 0;
+               break;
+       }
+       if (!valid_data)
+               fatal("%s: bad signature data blob", __func__);
+
+       verified = key_verify(key, signature, signaturelen, data, datalen);
+       debug3("%s: key %p signature %s",
+           __func__, key, (verified == 1) ? "verified" : "unverified");
+
+       key_free(key);
+       xfree(blob);
+       xfree(signature);
+       xfree(data);
+
+       auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
+
+       monitor_reset_key_state();
+
+       buffer_clear(m);
+       buffer_put_int(m, verified);
+       mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
+
+       return (verified == 1);
+}
+
+static void
+mm_record_login(Session *s, struct passwd *pw)
+{
+       socklen_t fromlen;
+       struct sockaddr_storage from;
+
+       /*
+        * Get IP address of client. If the connection is not a socket, let
+        * the address be 0.0.0.0.
+        */
+       memset(&from, 0, sizeof(from));
+       fromlen = sizeof(from);
+       if (packet_connection_is_on_socket()) {
+               if (getpeername(packet_get_connection_in(),
+                   (struct sockaddr *)&from, &fromlen) < 0) {
+                       debug("getpeername: %.100s", strerror(errno));
+                       cleanup_exit(255);
+               }
+       }
+       /* Record that there was a login on that tty from the remote host. */
+       record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
+           get_remote_name_or_ip(utmp_len, options.use_dns),
+           (struct sockaddr *)&from, fromlen);
+}
+
+static void
+mm_session_close(Session *s)
+{
+       debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
+       if (s->ttyfd != -1) {
+               debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
+               session_pty_cleanup2(s);
+       }
+       session_unused(s->self);
+}
+
+int
+mm_answer_pty(int sock, Buffer *m)
+{
+       extern struct monitor *pmonitor;
+       Session *s;
+       int res, fd0;
+
+       debug3("%s entering", __func__);
+
+       buffer_clear(m);
+       s = session_new();
+       if (s == NULL)
+               goto error;
+       s->authctxt = authctxt;
+       s->pw = authctxt->pw;
+       s->pid = pmonitor->m_pid;
+       res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
+       if (res == 0)
+               goto error;
+       pty_setowner(authctxt->pw, s->tty);
+
+       buffer_put_int(m, 1);
+       buffer_put_cstring(m, s->tty);
+
+       /* We need to trick ttyslot */
+       if (dup2(s->ttyfd, 0) == -1)
+               fatal("%s: dup2", __func__);
+
+       mm_record_login(s, authctxt->pw);
+
+       /* Now we can close the file descriptor again */
+       close(0);
+
+       /* send messages generated by record_login */
+       buffer_put_string(m, buffer_ptr(&loginmsg), buffer_len(&loginmsg));
+       buffer_clear(&loginmsg);
+
+       mm_request_send(sock, MONITOR_ANS_PTY, m);
+
+       if (mm_send_fd(sock, s->ptyfd) == -1 ||
+           mm_send_fd(sock, s->ttyfd) == -1)
+               fatal("%s: send fds failed", __func__);
+
+       /* make sure nothing uses fd 0 */
+       if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
+               fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
+       if (fd0 != 0)
+               error("%s: fd0 %d != 0", __func__, fd0);
+
+       /* slave is not needed */
+       close(s->ttyfd);
+       s->ttyfd = s->ptyfd;
+       /* no need to dup() because nobody closes ptyfd */
+       s->ptymaster = s->ptyfd;
+
+       debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd);
+
+       return (0);
+
+ error:
+       if (s != NULL)
+               mm_session_close(s);
+       buffer_put_int(m, 0);
+       mm_request_send(sock, MONITOR_ANS_PTY, m);
+       return (0);
+}
+
+int
+mm_answer_pty_cleanup(int sock, Buffer *m)
+{
+       Session *s;
+       char *tty;
+
+       debug3("%s entering", __func__);
+
+       tty = buffer_get_string(m, NULL);
+       if ((s = session_by_tty(tty)) != NULL)
+               mm_session_close(s);
+       buffer_clear(m);
+       xfree(tty);
+       return (0);
+}
+
+int
+mm_answer_sesskey(int sock, Buffer *m)
+{
+       BIGNUM *p;
+       int rsafail;
+
+       /* Turn off permissions */
+       monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0);
+
+       if ((p = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       buffer_get_bignum2(m, p);
+
+       rsafail = ssh1_session_key(p);
+
+       buffer_clear(m);
+       buffer_put_int(m, rsafail);
+       buffer_put_bignum2(m, p);
+
+       BN_clear_free(p);
+
+       mm_request_send(sock, MONITOR_ANS_SESSKEY, m);
+
+       /* Turn on permissions for sessid passing */
+       monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
+
+       return (0);
+}
+
+int
+mm_answer_sessid(int sock, Buffer *m)
+{
+       int i;
+
+       debug3("%s entering", __func__);
+
+       if (buffer_len(m) != 16)
+               fatal("%s: bad ssh1 session id", __func__);
+       for (i = 0; i < 16; i++)
+               session_id[i] = buffer_get_char(m);
+
+       /* Turn on permissions for getpwnam */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+
+       return (0);
+}
+
+int
+mm_answer_rsa_keyallowed(int sock, Buffer *m)
+{
+       BIGNUM *client_n;
+       Key *key = NULL;
+       u_char *blob = NULL;
+       u_int blen = 0;
+       int allowed = 0;
+
+       debug3("%s entering", __func__);
+
+       auth_method = "rsa";
+       if (options.rsa_authentication && authctxt->valid) {
+               if ((client_n = BN_new()) == NULL)
+                       fatal("%s: BN_new", __func__);
+               buffer_get_bignum2(m, client_n);
+               allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
+               BN_clear_free(client_n);
+       }
+       buffer_clear(m);
+       buffer_put_int(m, allowed);
+       buffer_put_int(m, forced_command != NULL);
+
+       /* clear temporarily storage (used by generate challenge) */
+       monitor_reset_key_state();
+
+       if (allowed && key != NULL) {
+               key->type = KEY_RSA;    /* cheat for key_to_blob */
+               if (key_to_blob(key, &blob, &blen) == 0)
+                       fatal("%s: key_to_blob failed", __func__);
+               buffer_put_string(m, blob, blen);
+
+               /* Save temporarily for comparison in verify */
+               key_blob = blob;
+               key_bloblen = blen;
+               key_blobtype = MM_RSAUSERKEY;
+       }
+       if (key != NULL)
+               key_free(key);
+
+       mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
+       monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
+       return (0);
+}
+
+int
+mm_answer_rsa_challenge(int sock, Buffer *m)
+{
+       Key *key = NULL;
+       u_char *blob;
+       u_int blen;
+
+       debug3("%s entering", __func__);
+
+       if (!authctxt->valid)
+               fatal("%s: authctxt not valid", __func__);
+       blob = buffer_get_string(m, &blen);
+       if (!monitor_allowed_key(blob, blen))
+               fatal("%s: bad key, not previously allowed", __func__);
+       if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
+               fatal("%s: key type mismatch", __func__);
+       if ((key = key_from_blob(blob, blen)) == NULL)
+               fatal("%s: received bad key", __func__);
+       if (key->type != KEY_RSA)
+               fatal("%s: received bad key type %d", __func__, key->type);
+       key->type = KEY_RSA1;
+       if (ssh1_challenge)
+               BN_clear_free(ssh1_challenge);
+       ssh1_challenge = auth_rsa_generate_challenge(key);
+
+       buffer_clear(m);
+       buffer_put_bignum2(m, ssh1_challenge);
+
+       debug3("%s sending reply", __func__);
+       mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
+
+       xfree(blob);
+       key_free(key);
+       return (0);
+}
+
+int
+mm_answer_rsa_response(int sock, Buffer *m)
+{
+       Key *key = NULL;
+       u_char *blob, *response;
+       u_int blen, len;
+       int success;
+
+       debug3("%s entering", __func__);
+
+       if (!authctxt->valid)
+               fatal("%s: authctxt not valid", __func__);
+       if (ssh1_challenge == NULL)
+               fatal("%s: no ssh1_challenge", __func__);
+
+       blob = buffer_get_string(m, &blen);
+       if (!monitor_allowed_key(blob, blen))
+               fatal("%s: bad key, not previously allowed", __func__);
+       if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
+               fatal("%s: key type mismatch: %d", __func__, key_blobtype);
+       if ((key = key_from_blob(blob, blen)) == NULL)
+               fatal("%s: received bad key", __func__);
+       response = buffer_get_string(m, &len);
+       if (len != 16)
+               fatal("%s: received bad response to challenge", __func__);
+       success = auth_rsa_verify_response(key, ssh1_challenge, response);
+
+       xfree(blob);
+       key_free(key);
+       xfree(response);
+
+       auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
+
+       /* reset state */
+       BN_clear_free(ssh1_challenge);
+       ssh1_challenge = NULL;
+       monitor_reset_key_state();
+
+       buffer_clear(m);
+       buffer_put_int(m, success);
+       mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m);
+
+       return (success);
+}
+
+int
+mm_answer_term(int sock, Buffer *req)
+{
+       extern struct monitor *pmonitor;
+       int res, status;
+
+       debug3("%s: tearing down sessions", __func__);
+
+       /* The child is terminating */
+       session_destroy_all(&mm_session_close);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               sshpam_cleanup();
+#endif
+
+       while (waitpid(pmonitor->m_pid, &status, 0) == -1)
+               if (errno != EINTR)
+                       exit(1);
+
+       res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
+
+       /* Terminate process */
+       exit(res);
+}
+
+#ifdef SSH_AUDIT_EVENTS
+/* Report that an audit event occurred */
+int
+mm_answer_audit_event(int socket, Buffer *m)
+{
+       ssh_audit_event_t event;
+
+       debug3("%s entering", __func__);
+
+       event = buffer_get_int(m);
+       switch(event) {
+       case SSH_AUTH_FAIL_PUBKEY:
+       case SSH_AUTH_FAIL_HOSTBASED:
+       case SSH_AUTH_FAIL_GSSAPI:
+       case SSH_LOGIN_EXCEED_MAXTRIES:
+       case SSH_LOGIN_ROOT_DENIED:
+       case SSH_CONNECTION_CLOSE:
+       case SSH_INVALID_USER:
+               audit_event(event);
+               break;
+       default:
+               fatal("Audit event type %d not permitted", event);
+       }
+
+       return (0);
+}
+
+int
+mm_answer_audit_command(int socket, Buffer *m)
+{
+       u_int len;
+       char *cmd;
+
+       debug3("%s entering", __func__);
+       cmd = buffer_get_string(m, &len);
+       /* sanity check command, if so how? */
+       audit_run_command(cmd);
+       xfree(cmd);
+       return (0);
+}
+#endif /* SSH_AUDIT_EVENTS */
+
+void
+monitor_apply_keystate(struct monitor *pmonitor)
+{
+       if (compat20) {
+               set_newkeys(MODE_IN);
+               set_newkeys(MODE_OUT);
+       } else {
+               packet_set_protocol_flags(child_state.ssh1protoflags);
+               packet_set_encryption_key(child_state.ssh1key,
+                   child_state.ssh1keylen, child_state.ssh1cipher);
+               xfree(child_state.ssh1key);
+       }
+
+       /* for rc4 and other stateful ciphers */
+       packet_set_keycontext(MODE_OUT, child_state.keyout);
+       xfree(child_state.keyout);
+       packet_set_keycontext(MODE_IN, child_state.keyin);
+       xfree(child_state.keyin);
+
+       if (!compat20) {
+               packet_set_iv(MODE_OUT, child_state.ivout);
+               xfree(child_state.ivout);
+               packet_set_iv(MODE_IN, child_state.ivin);
+               xfree(child_state.ivin);
+       }
+
+       memcpy(&incoming_stream, &child_state.incoming,
+           sizeof(incoming_stream));
+       memcpy(&outgoing_stream, &child_state.outgoing,
+           sizeof(outgoing_stream));
+
+       /* Update with new address */
+       if (options.compression)
+               mm_init_compression(pmonitor->m_zlib);
+
+       /* Network I/O buffers */
+       /* XXX inefficient for large buffers, need: buffer_init_from_string */
+       buffer_clear(packet_get_input());
+       buffer_append(packet_get_input(), child_state.input, child_state.ilen);
+       memset(child_state.input, 0, child_state.ilen);
+       xfree(child_state.input);
+
+       buffer_clear(packet_get_output());
+       buffer_append(packet_get_output(), child_state.output,
+                     child_state.olen);
+       memset(child_state.output, 0, child_state.olen);
+       xfree(child_state.output);
+
+       /* Roaming */
+       if (compat20)
+               roam_set_bytes(child_state.sent_bytes, child_state.recv_bytes);
+}
+
+static Kex *
+mm_get_kex(Buffer *m)
+{
+       Kex *kex;
+       void *blob;
+       u_int bloblen;
+
+       kex = xcalloc(1, sizeof(*kex));
+       kex->session_id = buffer_get_string(m, &kex->session_id_len);
+       if (session_id2 == NULL ||
+           kex->session_id_len != session_id2_len ||
+           timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0)
+               fatal("mm_get_get: internal error: bad session id");
+       kex->we_need = buffer_get_int(m);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
+#endif
+       kex->server = 1;
+       kex->hostkey_type = buffer_get_int(m);
+       kex->kex_type = buffer_get_int(m);
+       blob = buffer_get_string(m, &bloblen);
+       buffer_init(&kex->my);
+       buffer_append(&kex->my, blob, bloblen);
+       xfree(blob);
+       blob = buffer_get_string(m, &bloblen);
+       buffer_init(&kex->peer);
+       buffer_append(&kex->peer, blob, bloblen);
+       xfree(blob);
+       kex->done = 1;
+       kex->flags = buffer_get_int(m);
+       kex->client_version_string = buffer_get_string(m, NULL);
+       kex->server_version_string = buffer_get_string(m, NULL);
+       kex->load_host_public_key=&get_hostkey_public_by_type;
+       kex->load_host_private_key=&get_hostkey_private_by_type;
+       kex->host_key_index=&get_hostkey_index;
+
+       return (kex);
+}
+
+/* This function requries careful sanity checking */
+
+void
+mm_get_keystate(struct monitor *pmonitor)
+{
+       Buffer m;
+       u_char *blob, *p;
+       u_int bloblen, plen;
+       u_int32_t seqnr, packets;
+       u_int64_t blocks, bytes;
+
+       debug3("%s: Waiting for new keys", __func__);
+
+       buffer_init(&m);
+       mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
+       if (!compat20) {
+               child_state.ssh1protoflags = buffer_get_int(&m);
+               child_state.ssh1cipher = buffer_get_int(&m);
+               child_state.ssh1key = buffer_get_string(&m,
+                   &child_state.ssh1keylen);
+               child_state.ivout = buffer_get_string(&m,
+                   &child_state.ivoutlen);
+               child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
+               goto skip;
+       } else {
+               /* Get the Kex for rekeying */
+               *pmonitor->m_pkex = mm_get_kex(&m);
+       }
+
+       blob = buffer_get_string(&m, &bloblen);
+       current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
+       xfree(blob);
+
+       debug3("%s: Waiting for second key", __func__);
+       blob = buffer_get_string(&m, &bloblen);
+       current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
+       xfree(blob);
+
+       /* Now get sequence numbers for the packets */
+       seqnr = buffer_get_int(&m);
+       blocks = buffer_get_int64(&m);
+       packets = buffer_get_int(&m);
+       bytes = buffer_get_int64(&m);
+       packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes);
+       seqnr = buffer_get_int(&m);
+       blocks = buffer_get_int64(&m);
+       packets = buffer_get_int(&m);
+       bytes = buffer_get_int64(&m);
+       packet_set_state(MODE_IN, seqnr, blocks, packets, bytes);
+
+ skip:
+       /* Get the key context */
+       child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
+       child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);
+
+       debug3("%s: Getting compression state", __func__);
+       /* Get compression state */
+       p = buffer_get_string(&m, &plen);
+       if (plen != sizeof(child_state.outgoing))
+               fatal("%s: bad request size", __func__);
+       memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
+       xfree(p);
+
+       p = buffer_get_string(&m, &plen);
+       if (plen != sizeof(child_state.incoming))
+               fatal("%s: bad request size", __func__);
+       memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
+       xfree(p);
+
+       /* Network I/O buffers */
+       debug3("%s: Getting Network I/O buffers", __func__);
+       child_state.input = buffer_get_string(&m, &child_state.ilen);
+       child_state.output = buffer_get_string(&m, &child_state.olen);
+
+       /* Roaming */
+       if (compat20) {
+               child_state.sent_bytes = buffer_get_int64(&m);
+               child_state.recv_bytes = buffer_get_int64(&m);
+       }
+
+       buffer_free(&m);
+}
+
+
+/* Allocation functions for zlib */
+void *
+mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
+{
+       size_t len = (size_t) size * ncount;
+       void *address;
+
+       if (len == 0 || ncount > SIZE_T_MAX / size)
+               fatal("%s: mm_zalloc(%u, %u)", __func__, ncount, size);
+
+       address = mm_malloc(mm, len);
+
+       return (address);
+}
+
+void
+mm_zfree(struct mm_master *mm, void *address)
+{
+       mm_free(mm, address);
+}
+
+void
+mm_init_compression(struct mm_master *mm)
+{
+       outgoing_stream.zalloc = (alloc_func)mm_zalloc;
+       outgoing_stream.zfree = (free_func)mm_zfree;
+       outgoing_stream.opaque = mm;
+
+       incoming_stream.zalloc = (alloc_func)mm_zalloc;
+       incoming_stream.zfree = (free_func)mm_zfree;
+       incoming_stream.opaque = mm;
+}
+
+/* XXX */
+
+#define FD_CLOSEONEXEC(x) do { \
+       if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \
+               fatal("fcntl(%d, F_SETFD)", x); \
+} while (0)
+
+static void
+monitor_openfds(struct monitor *mon, int do_logfds)
+{
+       int pair[2];
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
+               fatal("%s: socketpair: %s", __func__, strerror(errno));
+       FD_CLOSEONEXEC(pair[0]);
+       FD_CLOSEONEXEC(pair[1]);
+       mon->m_recvfd = pair[0];
+       mon->m_sendfd = pair[1];
+
+       if (do_logfds) {
+               if (pipe(pair) == -1)
+                       fatal("%s: pipe: %s", __func__, strerror(errno));
+               FD_CLOSEONEXEC(pair[0]);
+               FD_CLOSEONEXEC(pair[1]);
+               mon->m_log_recvfd = pair[0];
+               mon->m_log_sendfd = pair[1];
+       } else
+               mon->m_log_recvfd = mon->m_log_sendfd = -1;
+}
+
+#define MM_MEMSIZE     65536
+
+struct monitor *
+monitor_init(void)
+{
+       struct monitor *mon;
+
+       mon = xcalloc(1, sizeof(*mon));
+
+       monitor_openfds(mon, 1);
+
+       /* Used to share zlib space across processes */
+       if (options.compression) {
+               mon->m_zback = mm_create(NULL, MM_MEMSIZE);
+               mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
+
+               /* Compression needs to share state across borders */
+               mm_init_compression(mon->m_zlib);
+       }
+
+       return mon;
+}
+
+void
+monitor_reinit(struct monitor *mon)
+{
+       monitor_openfds(mon, 0);
+}
+
+#ifdef GSSAPI
+int
+mm_answer_gss_setup_ctx(int sock, Buffer *m)
+{
+       gss_OID_desc goid;
+       OM_uint32 major;
+       u_int len;
+
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       goid.elements = buffer_get_string(m, &len);
+       goid.length = len;
+
+       major = ssh_gssapi_server_ctx(&gsscontext, &goid);
+
+       xfree(goid.elements);
+
+       buffer_clear(m);
+       buffer_put_int(m, major);
+
+       mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
+
+       /* Now we have a context, enable the step */
+       monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
+
+       return (0);
+}
+
+int
+mm_answer_gss_accept_ctx(int sock, Buffer *m)
+{
+       gss_buffer_desc in;
+       gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       OM_uint32 flags = 0; /* GSI needs this */
+       u_int len;
+
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       in.value = buffer_get_string(m, &len);
+       in.length = len;
+       major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
+       xfree(in.value);
+
+       buffer_clear(m);
+       buffer_put_int(m, major);
+       buffer_put_string(m, out.value, out.length);
+       buffer_put_int(m, flags);
+       mm_request_send(sock, MONITOR_ANS_GSSSTEP, m);
+
+       gss_release_buffer(&minor, &out);
+
+       if (major == GSS_S_COMPLETE) {
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
+       }
+       return (0);
+}
+
+int
+mm_answer_gss_checkmic(int sock, Buffer *m)
+{
+       gss_buffer_desc gssbuf, mic;
+       OM_uint32 ret;
+       u_int len;
+
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       gssbuf.value = buffer_get_string(m, &len);
+       gssbuf.length = len;
+       mic.value = buffer_get_string(m, &len);
+       mic.length = len;
+
+       ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
+
+       xfree(gssbuf.value);
+       xfree(mic.value);
+
+       buffer_clear(m);
+       buffer_put_int(m, ret);
+
+       mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m);
+
+       if (!GSS_ERROR(ret))
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
+
+       return (0);
+}
+
+int
+mm_answer_gss_userok(int sock, Buffer *m)
+{
+       int authenticated;
+
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       authenticated = authctxt->valid && 
+           ssh_gssapi_userok(authctxt->user, authctxt->pw);
+
+       buffer_clear(m);
+       buffer_put_int(m, authenticated);
+
+       debug3("%s: sending result %d", __func__, authenticated);
+       mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
+
+       auth_method = "gssapi-with-mic";
+
+       /* Monitor loop will terminate if authenticated */
+       return (authenticated);
+}
+
+int 
+mm_answer_gss_sign(int socket, Buffer *m)
+{
+       gss_buffer_desc data;
+       gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       u_int len;
+
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       data.value = buffer_get_string(m, &len);
+       data.length = len;
+       if (data.length != 20) 
+               fatal("%s: data length incorrect: %d", __func__, 
+                   (int) data.length);
+
+       /* Save the session ID on the first time around */
+       if (session_id2_len == 0) {
+               session_id2_len = data.length;
+               session_id2 = xmalloc(session_id2_len);
+               memcpy(session_id2, data.value, session_id2_len);
+       }
+       major = ssh_gssapi_sign(gsscontext, &data, &hash);
+
+       xfree(data.value);
+
+       buffer_clear(m);
+       buffer_put_int(m, major);
+       buffer_put_string(m, hash.value, hash.length);
+
+       mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
+
+       gss_release_buffer(&minor, &hash);
+
+       /* Turn on getpwnam permissions */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+       
+       /* And credential updating, for when rekeying */
+       monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
+
+       return (0);
+}
+
+int
+mm_answer_gss_updatecreds(int socket, Buffer *m) {
+       ssh_gssapi_ccache store;
+       int ok;
+
+       store.filename = buffer_get_string(m, NULL);
+       store.envvar   = buffer_get_string(m, NULL);
+       store.envval   = buffer_get_string(m, NULL);
+
+       ok = ssh_gssapi_update_creds(&store);
+
+       xfree(store.filename);
+       xfree(store.envvar);
+       xfree(store.envval);
+
+       buffer_clear(m);
+       buffer_put_int(m, ok);
+
+       mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
+
+       return(0);
+}
+
+#endif /* GSSAPI */
+
+#ifdef JPAKE
+int
+mm_answer_jpake_step1(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx;
+       u_char *x3_proof, *x4_proof;
+       u_int x3_proof_len, x4_proof_len;
+
+       if (!options.zero_knowledge_password_authentication)
+               fatal("zero_knowledge_password_authentication disabled");
+
+       if (authctxt->jpake_ctx != NULL)
+               fatal("%s: authctxt->jpake_ctx already set (%p)",
+                   __func__, authctxt->jpake_ctx);
+       authctxt->jpake_ctx = pctx = jpake_new();
+
+       jpake_step1(pctx->grp,
+           &pctx->server_id, &pctx->server_id_len,
+           &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
+           &x3_proof, &x3_proof_len,
+           &x4_proof, &x4_proof_len);
+
+       JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__));
+
+       buffer_clear(m);
+
+       buffer_put_string(m, pctx->server_id, pctx->server_id_len);
+       buffer_put_bignum2(m, pctx->g_x3);
+       buffer_put_bignum2(m, pctx->g_x4);
+       buffer_put_string(m, x3_proof, x3_proof_len);
+       buffer_put_string(m, x4_proof, x4_proof_len);
+
+       debug3("%s: sending step1", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m);
+
+       bzero(x3_proof, x3_proof_len);
+       bzero(x4_proof, x4_proof_len);
+       xfree(x3_proof);
+       xfree(x4_proof);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1);
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_get_pwdata(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+       char *hash_scheme, *salt;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt);
+
+       buffer_clear(m);
+       /* pctx->s is sensitive, not returned to slave */
+       buffer_put_cstring(m, hash_scheme);
+       buffer_put_cstring(m, salt);
+
+       debug3("%s: sending pwdata", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m);
+
+       bzero(hash_scheme, strlen(hash_scheme));
+       bzero(salt, strlen(salt));
+       xfree(hash_scheme);
+       xfree(salt);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_step2(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+       u_char *x1_proof, *x2_proof, *x4_s_proof;
+       u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       if ((pctx->g_x1 = BN_new()) == NULL ||
+           (pctx->g_x2 = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+       buffer_get_bignum2(m, pctx->g_x1);
+       buffer_get_bignum2(m, pctx->g_x2);
+       pctx->client_id = buffer_get_string(m, &pctx->client_id_len);
+       x1_proof = buffer_get_string(m, &x1_proof_len);
+       x2_proof = buffer_get_string(m, &x2_proof_len);
+
+       jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
+           pctx->g_x1, pctx->g_x2, pctx->x4,
+           pctx->client_id, pctx->client_id_len,
+           pctx->server_id, pctx->server_id_len,
+           x1_proof, x1_proof_len,
+           x2_proof, x2_proof_len,
+           &pctx->b,
+           &x4_s_proof, &x4_s_proof_len);
+
+       JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__));
+
+       bzero(x1_proof, x1_proof_len);
+       bzero(x2_proof, x2_proof_len);
+       xfree(x1_proof);
+       xfree(x2_proof);
+
+       buffer_clear(m);
+
+       buffer_put_bignum2(m, pctx->b);
+       buffer_put_string(m, x4_s_proof, x4_s_proof_len);
+
+       debug3("%s: sending step2", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m);
+
+       bzero(x4_s_proof, x4_s_proof_len);
+       xfree(x4_s_proof);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_key_confirm(int sock, Buffer *m)
+{
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+       u_char *x2_s_proof;
+       u_int x2_s_proof_len;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       if ((pctx->a = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+       buffer_get_bignum2(m, pctx->a);
+       x2_s_proof = buffer_get_string(m, &x2_s_proof_len);
+
+       jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
+           pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
+           pctx->server_id, pctx->server_id_len,
+           pctx->client_id, pctx->client_id_len,
+           session_id2, session_id2_len,
+           x2_s_proof, x2_s_proof_len,
+           &pctx->k,
+           &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len);
+
+       JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__));
+
+       bzero(x2_s_proof, x2_s_proof_len);
+       buffer_clear(m);
+
+       /* pctx->k is sensitive, not sent */
+       buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
+
+       debug3("%s: sending confirmation hash", __func__);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1);
+
+       return 0;
+}
+
+int
+mm_answer_jpake_check_confirm(int sock, Buffer *m)
+{
+       int authenticated = 0;
+       u_char *peer_confirm_hash;
+       u_int peer_confirm_hash_len;
+       struct jpake_ctx *pctx = authctxt->jpake_ctx;
+
+       if (pctx == NULL)
+               fatal("%s: pctx == NULL", __func__);
+
+       peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len);
+
+       authenticated = jpake_check_confirm(pctx->k,
+           pctx->client_id, pctx->client_id_len,
+           session_id2, session_id2_len,
+           peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid;
+
+       JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__));
+
+       bzero(peer_confirm_hash, peer_confirm_hash_len);
+       xfree(peer_confirm_hash);
+
+       buffer_clear(m);
+       buffer_put_int(m, authenticated);
+
+       debug3("%s: sending result %d", __func__, authenticated);
+       mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m);
+
+       monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1);
+
+       auth_method = "jpake-01@openssh.com";
+       return authenticated;
+}
+
+#endif /* JPAKE */
diff --git a/.pc/selinux-role.patch/monitor.h b/.pc/selinux-role.patch/monitor.h
new file mode 100644 (file)
index 0000000..db0443f
--- /dev/null
@@ -0,0 +1,101 @@
+/* $OpenBSD: monitor.h,v 1.16 2011/06/17 21:44:31 djm Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MONITOR_H_
+#define _MONITOR_H_
+
+enum monitor_reqtype {
+       MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
+       MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
+       MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
+       MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
+       MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
+       MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
+       MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY,
+       MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
+       MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
+       MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
+       MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
+       MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
+       MONITOR_REQ_KEYEXPORT,
+       MONITOR_REQ_PTY, MONITOR_ANS_PTY,
+       MONITOR_REQ_PTYCLEANUP,
+       MONITOR_REQ_SESSKEY, MONITOR_ANS_SESSKEY,
+       MONITOR_REQ_SESSID,
+       MONITOR_REQ_RSAKEYALLOWED, MONITOR_ANS_RSAKEYALLOWED,
+       MONITOR_REQ_RSACHALLENGE, MONITOR_ANS_RSACHALLENGE,
+       MONITOR_REQ_RSARESPONSE, MONITOR_ANS_RSARESPONSE,
+       MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP,
+       MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
+       MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
+       MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
+       MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
+       MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS,
+       MONITOR_REQ_PAM_START,
+       MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
+       MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
+       MONITOR_REQ_PAM_QUERY, MONITOR_ANS_PAM_QUERY,
+       MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND,
+       MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX,
+       MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND,
+       MONITOR_REQ_TERM,
+       MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
+       MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
+       MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2,
+       MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM,
+       MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM,
+};
+
+struct mm_master;
+struct monitor {
+       int                      m_recvfd;
+       int                      m_sendfd;
+       int                      m_log_recvfd;
+       int                      m_log_sendfd;
+       struct mm_master        *m_zback;
+       struct mm_master        *m_zlib;
+       struct Kex              **m_pkex;
+       pid_t                    m_pid;
+};
+
+struct monitor *monitor_init(void);
+void monitor_reinit(struct monitor *);
+void monitor_sync(struct monitor *);
+
+struct Authctxt;
+void monitor_child_preauth(struct Authctxt *, struct monitor *);
+void monitor_child_postauth(struct monitor *);
+
+struct mon_table;
+int monitor_read(struct monitor*, struct mon_table *, struct mon_table **);
+
+/* Prototypes for request sending and receiving */
+void mm_request_send(int, enum monitor_reqtype, Buffer *);
+void mm_request_receive(int, Buffer *);
+void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *);
+
+#endif /* _MONITOR_H_ */
diff --git a/.pc/selinux-role.patch/monitor_wrap.c b/.pc/selinux-role.patch/monitor_wrap.c
new file mode 100644 (file)
index 0000000..fc6bbcd
--- /dev/null
@@ -0,0 +1,1497 @@
+/* $OpenBSD: monitor_wrap.c,v 1.73 2011/06/17 21:44:31 djm Exp $ */
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * Copyright 2002 Markus Friedl <markus@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "dh.h"
+#include "buffer.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "auth-options.h"
+#include "packet.h"
+#include "mac.h"
+#include "log.h"
+#ifdef TARGET_OS_MAC    /* XXX Broken krb5 headers on Mac */
+#undef TARGET_OS_MAC
+#include "zlib.h"
+#define TARGET_OS_MAC 1
+#else
+#include "zlib.h"
+#endif
+#include "monitor.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "atomicio.h"
+#include "monitor_fdpass.h"
+#include "misc.h"
+#include "schnorr.h"
+#include "jpake.h"
+#include "uuencode.h"
+
+#include "channels.h"
+#include "session.h"
+#include "servconf.h"
+#include "roaming.h"
+
+/* Imports */
+extern int compat20;
+extern z_stream incoming_stream;
+extern z_stream outgoing_stream;
+extern struct monitor *pmonitor;
+extern Buffer loginmsg;
+extern ServerOptions options;
+
+void
+mm_log_handler(LogLevel level, const char *msg, void *ctx)
+{
+       Buffer log_msg;
+       struct monitor *mon = (struct monitor *)ctx;
+
+       if (mon->m_log_sendfd == -1)
+               fatal("%s: no log channel", __func__);
+
+       buffer_init(&log_msg);
+       /*
+        * Placeholder for packet length. Will be filled in with the actual
+        * packet length once the packet has been constucted. This saves
+        * fragile math.
+        */
+       buffer_put_int(&log_msg, 0);
+
+       buffer_put_int(&log_msg, level);
+       buffer_put_cstring(&log_msg, msg);
+       put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
+       if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
+           buffer_len(&log_msg)) != buffer_len(&log_msg))
+               fatal("%s: write: %s", __func__, strerror(errno));
+       buffer_free(&log_msg);
+}
+
+int
+mm_is_monitor(void)
+{
+       /*
+        * m_pid is only set in the privileged part, and
+        * points to the unprivileged child.
+        */
+       return (pmonitor && pmonitor->m_pid > 0);
+}
+
+void
+mm_request_send(int sock, enum monitor_reqtype type, Buffer *m)
+{
+       u_int mlen = buffer_len(m);
+       u_char buf[5];
+
+       debug3("%s entering: type %d", __func__, type);
+
+       put_u32(buf, mlen + 1);
+       buf[4] = (u_char) type;         /* 1st byte of payload is mesg-type */
+       if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
+               fatal("%s: write: %s", __func__, strerror(errno));
+       if (atomicio(vwrite, sock, buffer_ptr(m), mlen) != mlen)
+               fatal("%s: write: %s", __func__, strerror(errno));
+}
+
+void
+mm_request_receive(int sock, Buffer *m)
+{
+       u_char buf[4];
+       u_int msg_len;
+
+       debug3("%s entering", __func__);
+
+       if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
+               if (errno == EPIPE)
+                       cleanup_exit(255);
+               fatal("%s: read: %s", __func__, strerror(errno));
+       }
+       msg_len = get_u32(buf);
+       if (msg_len > 256 * 1024)
+               fatal("%s: read: bad msg_len %d", __func__, msg_len);
+       buffer_clear(m);
+       buffer_append_space(m, msg_len);
+       if (atomicio(read, sock, buffer_ptr(m), msg_len) != msg_len)
+               fatal("%s: read: %s", __func__, strerror(errno));
+}
+
+void
+mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
+{
+       u_char rtype;
+
+       debug3("%s entering: type %d", __func__, type);
+
+       mm_request_receive(sock, m);
+       rtype = buffer_get_char(m);
+       if (rtype != type)
+               fatal("%s: read: rtype %d != type %d", __func__,
+                   rtype, type);
+}
+
+DH *
+mm_choose_dh(int min, int nbits, int max)
+{
+       BIGNUM *p, *g;
+       int success = 0;
+       Buffer m;
+
+       buffer_init(&m);
+       buffer_put_int(&m, min);
+       buffer_put_int(&m, nbits);
+       buffer_put_int(&m, max);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m);
+
+       success = buffer_get_char(&m);
+       if (success == 0)
+               fatal("%s: MONITOR_ANS_MODULI failed", __func__);
+
+       if ((p = BN_new()) == NULL)
+               fatal("%s: BN_new failed", __func__);
+       if ((g = BN_new()) == NULL)
+               fatal("%s: BN_new failed", __func__);
+       buffer_get_bignum2(&m, p);
+       buffer_get_bignum2(&m, g);
+
+       debug3("%s: remaining %d", __func__, buffer_len(&m));
+       buffer_free(&m);
+
+       return (dh_new_group(g, p));
+}
+
+int
+mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
+{
+       Kex *kex = *pmonitor->m_pkex;
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_int(&m, kex->host_key_index(key));
+       buffer_put_string(&m, data, datalen);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m);
+       *sigp  = buffer_get_string(&m, lenp);
+       buffer_free(&m);
+
+       return (0);
+}
+
+struct passwd *
+mm_getpwnamallow(const char *username)
+{
+       Buffer m;
+       struct passwd *pw;
+       u_int len, i;
+       ServerOptions *newopts;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, username);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m);
+
+       if (buffer_get_char(&m) == 0) {
+               pw = NULL;
+               goto out;
+       }
+       pw = buffer_get_string(&m, &len);
+       if (len != sizeof(struct passwd))
+               fatal("%s: struct passwd size mismatch", __func__);
+       pw->pw_name = buffer_get_string(&m, NULL);
+       pw->pw_passwd = buffer_get_string(&m, NULL);
+       pw->pw_gecos = buffer_get_string(&m, NULL);
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+       pw->pw_class = buffer_get_string(&m, NULL);
+#endif
+       pw->pw_dir = buffer_get_string(&m, NULL);
+       pw->pw_shell = buffer_get_string(&m, NULL);
+
+out:
+       /* copy options block as a Match directive may have changed some */
+       newopts = buffer_get_string(&m, &len);
+       if (len != sizeof(*newopts))
+               fatal("%s: option block size mismatch", __func__);
+
+#define M_CP_STROPT(x) do { \
+               if (newopts->x != NULL) \
+                       newopts->x = buffer_get_string(&m, NULL); \
+       } while (0)
+#define M_CP_STRARRAYOPT(x, nx) do { \
+               for (i = 0; i < newopts->nx; i++) \
+                       newopts->x[i] = buffer_get_string(&m, NULL); \
+       } while (0)
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+
+       copy_set_server_options(&options, newopts, 1);
+       xfree(newopts);
+
+       buffer_free(&m);
+
+       return (pw);
+}
+
+char *
+mm_auth2_read_banner(void)
+{
+       Buffer m;
+       char *banner;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m);
+       buffer_clear(&m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_AUTH2_READ_BANNER, &m);
+       banner = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       /* treat empty banner as missing banner */
+       if (strlen(banner) == 0) {
+               xfree(banner);
+               banner = NULL;
+       }
+       return (banner);
+}
+
+/* Inform the privileged process about service and style */
+
+void
+mm_inform_authserv(char *service, char *style)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, service);
+       buffer_put_cstring(&m, style ? style : "");
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
+
+       buffer_free(&m);
+}
+
+/* Do the password authentication */
+int
+mm_auth_password(Authctxt *authctxt, char *password)
+{
+       Buffer m;
+       int authenticated = 0;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, password);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
+
+       authenticated = buffer_get_int(&m);
+
+       buffer_free(&m);
+
+       debug3("%s: user %sauthenticated",
+           __func__, authenticated ? "" : "not ");
+       return (authenticated);
+}
+
+int
+mm_user_key_allowed(struct passwd *pw, Key *key)
+{
+       return (mm_key_allowed(MM_USERKEY, NULL, NULL, key));
+}
+
+int
+mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
+    Key *key)
+{
+       return (mm_key_allowed(MM_HOSTKEY, user, host, key));
+}
+
+int
+mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
+    char *host, Key *key)
+{
+       int ret;
+
+       key->type = KEY_RSA; /* XXX hack for key_to_blob */
+       ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key);
+       key->type = KEY_RSA1;
+       return (ret);
+}
+
+int
+mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key)
+{
+       Buffer m;
+       u_char *blob;
+       u_int len;
+       int allowed = 0, have_forced = 0;
+
+       debug3("%s entering", __func__);
+
+       /* Convert the key to a blob and the pass it over */
+       if (!key_to_blob(key, &blob, &len))
+               return (0);
+
+       buffer_init(&m);
+       buffer_put_int(&m, type);
+       buffer_put_cstring(&m, user ? user : "");
+       buffer_put_cstring(&m, host ? host : "");
+       buffer_put_string(&m, blob, len);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m);
+
+       allowed = buffer_get_int(&m);
+
+       /* fake forced command */
+       auth_clear_options();
+       have_forced = buffer_get_int(&m);
+       forced_command = have_forced ? xstrdup("true") : NULL;
+
+       buffer_free(&m);
+
+       return (allowed);
+}
+
+/*
+ * This key verify needs to send the key type along, because the
+ * privileged parent makes the decision if the key is allowed
+ * for authentication.
+ */
+
+int
+mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+{
+       Buffer m;
+       u_char *blob;
+       u_int len;
+       int verified = 0;
+
+       debug3("%s entering", __func__);
+
+       /* Convert the key to a blob and the pass it over */
+       if (!key_to_blob(key, &blob, &len))
+               return (0);
+
+       buffer_init(&m);
+       buffer_put_string(&m, blob, len);
+       buffer_put_string(&m, sig, siglen);
+       buffer_put_string(&m, data, datalen);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
+
+       verified = buffer_get_int(&m);
+
+       buffer_free(&m);
+
+       return (verified);
+}
+
+/* Export key state after authentication */
+Newkeys *
+mm_newkeys_from_blob(u_char *blob, int blen)
+{
+       Buffer b;
+       u_int len;
+       Newkeys *newkey = NULL;
+       Enc *enc;
+       Mac *mac;
+       Comp *comp;
+
+       debug3("%s: %p(%d)", __func__, blob, blen);
+#ifdef DEBUG_PK
+       dump_base64(stderr, blob, blen);
+#endif
+       buffer_init(&b);
+       buffer_append(&b, blob, blen);
+
+       newkey = xmalloc(sizeof(*newkey));
+       enc = &newkey->enc;
+       mac = &newkey->mac;
+       comp = &newkey->comp;
+
+       /* Enc structure */
+       enc->name = buffer_get_string(&b, NULL);
+       buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
+       enc->enabled = buffer_get_int(&b);
+       enc->block_size = buffer_get_int(&b);
+       enc->key = buffer_get_string(&b, &enc->key_len);
+       enc->iv = buffer_get_string(&b, &len);
+       if (len != enc->block_size)
+               fatal("%s: bad ivlen: expected %u != %u", __func__,
+                   enc->block_size, len);
+
+       if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
+               fatal("%s: bad cipher name %s or pointer %p", __func__,
+                   enc->name, enc->cipher);
+
+       /* Mac structure */
+       mac->name = buffer_get_string(&b, NULL);
+       if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
+               fatal("%s: can not setup mac %s", __func__, mac->name);
+       mac->enabled = buffer_get_int(&b);
+       mac->key = buffer_get_string(&b, &len);
+       if (len > mac->key_len)
+               fatal("%s: bad mac key length: %u > %d", __func__, len,
+                   mac->key_len);
+       mac->key_len = len;
+
+       /* Comp structure */
+       comp->type = buffer_get_int(&b);
+       comp->enabled = buffer_get_int(&b);
+       comp->name = buffer_get_string(&b, NULL);
+
+       len = buffer_len(&b);
+       if (len != 0)
+               error("newkeys_from_blob: remaining bytes in blob %u", len);
+       buffer_free(&b);
+       return (newkey);
+}
+
+int
+mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
+{
+       Buffer b;
+       int len;
+       Enc *enc;
+       Mac *mac;
+       Comp *comp;
+       Newkeys *newkey = (Newkeys *)packet_get_newkeys(mode);
+
+       debug3("%s: converting %p", __func__, newkey);
+
+       if (newkey == NULL) {
+               error("%s: newkey == NULL", __func__);
+               return 0;
+       }
+       enc = &newkey->enc;
+       mac = &newkey->mac;
+       comp = &newkey->comp;
+
+       buffer_init(&b);
+       /* Enc structure */
+       buffer_put_cstring(&b, enc->name);
+       /* The cipher struct is constant and shared, you export pointer */
+       buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
+       buffer_put_int(&b, enc->enabled);
+       buffer_put_int(&b, enc->block_size);
+       buffer_put_string(&b, enc->key, enc->key_len);
+       packet_get_keyiv(mode, enc->iv, enc->block_size);
+       buffer_put_string(&b, enc->iv, enc->block_size);
+
+       /* Mac structure */
+       buffer_put_cstring(&b, mac->name);
+       buffer_put_int(&b, mac->enabled);
+       buffer_put_string(&b, mac->key, mac->key_len);
+
+       /* Comp structure */
+       buffer_put_int(&b, comp->type);
+       buffer_put_int(&b, comp->enabled);
+       buffer_put_cstring(&b, comp->name);
+
+       len = buffer_len(&b);
+       if (lenp != NULL)
+               *lenp = len;
+       if (blobp != NULL) {
+               *blobp = xmalloc(len);
+               memcpy(*blobp, buffer_ptr(&b), len);
+       }
+       memset(buffer_ptr(&b), 0, len);
+       buffer_free(&b);
+       return len;
+}
+
+static void
+mm_send_kex(Buffer *m, Kex *kex)
+{
+       buffer_put_string(m, kex->session_id, kex->session_id_len);
+       buffer_put_int(m, kex->we_need);
+       buffer_put_int(m, kex->hostkey_type);
+       buffer_put_int(m, kex->kex_type);
+       buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my));
+       buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer));
+       buffer_put_int(m, kex->flags);
+       buffer_put_cstring(m, kex->client_version_string);
+       buffer_put_cstring(m, kex->server_version_string);
+}
+
+void
+mm_send_keystate(struct monitor *monitor)
+{
+       Buffer m, *input, *output;
+       u_char *blob, *p;
+       u_int bloblen, plen;
+       u_int32_t seqnr, packets;
+       u_int64_t blocks, bytes;
+
+       buffer_init(&m);
+
+       if (!compat20) {
+               u_char iv[24];
+               u_char *key;
+               u_int ivlen, keylen;
+
+               buffer_put_int(&m, packet_get_protocol_flags());
+
+               buffer_put_int(&m, packet_get_ssh1_cipher());
+
+               debug3("%s: Sending ssh1 KEY+IV", __func__);
+               keylen = packet_get_encryption_key(NULL);
+               key = xmalloc(keylen+1);        /* add 1 if keylen == 0 */
+               keylen = packet_get_encryption_key(key);
+               buffer_put_string(&m, key, keylen);
+               memset(key, 0, keylen);
+               xfree(key);
+
+               ivlen = packet_get_keyiv_len(MODE_OUT);
+               packet_get_keyiv(MODE_OUT, iv, ivlen);
+               buffer_put_string(&m, iv, ivlen);
+               ivlen = packet_get_keyiv_len(MODE_OUT);
+               packet_get_keyiv(MODE_IN, iv, ivlen);
+               buffer_put_string(&m, iv, ivlen);
+               goto skip;
+       } else {
+               /* Kex for rekeying */
+               mm_send_kex(&m, *monitor->m_pkex);
+       }
+
+       debug3("%s: Sending new keys: %p %p",
+           __func__, packet_get_newkeys(MODE_OUT),
+           packet_get_newkeys(MODE_IN));
+
+       /* Keys from Kex */
+       if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
+               fatal("%s: conversion of newkeys failed", __func__);
+
+       buffer_put_string(&m, blob, bloblen);
+       xfree(blob);
+
+       if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
+               fatal("%s: conversion of newkeys failed", __func__);
+
+       buffer_put_string(&m, blob, bloblen);
+       xfree(blob);
+
+       packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
+       buffer_put_int(&m, seqnr);
+       buffer_put_int64(&m, blocks);
+       buffer_put_int(&m, packets);
+       buffer_put_int64(&m, bytes);
+       packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
+       buffer_put_int(&m, seqnr);
+       buffer_put_int64(&m, blocks);
+       buffer_put_int(&m, packets);
+       buffer_put_int64(&m, bytes);
+
+       debug3("%s: New keys have been sent", __func__);
+ skip:
+       /* More key context */
+       plen = packet_get_keycontext(MODE_OUT, NULL);
+       p = xmalloc(plen+1);
+       packet_get_keycontext(MODE_OUT, p);
+       buffer_put_string(&m, p, plen);
+       xfree(p);
+
+       plen = packet_get_keycontext(MODE_IN, NULL);
+       p = xmalloc(plen+1);
+       packet_get_keycontext(MODE_IN, p);
+       buffer_put_string(&m, p, plen);
+       xfree(p);
+
+       /* Compression state */
+       debug3("%s: Sending compression state", __func__);
+       buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
+       buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
+
+       /* Network I/O buffers */
+       input = (Buffer *)packet_get_input();
+       output = (Buffer *)packet_get_output();
+       buffer_put_string(&m, buffer_ptr(input), buffer_len(input));
+       buffer_put_string(&m, buffer_ptr(output), buffer_len(output));
+
+       /* Roaming */
+       if (compat20) {
+               buffer_put_int64(&m, get_sent_bytes());
+               buffer_put_int64(&m, get_recv_bytes());
+       }
+
+       mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m);
+       debug3("%s: Finished sending state", __func__);
+
+       buffer_free(&m);
+}
+
+int
+mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
+{
+       Buffer m;
+       char *p, *msg;
+       int success = 0, tmp1 = -1, tmp2 = -1;
+
+       /* Kludge: ensure there are fds free to receive the pty/tty */
+       if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
+           (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
+               error("%s: cannot allocate fds for pty", __func__);
+               if (tmp1 > 0)
+                       close(tmp1);
+               if (tmp2 > 0)
+                       close(tmp2);
+               return 0;
+       }
+       close(tmp1);
+       close(tmp2);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m);
+
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: pty alloc failed", __func__);
+               buffer_free(&m);
+               return (0);
+       }
+       p = buffer_get_string(&m, NULL);
+       msg = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       strlcpy(namebuf, p, namebuflen); /* Possible truncation */
+       xfree(p);
+
+       buffer_append(&loginmsg, msg, strlen(msg));
+       xfree(msg);
+
+       if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
+           (*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
+               fatal("%s: receive fds failed", __func__);
+
+       /* Success */
+       return (1);
+}
+
+void
+mm_session_pty_cleanup2(Session *s)
+{
+       Buffer m;
+
+       if (s->ttyfd == -1)
+               return;
+       buffer_init(&m);
+       buffer_put_cstring(&m, s->tty);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m);
+       buffer_free(&m);
+
+       /* closed dup'ed master */
+       if (s->ptymaster != -1 && close(s->ptymaster) < 0)
+               error("close(s->ptymaster/%d): %s",
+                   s->ptymaster, strerror(errno));
+
+       /* unlink pty from session */
+       s->ttyfd = -1;
+}
+
+#ifdef USE_PAM
+void
+mm_start_pam(Authctxt *authctxt)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+       if (!options.use_pam)
+               fatal("UsePAM=no, but ended up in %s anyway", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m);
+
+       buffer_free(&m);
+}
+
+u_int
+mm_do_pam_account(void)
+{
+       Buffer m;
+       u_int ret;
+       char *msg;
+
+       debug3("%s entering", __func__);
+       if (!options.use_pam)
+               fatal("UsePAM=no, but ended up in %s anyway", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_PAM_ACCOUNT, &m);
+       ret = buffer_get_int(&m);
+       msg = buffer_get_string(&m, NULL);
+       buffer_append(&loginmsg, msg, strlen(msg));
+       xfree(msg);
+
+       buffer_free(&m);
+
+       debug3("%s returning %d", __func__, ret);
+
+       return (ret);
+}
+
+void *
+mm_sshpam_init_ctx(Authctxt *authctxt)
+{
+       Buffer m;
+       int success;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       buffer_put_cstring(&m, authctxt->user);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, &m);
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: pam_init_ctx failed", __func__);
+               buffer_free(&m);
+               return (NULL);
+       }
+       buffer_free(&m);
+       return (authctxt);
+}
+
+int
+mm_sshpam_query(void *ctx, char **name, char **info,
+    u_int *num, char ***prompts, u_int **echo_on)
+{
+       Buffer m;
+       u_int i;
+       int ret;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, &m);
+       ret = buffer_get_int(&m);
+       debug3("%s: pam_query returned %d", __func__, ret);
+       *name = buffer_get_string(&m, NULL);
+       *info = buffer_get_string(&m, NULL);
+       *num = buffer_get_int(&m);
+       if (*num > PAM_MAX_NUM_MSG)
+               fatal("%s: recieved %u PAM messages, expected <= %u",
+                   __func__, *num, PAM_MAX_NUM_MSG);
+       *prompts = xcalloc((*num + 1), sizeof(char *));
+       *echo_on = xcalloc((*num + 1), sizeof(u_int));
+       for (i = 0; i < *num; ++i) {
+               (*prompts)[i] = buffer_get_string(&m, NULL);
+               (*echo_on)[i] = buffer_get_int(&m);
+       }
+       buffer_free(&m);
+       return (ret);
+}
+
+int
+mm_sshpam_respond(void *ctx, u_int num, char **resp)
+{
+       Buffer m;
+       u_int i;
+       int ret;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       buffer_put_int(&m, num);
+       for (i = 0; i < num; ++i)
+               buffer_put_cstring(&m, resp[i]);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, &m);
+       ret = buffer_get_int(&m);
+       debug3("%s: pam_respond returned %d", __func__, ret);
+       buffer_free(&m);
+       return (ret);
+}
+
+void
+mm_sshpam_free_ctx(void *ctxtp)
+{
+       Buffer m;
+
+       debug3("%s", __func__);
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, &m);
+       debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, &m);
+       buffer_free(&m);
+}
+#endif /* USE_PAM */
+
+/* Request process termination */
+
+void
+mm_terminate(void)
+{
+       Buffer m;
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m);
+       buffer_free(&m);
+}
+
+int
+mm_ssh1_session_key(BIGNUM *num)
+{
+       int rsafail;
+       Buffer m;
+
+       buffer_init(&m);
+       buffer_put_bignum2(&m, num);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m);
+
+       rsafail = buffer_get_int(&m);
+       buffer_get_bignum2(&m, num);
+
+       buffer_free(&m);
+
+       return (rsafail);
+}
+
+static void
+mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
+    char ***prompts, u_int **echo_on)
+{
+       *name = xstrdup("");
+       *infotxt = xstrdup("");
+       *numprompts = 1;
+       *prompts = xcalloc(*numprompts, sizeof(char *));
+       *echo_on = xcalloc(*numprompts, sizeof(u_int));
+       (*echo_on)[0] = 0;
+}
+
+int
+mm_bsdauth_query(void *ctx, char **name, char **infotxt,
+   u_int *numprompts, char ***prompts, u_int **echo_on)
+{
+       Buffer m;
+       u_int success;
+       char *challenge;
+
+       debug3("%s: entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY,
+           &m);
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: no challenge", __func__);
+               buffer_free(&m);
+               return (-1);
+       }
+
+       /* Get the challenge, and format the response */
+       challenge  = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
+       (*prompts)[0] = challenge;
+
+       debug3("%s: received challenge: %s", __func__, challenge);
+
+       return (0);
+}
+
+int
+mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
+{
+       Buffer m;
+       int authok;
+
+       debug3("%s: entering", __func__);
+       if (numresponses != 1)
+               return (-1);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, responses[0]);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_BSDAUTHRESPOND, &m);
+
+       authok = buffer_get_int(&m);
+       buffer_free(&m);
+
+       return ((authok == 0) ? -1 : 0);
+}
+
+#ifdef SKEY
+int
+mm_skey_query(void *ctx, char **name, char **infotxt,
+   u_int *numprompts, char ***prompts, u_int **echo_on)
+{
+       Buffer m;
+       u_int success;
+       char *challenge;
+
+       debug3("%s: entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY,
+           &m);
+       success = buffer_get_int(&m);
+       if (success == 0) {
+               debug3("%s: no challenge", __func__);
+               buffer_free(&m);
+               return (-1);
+       }
+
+       /* Get the challenge, and format the response */
+       challenge  = buffer_get_string(&m, NULL);
+       buffer_free(&m);
+
+       debug3("%s: received challenge: %s", __func__, challenge);
+
+       mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
+
+       xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT);
+       xfree(challenge);
+
+       return (0);
+}
+
+int
+mm_skey_respond(void *ctx, u_int numresponses, char **responses)
+{
+       Buffer m;
+       int authok;
+
+       debug3("%s: entering", __func__);
+       if (numresponses != 1)
+               return (-1);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, responses[0]);
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m);
+
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_SKEYRESPOND, &m);
+
+       authok = buffer_get_int(&m);
+       buffer_free(&m);
+
+       return ((authok == 0) ? -1 : 0);
+}
+#endif /* SKEY */
+
+void
+mm_ssh1_session_id(u_char session_id[16])
+{
+       Buffer m;
+       int i;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       for (i = 0; i < 16; i++)
+               buffer_put_char(&m, session_id[i]);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m);
+       buffer_free(&m);
+}
+
+int
+mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+{
+       Buffer m;
+       Key *key;
+       u_char *blob;
+       u_int blen;
+       int allowed = 0, have_forced = 0;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_bignum2(&m, client_n);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m);
+
+       allowed = buffer_get_int(&m);
+
+       /* fake forced command */
+       auth_clear_options();
+       have_forced = buffer_get_int(&m);
+       forced_command = have_forced ? xstrdup("true") : NULL;
+
+       if (allowed && rkey != NULL) {
+               blob = buffer_get_string(&m, &blen);
+               if ((key = key_from_blob(blob, blen)) == NULL)
+                       fatal("%s: key_from_blob failed", __func__);
+               *rkey = key;
+               xfree(blob);
+       }
+       buffer_free(&m);
+
+       return (allowed);
+}
+
+BIGNUM *
+mm_auth_rsa_generate_challenge(Key *key)
+{
+       Buffer m;
+       BIGNUM *challenge;
+       u_char *blob;
+       u_int blen;
+
+       debug3("%s entering", __func__);
+
+       if ((challenge = BN_new()) == NULL)
+               fatal("%s: BN_new failed", __func__);
+
+       key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
+       if (key_to_blob(key, &blob, &blen) == 0)
+               fatal("%s: key_to_blob failed", __func__);
+       key->type = KEY_RSA1;
+
+       buffer_init(&m);
+       buffer_put_string(&m, blob, blen);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m);
+
+       buffer_get_bignum2(&m, challenge);
+       buffer_free(&m);
+
+       return (challenge);
+}
+
+int
+mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
+{
+       Buffer m;
+       u_char *blob;
+       u_int blen;
+       int success = 0;
+
+       debug3("%s entering", __func__);
+
+       key->type = KEY_RSA;    /* XXX cheat for key_to_blob */
+       if (key_to_blob(key, &blob, &blen) == 0)
+               fatal("%s: key_to_blob failed", __func__);
+       key->type = KEY_RSA1;
+
+       buffer_init(&m);
+       buffer_put_string(&m, blob, blen);
+       buffer_put_string(&m, response, 16);
+       xfree(blob);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m);
+
+       success = buffer_get_int(&m);
+       buffer_free(&m);
+
+       return (success);
+}
+
+#ifdef SSH_AUDIT_EVENTS
+void
+mm_audit_event(ssh_audit_event_t event)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_int(&m, event);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
+       buffer_free(&m);
+}
+
+void
+mm_audit_run_command(const char *command)
+{
+       Buffer m;
+
+       debug3("%s entering command %s", __func__, command);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, command);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
+       buffer_free(&m);
+}
+#endif /* SSH_AUDIT_EVENTS */
+
+#ifdef GSSAPI
+OM_uint32
+mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
+{
+       Buffer m;
+       OM_uint32 major;
+
+       /* Client doesn't get to see the context */
+       *ctx = NULL;
+
+       buffer_init(&m);
+       buffer_put_string(&m, goid->elements, goid->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
+
+       major = buffer_get_int(&m);
+
+       buffer_free(&m);
+       return (major);
+}
+
+OM_uint32
+mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
+    gss_buffer_desc *out, OM_uint32 *flags)
+{
+       Buffer m;
+       OM_uint32 major;
+       u_int len;
+
+       buffer_init(&m);
+       buffer_put_string(&m, in->value, in->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
+
+       major = buffer_get_int(&m);
+       out->value = buffer_get_string(&m, &len);
+       out->length = len;
+       if (flags)
+               *flags = buffer_get_int(&m);
+
+       buffer_free(&m);
+
+       return (major);
+}
+
+OM_uint32
+mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+       Buffer m;
+       OM_uint32 major;
+
+       buffer_init(&m);
+       buffer_put_string(&m, gssbuf->value, gssbuf->length);
+       buffer_put_string(&m, gssmic->value, gssmic->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSCHECKMIC,
+           &m);
+
+       major = buffer_get_int(&m);
+       buffer_free(&m);
+       return(major);
+}
+
+int
+mm_ssh_gssapi_userok(char *user, struct passwd *pw)
+{
+       Buffer m;
+       int authenticated = 0;
+
+       buffer_init(&m);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
+                                 &m);
+
+       authenticated = buffer_get_int(&m);
+
+       buffer_free(&m);
+       debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
+       return (authenticated);
+}
+
+OM_uint32
+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
+{
+       Buffer m;
+       OM_uint32 major;
+       u_int len;
+
+       buffer_init(&m);
+       buffer_put_string(&m, data->value, data->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
+
+       major = buffer_get_int(&m);
+       hash->value = buffer_get_string(&m, &len);
+       hash->length = len;
+
+       buffer_free(&m);
+
+       return(major);
+}
+
+int
+mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
+{
+       Buffer m;
+       int ok;
+
+       buffer_init(&m);
+
+       buffer_put_cstring(&m, store->filename ? store->filename : "");
+       buffer_put_cstring(&m, store->envvar ? store->envvar : "");
+       buffer_put_cstring(&m, store->envval ? store->envval : "");
+       
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
+
+       ok = buffer_get_int(&m);
+
+       buffer_free(&m);
+       
+       return (ok);
+}
+
+#endif /* GSSAPI */
+
+#ifdef JPAKE
+void
+mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
+    char **hash_scheme, char **salt)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_GET_PWDATA, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_GET_PWDATA, &m);
+
+       *hash_scheme = buffer_get_string(&m, NULL);
+       *salt = buffer_get_string(&m, NULL);
+
+       buffer_free(&m);
+}
+
+void
+mm_jpake_step1(struct modp_group *grp,
+    u_char **id, u_int *id_len,
+    BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
+    u_char **priv1_proof, u_int *priv1_proof_len,
+    u_char **priv2_proof, u_int *priv2_proof_len)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_STEP1, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_STEP1, &m);
+
+       if ((*priv1 = BN_new()) == NULL ||
+           (*priv2 = BN_new()) == NULL ||
+           (*g_priv1 = BN_new()) == NULL ||
+           (*g_priv2 = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       *id = buffer_get_string(&m, id_len);
+       /* priv1 and priv2 are, well, private */
+       buffer_get_bignum2(&m, *g_priv1);
+       buffer_get_bignum2(&m, *g_priv2);
+       *priv1_proof = buffer_get_string(&m, priv1_proof_len);
+       *priv2_proof = buffer_get_string(&m, priv2_proof_len);
+
+       buffer_free(&m);
+}
+
+void
+mm_jpake_step2(struct modp_group *grp, BIGNUM *s,
+    BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
+    const u_char *theirid, u_int theirid_len,
+    const u_char *myid, u_int myid_len,
+    const u_char *theirpub1_proof, u_int theirpub1_proof_len,
+    const u_char *theirpub2_proof, u_int theirpub2_proof_len,
+    BIGNUM **newpub,
+    u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       /* monitor already has all bignums except theirpub1, theirpub2 */
+       buffer_put_bignum2(&m, theirpub1);
+       buffer_put_bignum2(&m, theirpub2);
+       /* monitor already knows our id */
+       buffer_put_string(&m, theirid, theirid_len);
+       buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len);
+       buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len);
+
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_STEP2, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_STEP2, &m);
+
+       if ((*newpub = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       buffer_get_bignum2(&m, *newpub);
+       *newpub_exponent_proof = buffer_get_string(&m,
+           newpub_exponent_proof_len);
+
+       buffer_free(&m);
+}
+
+void
+mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
+    BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
+    BIGNUM *theirpub1, BIGNUM *theirpub2,
+    const u_char *my_id, u_int my_id_len,
+    const u_char *their_id, u_int their_id_len,
+    const u_char *sess_id, u_int sess_id_len,
+    const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
+    BIGNUM **k,
+    u_char **confirm_hash, u_int *confirm_hash_len)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       /* monitor already has all bignums except step2_val */
+       buffer_put_bignum2(&m, step2_val);
+       /* monitor already knows all the ids */
+       buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len);
+
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_KEY_CONFIRM, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_KEY_CONFIRM, &m);
+
+       /* 'k' is sensitive and stays in the monitor */
+       *confirm_hash = buffer_get_string(&m, confirm_hash_len);
+
+       buffer_free(&m);
+}
+
+int
+mm_jpake_check_confirm(const BIGNUM *k,
+    const u_char *peer_id, u_int peer_id_len,
+    const u_char *sess_id, u_int sess_id_len,
+    const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
+{
+       Buffer m;
+       int success = 0;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       /* k is dummy in slave, ignored */
+       /* monitor knows all the ids */
+       buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len);
+       mm_request_send(pmonitor->m_recvfd,
+           MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m);
+
+       debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__);
+       mm_request_receive_expect(pmonitor->m_recvfd,
+           MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m);
+
+       success = buffer_get_int(&m);
+       buffer_free(&m);
+
+       debug3("%s: success = %d", __func__, success);
+       return success;
+}
+#endif /* JPAKE */
diff --git a/.pc/selinux-role.patch/monitor_wrap.h b/.pc/selinux-role.patch/monitor_wrap.h
new file mode 100644 (file)
index 0000000..ec9b9b1
--- /dev/null
@@ -0,0 +1,133 @@
+/* $OpenBSD: monitor_wrap.h,v 1.23 2011/06/17 21:44:31 djm Exp $ */
+
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MM_WRAP_H_
+#define _MM_WRAP_H_
+
+extern int use_privsep;
+#define PRIVSEP(x)     (use_privsep ? mm_##x : x)
+
+enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY};
+
+struct monitor;
+struct mm_master;
+struct Authctxt;
+
+void mm_log_handler(LogLevel, const char *, void *);
+int mm_is_monitor(void);
+DH *mm_choose_dh(int, int, int);
+int mm_key_sign(Key *, u_char **, u_int *, 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_key_allowed(enum mm_keytype, char *, char *, Key *);
+int mm_user_key_allowed(struct passwd *, Key *);
+int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
+int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
+int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
+int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
+int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
+BIGNUM *mm_auth_rsa_generate_challenge(Key *);
+
+#ifdef GSSAPI
+OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
+OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
+   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
+int mm_ssh_gssapi_userok(char *user, struct passwd *);
+OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
+#endif
+
+#ifdef USE_PAM
+void mm_start_pam(struct Authctxt *);
+u_int mm_do_pam_account(void);
+void *mm_sshpam_init_ctx(struct Authctxt *);
+int mm_sshpam_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_sshpam_respond(void *, u_int, char **);
+void mm_sshpam_free_ctx(void *);
+#endif
+
+#ifdef SSH_AUDIT_EVENTS
+#include "audit.h"
+void mm_audit_event(ssh_audit_event_t);
+void mm_audit_run_command(const char *);
+#endif
+
+struct Session;
+void mm_terminate(void);
+int mm_pty_allocate(int *, int *, char *, size_t);
+void mm_session_pty_cleanup2(struct Session *);
+
+/* SSHv1 interfaces */
+void mm_ssh1_session_id(u_char *);
+int mm_ssh1_session_key(BIGNUM *);
+
+/* Key export functions */
+struct Newkeys *mm_newkeys_from_blob(u_char *, int);
+int mm_newkeys_to_blob(int, u_char **, u_int *);
+
+void monitor_apply_keystate(struct monitor *);
+void mm_get_keystate(struct monitor *);
+void mm_send_keystate(struct monitor*);
+
+/* bsdauth */
+int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_bsdauth_respond(void *, u_int, char **);
+
+/* skey */
+int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
+int mm_skey_respond(void *, u_int, char **);
+
+/* jpake */
+struct modp_group;
+void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **);
+void mm_jpake_step1(struct modp_group *, u_char **, u_int *,
+    BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **,
+    u_char **, u_int *, u_char **, u_int *);
+void mm_jpake_step2(struct modp_group *, BIGNUM *,
+    BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
+    const u_char *, u_int, const u_char *, u_int,
+    const u_char *, u_int, const u_char *, u_int,
+    BIGNUM **, u_char **, u_int *);
+void mm_jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *,
+    BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
+    const u_char *, u_int, const u_char *, u_int,
+    const u_char *, u_int, const u_char *, u_int,
+    BIGNUM **, u_char **, u_int *);
+int mm_jpake_check_confirm(const BIGNUM *,
+    const u_char *, u_int, const u_char *, u_int, const u_char *, u_int);
+
+
+/* zlib allocation hooks */
+
+void *mm_zalloc(struct mm_master *, u_int, u_int);
+void mm_zfree(struct mm_master *, void *);
+void mm_init_compression(struct mm_master *);
+
+#endif /* _MM_WRAP_H_ */
diff --git a/.pc/selinux-role.patch/openbsd-compat/port-linux.c b/.pc/selinux-role.patch/openbsd-compat/port-linux.c
new file mode 100644 (file)
index 0000000..ea8dff4
--- /dev/null
@@ -0,0 +1,312 @@
+/* $Id: port-linux.c,v 1.16 2011/08/29 06:09:57 djm Exp $ */
+
+/*
+ * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
+ * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Linux-specific portability code - just SELinux support at present
+ */
+
+#include "includes.h"
+
+#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "log.h"
+#include "xmalloc.h"
+#include "port-linux.h"
+
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/flask.h>
+#include <selinux/get_context_list.h>
+
+#ifndef SSH_SELINUX_UNCONFINED_TYPE
+# define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:"
+#endif
+
+/* Wrapper around is_selinux_enabled() to log its return value once only */
+int
+ssh_selinux_enabled(void)
+{
+       static int enabled = -1;
+
+       if (enabled == -1) {
+               enabled = (is_selinux_enabled() == 1);
+               debug("SELinux support %s", enabled ? "enabled" : "disabled");
+       }
+
+       return (enabled);
+}
+
+/* Return the default security context for the given username */
+static security_context_t
+ssh_selinux_getctxbyname(char *pwname)
+{
+       security_context_t sc;
+       char *sename = NULL, *lvl = NULL;
+       int r;
+
+#ifdef HAVE_GETSEUSERBYNAME
+       if (getseuserbyname(pwname, &sename, &lvl) != 0)
+               return NULL;
+#else
+       sename = pwname;
+       lvl = NULL;
+#endif
+
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+       r = get_default_context_with_level(sename, lvl, NULL, &sc);
+#else
+       r = get_default_context(sename, NULL, &sc);
+#endif
+
+       if (r != 0) {
+               switch (security_getenforce()) {
+               case -1:
+                       fatal("%s: ssh_selinux_getctxbyname: "
+                           "security_getenforce() failed", __func__);
+               case 0:
+                       error("%s: Failed to get default SELinux security "
+                           "context for %s", __func__, pwname);
+                       break;
+               default:
+                       fatal("%s: Failed to get default SELinux security "
+                           "context for %s (in enforcing mode)",
+                           __func__, pwname);
+               }
+       }
+
+#ifdef HAVE_GETSEUSERBYNAME
+       if (sename != NULL)
+               xfree(sename);
+       if (lvl != NULL)
+               xfree(lvl);
+#endif
+
+       return (sc);
+}
+
+/* Set the execution context to the default for the specified user */
+void
+ssh_selinux_setup_exec_context(char *pwname)
+{
+       security_context_t user_ctx = NULL;
+
+       if (!ssh_selinux_enabled())
+               return;
+
+       debug3("%s: setting execution context", __func__);
+
+       user_ctx = ssh_selinux_getctxbyname(pwname);
+       if (setexeccon(user_ctx) != 0) {
+               switch (security_getenforce()) {
+               case -1:
+                       fatal("%s: security_getenforce() failed", __func__);
+               case 0:
+                       error("%s: Failed to set SELinux execution "
+                           "context for %s", __func__, pwname);
+                       break;
+               default:
+                       fatal("%s: Failed to set SELinux execution context "
+                           "for %s (in enforcing mode)", __func__, pwname);
+               }
+       }
+       if (user_ctx != NULL)
+               freecon(user_ctx);
+
+       debug3("%s: done", __func__);
+}
+
+/* Set the TTY context for the specified user */
+void
+ssh_selinux_setup_pty(char *pwname, const char *tty)
+{
+       security_context_t new_tty_ctx = NULL;
+       security_context_t user_ctx = NULL;
+       security_context_t old_tty_ctx = NULL;
+
+       if (!ssh_selinux_enabled())
+               return;
+
+       debug3("%s: setting TTY context on %s", __func__, tty);
+
+       user_ctx = ssh_selinux_getctxbyname(pwname);
+
+       /* XXX: should these calls fatal() upon failure in enforcing mode? */
+
+       if (getfilecon(tty, &old_tty_ctx) == -1) {
+               error("%s: getfilecon: %s", __func__, strerror(errno));
+               goto out;
+       }
+
+       if (security_compute_relabel(user_ctx, old_tty_ctx,
+           SECCLASS_CHR_FILE, &new_tty_ctx) != 0) {
+               error("%s: security_compute_relabel: %s",
+                   __func__, strerror(errno));
+               goto out;
+       }
+
+       if (setfilecon(tty, new_tty_ctx) != 0)
+               error("%s: setfilecon: %s", __func__, strerror(errno));
+ out:
+       if (new_tty_ctx != NULL)
+               freecon(new_tty_ctx);
+       if (old_tty_ctx != NULL)
+               freecon(old_tty_ctx);
+       if (user_ctx != NULL)
+               freecon(user_ctx);
+       debug3("%s: done", __func__);
+}
+
+void
+ssh_selinux_change_context(const char *newname)
+{
+       int len, newlen;
+       char *oldctx, *newctx, *cx;
+       void (*switchlog) (const char *fmt,...) = logit;
+
+       if (!ssh_selinux_enabled())
+               return;
+
+       if (getcon((security_context_t *)&oldctx) < 0) {
+               logit("%s: getcon failed with %s", __func__, strerror(errno));
+               return;
+       }
+       if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) ==
+           NULL) {
+               logit ("%s: unparseable context %s", __func__, oldctx);
+               return;
+       }
+
+       /*
+        * Check whether we are attempting to switch away from an unconfined
+        * security context.
+        */
+       if (strncmp(cx, SSH_SELINUX_UNCONFINED_TYPE,
+           sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0)
+               switchlog = debug3;
+
+       newlen = strlen(oldctx) + strlen(newname) + 1;
+       newctx = xmalloc(newlen);
+       len = cx - oldctx + 1;
+       memcpy(newctx, oldctx, len);
+       strlcpy(newctx + len, newname, newlen - len);
+       if ((cx = index(cx + 1, ':')))
+               strlcat(newctx, cx, newlen);
+       debug3("%s: setting context from '%s' to '%s'", __func__,
+           oldctx, newctx);
+       if (setcon(newctx) < 0)
+               switchlog("%s: setcon %s from %s failed with %s", __func__,
+                   newctx, oldctx, strerror(errno));
+       xfree(oldctx);
+       xfree(newctx);
+}
+
+void
+ssh_selinux_setfscreatecon(const char *path)
+{
+       security_context_t context;
+
+       if (!ssh_selinux_enabled())
+               return;
+       if (path == NULL) {
+               setfscreatecon(NULL);
+               return;
+       }
+       if (matchpathcon(path, 0700, &context) == 0)
+               setfscreatecon(context);
+}
+
+#endif /* WITH_SELINUX */
+
+#ifdef LINUX_OOM_ADJUST
+/*
+ * The magic "don't kill me" values, old and new, as documented in eg:
+ * http://lxr.linux.no/#linux+v2.6.32/Documentation/filesystems/proc.txt
+ * http://lxr.linux.no/#linux+v2.6.36/Documentation/filesystems/proc.txt
+ */
+
+static int oom_adj_save = INT_MIN;
+static char *oom_adj_path = NULL;
+struct {
+       char *path;
+       int value;
+} oom_adjust[] = {
+       {"/proc/self/oom_score_adj", -1000},    /* kernels >= 2.6.36 */
+       {"/proc/self/oom_adj", -17},            /* kernels <= 2.6.35 */
+       {NULL, 0},
+};
+
+/*
+ * Tell the kernel's out-of-memory killer to avoid sshd.
+ * Returns the previous oom_adj value or zero.
+ */
+void
+oom_adjust_setup(void)
+{
+       int i, value;
+       FILE *fp;
+
+       debug3("%s", __func__);
+        for (i = 0; oom_adjust[i].path != NULL; i++) {
+               oom_adj_path = oom_adjust[i].path;
+               value = oom_adjust[i].value;
+               if ((fp = fopen(oom_adj_path, "r+")) != NULL) {
+                       if (fscanf(fp, "%d", &oom_adj_save) != 1)
+                               verbose("error reading %s: %s", oom_adj_path,
+                                   strerror(errno));
+                       else {
+                               rewind(fp);
+                               if (fprintf(fp, "%d\n", value) <= 0)
+                                       verbose("error writing %s: %s",
+                                          oom_adj_path, strerror(errno));
+                               else
+                                       verbose("Set %s from %d to %d",
+                                          oom_adj_path, oom_adj_save, value);
+                       }
+                       fclose(fp);
+                       return;
+               }
+       }
+       oom_adj_path = NULL;
+}
+
+/* Restore the saved OOM adjustment */
+void
+oom_adjust_restore(void)
+{
+       FILE *fp;
+
+       debug3("%s", __func__);
+       if (oom_adj_save == INT_MIN || oom_adj_path == NULL ||
+           (fp = fopen(oom_adj_path, "w")) == NULL)
+               return;
+
+       if (fprintf(fp, "%d\n", oom_adj_save) <= 0)
+               verbose("error writing %s: %s", oom_adj_path, strerror(errno));
+       else
+               verbose("Set %s to %d", oom_adj_path, oom_adj_save);
+
+       fclose(fp);
+       return;
+}
+#endif /* LINUX_OOM_ADJUST */
+#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */
diff --git a/.pc/selinux-role.patch/openbsd-compat/port-linux.h b/.pc/selinux-role.patch/openbsd-compat/port-linux.h
new file mode 100644 (file)
index 0000000..e3d1004
--- /dev/null
@@ -0,0 +1,35 @@
+/* $Id: port-linux.h,v 1.5 2011/01/25 01:16:18 djm Exp $ */
+
+/*
+ * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _PORT_LINUX_H
+#define _PORT_LINUX_H
+
+#ifdef WITH_SELINUX
+int ssh_selinux_enabled(void);
+void ssh_selinux_setup_pty(char *, const char *);
+void ssh_selinux_setup_exec_context(char *);
+void ssh_selinux_change_context(const char *);
+void ssh_selinux_setfscreatecon(const char *);
+#endif
+
+#ifdef LINUX_OOM_ADJUST
+void oom_adjust_restore(void);
+void oom_adjust_setup(void);
+#endif
+
+#endif /* ! _PORT_LINUX_H */
diff --git a/.pc/selinux-role.patch/platform.c b/.pc/selinux-role.patch/platform.c
new file mode 100644 (file)
index 0000000..a455472
--- /dev/null
@@ -0,0 +1,196 @@
+/* $Id: platform.c,v 1.18 2011/01/11 06:02:25 djm Exp $ */
+
+/*
+ * Copyright (c) 2006 Darren Tucker.  All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "auth-pam.h"
+#include "platform.h"
+
+#include "openbsd-compat/openbsd-compat.h"
+
+extern int use_privsep;
+extern ServerOptions options;
+
+void
+platform_pre_listen(void)
+{
+#ifdef LINUX_OOM_ADJUST
+       /* Adjust out-of-memory killer so listening process is not killed */
+       oom_adjust_setup();
+#endif
+}
+
+void
+platform_pre_fork(void)
+{
+#ifdef USE_SOLARIS_PROCESS_CONTRACTS
+       solaris_contract_pre_fork();
+#endif
+}
+
+void
+platform_post_fork_parent(pid_t child_pid)
+{
+#ifdef USE_SOLARIS_PROCESS_CONTRACTS
+       solaris_contract_post_fork_parent(child_pid);
+#endif
+}
+
+void
+platform_post_fork_child(void)
+{
+#ifdef USE_SOLARIS_PROCESS_CONTRACTS
+       solaris_contract_post_fork_child();
+#endif
+#ifdef LINUX_OOM_ADJUST
+       oom_adjust_restore();
+#endif
+}
+
+/* return 1 if we are running with privilege to swap UIDs, 0 otherwise */
+int
+platform_privileged_uidswap(void)
+{
+#ifdef HAVE_CYGWIN
+       /* uid 0 is not special on Cygwin so always try */
+       return 1;
+#else
+       return (getuid() == 0 || geteuid() == 0);
+#endif
+}
+
+/*
+ * This gets called before switching UIDs, and is called even when sshd is
+ * not running as root.
+ */
+void
+platform_setusercontext(struct passwd *pw)
+{
+#ifdef WITH_SELINUX
+       /* Cache selinux status for later use */
+       (void)ssh_selinux_enabled();
+#endif
+
+#ifdef USE_SOLARIS_PROJECTS
+       /* if solaris projects were detected, set the default now */
+       if (getuid() == 0 || geteuid() == 0)
+               solaris_set_default_project(pw);
+#endif
+
+#if defined(HAVE_LOGIN_CAP) && defined (__bsdi__)
+       if (getuid() == 0 || geteuid() == 0)
+               setpgid(0, 0);
+# endif
+
+#if defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
+       /*
+        * If we have both LOGIN_CAP and PAM, we want to establish creds
+        * before calling setusercontext (in session.c:do_setusercontext).
+        */
+       if (getuid() == 0 || geteuid() == 0) {
+               if (options.use_pam) {
+                       do_pam_setcred(use_privsep);
+               }
+       }
+# endif /* USE_PAM */
+
+#if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
+       if (getuid() == 0 || geteuid() == 0) {
+               /* Sets login uid for accounting */
+               if (getluid() == -1 && setluid(pw->pw_uid) == -1)
+                       error("setluid: %s", strerror(errno));
+       }
+#endif
+}
+
+/*
+ * This gets called after we've established the user's groups, and is only
+ * called if sshd is running as root.
+ */
+void
+platform_setusercontext_post_groups(struct passwd *pw)
+{
+#if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
+       /*
+        * PAM credentials may take the form of supplementary groups.
+        * These will have been wiped by the above initgroups() call.
+        * Reestablish them here.
+        */
+       if (options.use_pam) {
+               do_pam_setcred(use_privsep);
+       }
+#endif /* USE_PAM */
+
+#if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \
+    defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY))
+       irix_setusercontext(pw);
+#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
+
+#ifdef _AIX
+       aix_usrinfo(pw);
+#endif /* _AIX */
+
+#if !defined(HAVE_LOGIN_CAP) && defined(USE_LIBIAF)
+       if (set_id(pw->pw_name) != 0) {
+               exit(1);
+       }
+# endif /* USE_LIBIAF */
+
+#ifdef HAVE_SETPCRED
+       /*
+        * If we have a chroot directory, we set all creds except real
+        * uid which we will need for chroot.  If we don't have a
+        * chroot directory, we don't override anything.
+        */
+       {
+               char **creds = NULL, *chroot_creds[] =
+                   { "REAL_USER=root", NULL };
+
+               if (options.chroot_directory != NULL &&
+                   strcasecmp(options.chroot_directory, "none") != 0)
+                       creds = chroot_creds;
+
+               if (setpcred(pw->pw_name, creds) == -1)
+                       fatal("Failed to set process credentials");
+       }
+#endif /* HAVE_SETPCRED */
+#ifdef WITH_SELINUX
+       ssh_selinux_setup_exec_context(pw->pw_name);
+#endif
+}
+
+char *
+platform_krb5_get_principal_name(const char *pw_name)
+{
+#ifdef USE_AIX_KRB_NAME
+       return aix_krb5_get_principal_name(pw_name);
+#else
+       return NULL;
+#endif
+}
diff --git a/.pc/selinux-role.patch/platform.h b/.pc/selinux-role.patch/platform.h
new file mode 100644 (file)
index 0000000..944d2c3
--- /dev/null
@@ -0,0 +1,33 @@
+/* $Id: platform.h,v 1.7 2010/11/05 03:47:01 dtucker Exp $ */
+
+/*
+ * Copyright (c) 2006 Darren Tucker.  All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <pwd.h>
+
+void platform_pre_listen(void);
+void platform_pre_fork(void);
+void platform_post_fork_parent(pid_t child_pid);
+void platform_post_fork_child(void);
+int  platform_privileged_uidswap(void);
+void platform_setusercontext(struct passwd *);
+void platform_setusercontext_post_groups(struct passwd *);
+char *platform_get_krb5_client(const char *);
+char *platform_krb5_get_principal_name(const char *);
+
+
diff --git a/.pc/selinux-role.patch/session.c b/.pc/selinux-role.patch/session.c
new file mode 100644 (file)
index 0000000..6a70400
--- /dev/null
@@ -0,0 +1,2734 @@
+/* $OpenBSD: session.c,v 1.258 2010/11/25 04:10:09 djm Exp $ */
+/*
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 support by Markus Friedl.
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "sshpty.h"
+#include "packet.h"
+#include "buffer.h"
+#include "match.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "channels.h"
+#include "key.h"
+#include "cipher.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "hostfile.h"
+#include "auth.h"
+#include "auth-options.h"
+#include "pathnames.h"
+#include "log.h"
+#include "servconf.h"
+#include "sshlogin.h"
+#include "serverloop.h"
+#include "canohost.h"
+#include "misc.h"
+#include "session.h"
+#include "kex.h"
+#include "monitor_wrap.h"
+#include "sftp.h"
+
+#if defined(KRB5) && defined(USE_AFS)
+#include <kafs.h>
+#endif
+
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#endif
+
+#define IS_INTERNAL_SFTP(c) \
+       (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
+        (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
+         c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \
+         c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t'))
+
+/* func */
+
+Session *session_new(void);
+void   session_set_fds(Session *, int, int, int, int, int);
+void   session_pty_cleanup(Session *);
+void   session_proctitle(Session *);
+int    session_setup_x11fwd(Session *);
+int    do_exec_pty(Session *, const char *);
+int    do_exec_no_pty(Session *, const char *);
+int    do_exec(Session *, const char *);
+void   do_login(Session *, const char *);
+#ifdef LOGIN_NEEDS_UTMPX
+static void    do_pre_login(Session *s);
+#endif
+void   do_child(Session *, const char *);
+void   do_motd(void);
+int    check_quietlogin(Session *, const char *);
+
+static void do_authenticated1(Authctxt *);
+static void do_authenticated2(Authctxt *);
+
+static int session_pty_req(Session *);
+
+/* import */
+extern ServerOptions options;
+extern char *__progname;
+extern int log_stderr;
+extern int debug_flag;
+extern u_int utmp_len;
+extern int startup_pipe;
+extern void destroy_sensitive_data(void);
+extern Buffer loginmsg;
+
+/* original command from peer. */
+const char *original_command = NULL;
+
+/* data */
+static int sessions_first_unused = -1;
+static int sessions_nalloc = 0;
+static Session *sessions = NULL;
+
+#define SUBSYSTEM_NONE                 0
+#define SUBSYSTEM_EXT                  1
+#define SUBSYSTEM_INT_SFTP             2
+#define SUBSYSTEM_INT_SFTP_ERROR       3
+
+#ifdef HAVE_LOGIN_CAP
+login_cap_t *lc;
+#endif
+
+static int is_child = 0;
+
+/* Name and directory of socket for authentication agent forwarding. */
+static char *auth_sock_name = NULL;
+static char *auth_sock_dir = NULL;
+
+/* removes the agent forwarding socket */
+
+static void
+auth_sock_cleanup_proc(struct passwd *pw)
+{
+       if (auth_sock_name != NULL) {
+               temporarily_use_uid(pw);
+               unlink(auth_sock_name);
+               rmdir(auth_sock_dir);
+               auth_sock_name = NULL;
+               restore_uid();
+       }
+}
+
+static int
+auth_input_request_forwarding(struct passwd * pw)
+{
+       Channel *nc;
+       int sock = -1;
+       struct sockaddr_un sunaddr;
+
+       if (auth_sock_name != NULL) {
+               error("authentication forwarding requested twice.");
+               return 0;
+       }
+
+       /* Temporarily drop privileged uid for mkdir/bind. */
+       temporarily_use_uid(pw);
+
+       /* Allocate a buffer for the socket name, and format the name. */
+       auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
+
+       /* Create private directory for socket */
+       if (mkdtemp(auth_sock_dir) == NULL) {
+               packet_send_debug("Agent forwarding disabled: "
+                   "mkdtemp() failed: %.100s", strerror(errno));
+               restore_uid();
+               xfree(auth_sock_dir);
+               auth_sock_dir = NULL;
+               goto authsock_err;
+       }
+
+       xasprintf(&auth_sock_name, "%s/agent.%ld",
+           auth_sock_dir, (long) getpid());
+
+       /* Create the socket. */
+       sock = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (sock < 0) {
+               error("socket: %.100s", strerror(errno));
+               restore_uid();
+               goto authsock_err;
+       }
+
+       /* Bind it to the name. */
+       memset(&sunaddr, 0, sizeof(sunaddr));
+       sunaddr.sun_family = AF_UNIX;
+       strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
+
+       if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
+               error("bind: %.100s", strerror(errno));
+               restore_uid();
+               goto authsock_err;
+       }
+
+       /* Restore the privileged uid. */
+       restore_uid();
+
+       /* Start listening on the socket. */
+       if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
+               error("listen: %.100s", strerror(errno));
+               goto authsock_err;
+       }
+
+       /* Allocate a channel for the authentication agent socket. */
+       nc = channel_new("auth socket",
+           SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
+           CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
+           0, "auth socket", 1);
+       nc->path = xstrdup(auth_sock_name);
+       return 1;
+
+ authsock_err:
+       if (auth_sock_name != NULL)
+               xfree(auth_sock_name);
+       if (auth_sock_dir != NULL) {
+               rmdir(auth_sock_dir);
+               xfree(auth_sock_dir);
+       }
+       if (sock != -1)
+               close(sock);
+       auth_sock_name = NULL;
+       auth_sock_dir = NULL;
+       return 0;
+}
+
+static void
+display_loginmsg(void)
+{
+       if (buffer_len(&loginmsg) > 0) {
+               buffer_append(&loginmsg, "\0", 1);
+               printf("%s", (char *)buffer_ptr(&loginmsg));
+               buffer_clear(&loginmsg);
+       }
+}
+
+void
+do_authenticated(Authctxt *authctxt)
+{
+       setproctitle("%s", authctxt->pw->pw_name);
+
+       /* setup the channel layer */
+       if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
+               channel_permit_all_opens();
+
+       auth_debug_send();
+
+       if (compat20)
+               do_authenticated2(authctxt);
+       else
+               do_authenticated1(authctxt);
+
+       do_cleanup(authctxt);
+}
+
+/*
+ * Prepares for an interactive session.  This is called after the user has
+ * been successfully authenticated.  During this message exchange, pseudo
+ * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
+ * are requested, etc.
+ */
+static void
+do_authenticated1(Authctxt *authctxt)
+{
+       Session *s;
+       char *command;
+       int success, type, screen_flag;
+       int enable_compression_after_reply = 0;
+       u_int proto_len, data_len, dlen, compression_level = 0;
+
+       s = session_new();
+       if (s == NULL) {
+               error("no more sessions");
+               return;
+       }
+       s->authctxt = authctxt;
+       s->pw = authctxt->pw;
+
+       /*
+        * We stay in this loop until the client requests to execute a shell
+        * or a command.
+        */
+       for (;;) {
+               success = 0;
+
+               /* Get a packet from the client. */
+               type = packet_read();
+
+               /* Process the packet. */
+               switch (type) {
+               case SSH_CMSG_REQUEST_COMPRESSION:
+                       compression_level = packet_get_int();
+                       packet_check_eom();
+                       if (compression_level < 1 || compression_level > 9) {
+                               packet_send_debug("Received invalid compression level %d.",
+                                   compression_level);
+                               break;
+                       }
+                       if (options.compression == COMP_NONE) {
+                               debug2("compression disabled");
+                               break;
+                       }
+                       /* Enable compression after we have responded with SUCCESS. */
+                       enable_compression_after_reply = 1;
+                       success = 1;
+                       break;
+
+               case SSH_CMSG_REQUEST_PTY:
+                       success = session_pty_req(s);
+                       break;
+
+               case SSH_CMSG_X11_REQUEST_FORWARDING:
+                       s->auth_proto = packet_get_string(&proto_len);
+                       s->auth_data = packet_get_string(&data_len);
+
+                       screen_flag = packet_get_protocol_flags() &
+                           SSH_PROTOFLAG_SCREEN_NUMBER;
+                       debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
+
+                       if (packet_remaining() == 4) {
+                               if (!screen_flag)
+                                       debug2("Buggy client: "
+                                           "X11 screen flag missing");
+                               s->screen = packet_get_int();
+                       } else {
+                               s->screen = 0;
+                       }
+                       packet_check_eom();
+                       success = session_setup_x11fwd(s);
+                       if (!success) {
+                               xfree(s->auth_proto);
+                               xfree(s->auth_data);
+                               s->auth_proto = NULL;
+                               s->auth_data = NULL;
+                       }
+                       break;
+
+               case SSH_CMSG_AGENT_REQUEST_FORWARDING:
+                       if (!options.allow_agent_forwarding ||
+                           no_agent_forwarding_flag || compat13) {
+                               debug("Authentication agent forwarding not permitted for this authentication.");
+                               break;
+                       }
+                       debug("Received authentication agent forwarding request.");
+                       success = auth_input_request_forwarding(s->pw);
+                       break;
+
+               case SSH_CMSG_PORT_FORWARD_REQUEST:
+                       if (no_port_forwarding_flag) {
+                               debug("Port forwarding not permitted for this authentication.");
+                               break;
+                       }
+                       if (!options.allow_tcp_forwarding) {
+                               debug("Port forwarding not permitted.");
+                               break;
+                       }
+                       debug("Received TCP/IP port forwarding request.");
+                       if (channel_input_port_forward_request(s->pw->pw_uid == 0,
+                           options.gateway_ports) < 0) {
+                               debug("Port forwarding failed.");
+                               break;
+                       }
+                       success = 1;
+                       break;
+
+               case SSH_CMSG_MAX_PACKET_SIZE:
+                       if (packet_set_maxsize(packet_get_int()) > 0)
+                               success = 1;
+                       break;
+
+               case SSH_CMSG_EXEC_SHELL:
+               case SSH_CMSG_EXEC_CMD:
+                       if (type == SSH_CMSG_EXEC_CMD) {
+                               command = packet_get_string(&dlen);
+                               debug("Exec command '%.500s'", command);
+                               if (do_exec(s, command) != 0)
+                                       packet_disconnect(
+                                           "command execution failed");
+                               xfree(command);
+                       } else {
+                               if (do_exec(s, NULL) != 0)
+                                       packet_disconnect(
+                                           "shell execution failed");
+                       }
+                       packet_check_eom();
+                       session_close(s);
+                       return;
+
+               default:
+                       /*
+                        * Any unknown messages in this phase are ignored,
+                        * and a failure message is returned.
+                        */
+                       logit("Unknown packet type received after authentication: %d", type);
+               }
+               packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
+               packet_send();
+               packet_write_wait();
+
+               /* Enable compression now that we have replied if appropriate. */
+               if (enable_compression_after_reply) {
+                       enable_compression_after_reply = 0;
+                       packet_start_compression(compression_level);
+               }
+       }
+}
+
+#define USE_PIPES
+/*
+ * This is called to fork and execute a command when we have no tty.  This
+ * will call do_child from the child, and server_loop from the parent after
+ * setting up file descriptors and such.
+ */
+int
+do_exec_no_pty(Session *s, const char *command)
+{
+       pid_t pid;
+
+#ifdef USE_PIPES
+       int pin[2], pout[2], perr[2];
+
+       if (s == NULL)
+               fatal("do_exec_no_pty: no session");
+
+       /* Allocate pipes for communicating with the program. */
+       if (pipe(pin) < 0) {
+               error("%s: pipe in: %.100s", __func__, strerror(errno));
+               return -1;
+       }
+       if (pipe(pout) < 0) {
+               error("%s: pipe out: %.100s", __func__, strerror(errno));
+               close(pin[0]);
+               close(pin[1]);
+               return -1;
+       }
+       if (pipe(perr) < 0) {
+               error("%s: pipe err: %.100s", __func__,
+                   strerror(errno));
+               close(pin[0]);
+               close(pin[1]);
+               close(pout[0]);
+               close(pout[1]);
+               return -1;
+       }
+#else
+       int inout[2], err[2];
+
+       if (s == NULL)
+               fatal("do_exec_no_pty: no session");
+
+       /* Uses socket pairs to communicate with the program. */
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
+               error("%s: socketpair #1: %.100s", __func__, strerror(errno));
+               return -1;
+       }
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
+               error("%s: socketpair #2: %.100s", __func__,
+                   strerror(errno));
+               close(inout[0]);
+               close(inout[1]);
+               return -1;
+       }
+#endif
+
+       session_proctitle(s);
+
+       /* Fork the child. */
+       switch ((pid = fork())) {
+       case -1:
+               error("%s: fork: %.100s", __func__, strerror(errno));
+#ifdef USE_PIPES
+               close(pin[0]);
+               close(pin[1]);
+               close(pout[0]);
+               close(pout[1]);
+               close(perr[0]);
+               close(perr[1]);
+#else
+               close(inout[0]);
+               close(inout[1]);
+               close(err[0]);
+               close(err[1]);
+#endif
+               return -1;
+       case 0:
+               is_child = 1;
+
+               /* Child.  Reinitialize the log since the pid has changed. */
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
+
+               /*
+                * Create a new session and process group since the 4.4BSD
+                * setlogin() affects the entire process group.
+                */
+               if (setsid() < 0)
+                       error("setsid failed: %.100s", strerror(errno));
+
+#ifdef USE_PIPES
+               /*
+                * Redirect stdin.  We close the parent side of the socket
+                * pair, and make the child side the standard input.
+                */
+               close(pin[1]);
+               if (dup2(pin[0], 0) < 0)
+                       perror("dup2 stdin");
+               close(pin[0]);
+
+               /* Redirect stdout. */
+               close(pout[0]);
+               if (dup2(pout[1], 1) < 0)
+                       perror("dup2 stdout");
+               close(pout[1]);
+
+               /* Redirect stderr. */
+               close(perr[0]);
+               if (dup2(perr[1], 2) < 0)
+                       perror("dup2 stderr");
+               close(perr[1]);
+#else
+               /*
+                * Redirect stdin, stdout, and stderr.  Stdin and stdout will
+                * use the same socket, as some programs (particularly rdist)
+                * seem to depend on it.
+                */
+               close(inout[1]);
+               close(err[1]);
+               if (dup2(inout[0], 0) < 0)      /* stdin */
+                       perror("dup2 stdin");
+               if (dup2(inout[0], 1) < 0)      /* stdout (same as stdin) */
+                       perror("dup2 stdout");
+               close(inout[0]);
+               if (dup2(err[0], 2) < 0)        /* stderr */
+                       perror("dup2 stderr");
+               close(err[0]);
+#endif
+
+
+#ifdef _UNICOS
+               cray_init_job(s->pw); /* set up cray jid and tmpdir */
+#endif
+
+               /* Do processing for the child (exec command etc). */
+               do_child(s, command);
+               /* NOTREACHED */
+       default:
+               break;
+       }
+
+#ifdef _UNICOS
+       signal(WJSIGNAL, cray_job_termination_handler);
+#endif /* _UNICOS */
+#ifdef HAVE_CYGWIN
+       cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
+#endif
+
+       s->pid = pid;
+       /* Set interactive/non-interactive mode. */
+       packet_set_interactive(s->display != NULL,
+           options.ip_qos_interactive, options.ip_qos_bulk);
+
+       /*
+        * Clear loginmsg, since it's the child's responsibility to display
+        * it to the user, otherwise multiple sessions may accumulate
+        * multiple copies of the login messages.
+        */
+       buffer_clear(&loginmsg);
+
+#ifdef USE_PIPES
+       /* We are the parent.  Close the child sides of the pipes. */
+       close(pin[0]);
+       close(pout[1]);
+       close(perr[1]);
+
+       if (compat20) {
+               session_set_fds(s, pin[1], pout[0], perr[0],
+                   s->is_subsystem, 0);
+       } else {
+               /* Enter the interactive session. */
+               server_loop(pid, pin[1], pout[0], perr[0]);
+               /* server_loop has closed pin[1], pout[0], and perr[0]. */
+       }
+#else
+       /* We are the parent.  Close the child sides of the socket pairs. */
+       close(inout[0]);
+       close(err[0]);
+
+       /*
+        * Enter the interactive session.  Note: server_loop must be able to
+        * handle the case that fdin and fdout are the same.
+        */
+       if (compat20) {
+               session_set_fds(s, inout[1], inout[1], err[1],
+                   s->is_subsystem, 0);
+       } else {
+               server_loop(pid, inout[1], inout[1], err[1]);
+               /* server_loop has closed inout[1] and err[1]. */
+       }
+#endif
+       return 0;
+}
+
+/*
+ * This is called to fork and execute a command when we have a tty.  This
+ * will call do_child from the child, and server_loop from the parent after
+ * setting up file descriptors, controlling tty, updating wtmp, utmp,
+ * lastlog, and other such operations.
+ */
+int
+do_exec_pty(Session *s, const char *command)
+{
+       int fdout, ptyfd, ttyfd, ptymaster;
+       pid_t pid;
+
+       if (s == NULL)
+               fatal("do_exec_pty: no session");
+       ptyfd = s->ptyfd;
+       ttyfd = s->ttyfd;
+
+       /*
+        * Create another descriptor of the pty master side for use as the
+        * standard input.  We could use the original descriptor, but this
+        * simplifies code in server_loop.  The descriptor is bidirectional.
+        * Do this before forking (and cleanup in the child) so as to
+        * detect and gracefully fail out-of-fd conditions.
+        */
+       if ((fdout = dup(ptyfd)) < 0) {
+               error("%s: dup #1: %s", __func__, strerror(errno));
+               close(ttyfd);
+               close(ptyfd);
+               return -1;
+       }
+       /* we keep a reference to the pty master */
+       if ((ptymaster = dup(ptyfd)) < 0) {
+               error("%s: dup #2: %s", __func__, strerror(errno));
+               close(ttyfd);
+               close(ptyfd);
+               close(fdout);
+               return -1;
+       }
+
+       /* Fork the child. */
+       switch ((pid = fork())) {
+       case -1:
+               error("%s: fork: %.100s", __func__, strerror(errno));
+               close(fdout);
+               close(ptymaster);
+               close(ttyfd);
+               close(ptyfd);
+               return -1;
+       case 0:
+               is_child = 1;
+
+               close(fdout);
+               close(ptymaster);
+
+               /* Child.  Reinitialize the log because the pid has changed. */
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
+               /* Close the master side of the pseudo tty. */
+               close(ptyfd);
+
+               /* Make the pseudo tty our controlling tty. */
+               pty_make_controlling_tty(&ttyfd, s->tty);
+
+               /* Redirect stdin/stdout/stderr from the pseudo tty. */
+               if (dup2(ttyfd, 0) < 0)
+                       error("dup2 stdin: %s", strerror(errno));
+               if (dup2(ttyfd, 1) < 0)
+                       error("dup2 stdout: %s", strerror(errno));
+               if (dup2(ttyfd, 2) < 0)
+                       error("dup2 stderr: %s", strerror(errno));
+
+               /* Close the extra descriptor for the pseudo tty. */
+               close(ttyfd);
+
+               /* record login, etc. similar to login(1) */
+#ifndef HAVE_OSF_SIA
+               if (!(options.use_login && command == NULL)) {
+#ifdef _UNICOS
+                       cray_init_job(s->pw); /* set up cray jid and tmpdir */
+#endif /* _UNICOS */
+                       do_login(s, command);
+               }
+# ifdef LOGIN_NEEDS_UTMPX
+               else
+                       do_pre_login(s);
+# endif
+#endif
+               /*
+                * Do common processing for the child, such as execing
+                * the command.
+                */
+               do_child(s, command);
+               /* NOTREACHED */
+       default:
+               break;
+       }
+
+#ifdef _UNICOS
+       signal(WJSIGNAL, cray_job_termination_handler);
+#endif /* _UNICOS */
+#ifdef HAVE_CYGWIN
+       cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
+#endif
+
+       s->pid = pid;
+
+       /* Parent.  Close the slave side of the pseudo tty. */
+       close(ttyfd);
+
+       /* Enter interactive session. */
+       s->ptymaster = ptymaster;
+       packet_set_interactive(1, 
+           options.ip_qos_interactive, options.ip_qos_bulk);
+       if (compat20) {
+               session_set_fds(s, ptyfd, fdout, -1, 1, 1);
+       } else {
+               server_loop(pid, ptyfd, fdout, -1);
+               /* server_loop _has_ closed ptyfd and fdout. */
+       }
+       return 0;
+}
+
+#ifdef LOGIN_NEEDS_UTMPX
+static void
+do_pre_login(Session *s)
+{
+       socklen_t fromlen;
+       struct sockaddr_storage from;
+       pid_t pid = getpid();
+
+       /*
+        * Get IP address of client. If the connection is not a socket, let
+        * the address be 0.0.0.0.
+        */
+       memset(&from, 0, sizeof(from));
+       fromlen = sizeof(from);
+       if (packet_connection_is_on_socket()) {
+               if (getpeername(packet_get_connection_in(),
+                   (struct sockaddr *)&from, &fromlen) < 0) {
+                       debug("getpeername: %.100s", strerror(errno));
+                       cleanup_exit(255);
+               }
+       }
+
+       record_utmp_only(pid, s->tty, s->pw->pw_name,
+           get_remote_name_or_ip(utmp_len, options.use_dns),
+           (struct sockaddr *)&from, fromlen);
+}
+#endif
+
+/*
+ * This is called to fork and execute a command.  If another command is
+ * to be forced, execute that instead.
+ */
+int
+do_exec(Session *s, const char *command)
+{
+       int ret;
+
+       if (options.adm_forced_command) {
+               original_command = command;
+               command = options.adm_forced_command;
+               if (IS_INTERNAL_SFTP(command)) {
+                       s->is_subsystem = s->is_subsystem ?
+                           SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
+               } else if (s->is_subsystem)
+                       s->is_subsystem = SUBSYSTEM_EXT;
+               debug("Forced command (config) '%.900s'", command);
+       } else if (forced_command) {
+               original_command = command;
+               command = forced_command;
+               if (IS_INTERNAL_SFTP(command)) {
+                       s->is_subsystem = s->is_subsystem ?
+                           SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
+               } else if (s->is_subsystem)
+                       s->is_subsystem = SUBSYSTEM_EXT;
+               debug("Forced command (key option) '%.900s'", command);
+       }
+
+#ifdef SSH_AUDIT_EVENTS
+       if (command != NULL)
+               PRIVSEP(audit_run_command(command));
+       else if (s->ttyfd == -1) {
+               char *shell = s->pw->pw_shell;
+
+               if (shell[0] == '\0')   /* empty shell means /bin/sh */
+                       shell =_PATH_BSHELL;
+               PRIVSEP(audit_run_command(shell));
+       }
+#endif
+       if (s->ttyfd != -1)
+               ret = do_exec_pty(s, command);
+       else
+               ret = do_exec_no_pty(s, command);
+
+       original_command = NULL;
+
+       /*
+        * Clear loginmsg: it's the child's responsibility to display
+        * it to the user, otherwise multiple sessions may accumulate
+        * multiple copies of the login messages.
+        */
+       buffer_clear(&loginmsg);
+
+       return ret;
+}
+
+/* administrative, login(1)-like work */
+void
+do_login(Session *s, const char *command)
+{
+       socklen_t fromlen;
+       struct sockaddr_storage from;
+       struct passwd * pw = s->pw;
+       pid_t pid = getpid();
+
+       /*
+        * Get IP address of client. If the connection is not a socket, let
+        * the address be 0.0.0.0.
+        */
+       memset(&from, 0, sizeof(from));
+       fromlen = sizeof(from);
+       if (packet_connection_is_on_socket()) {
+               if (getpeername(packet_get_connection_in(),
+                   (struct sockaddr *)&from, &fromlen) < 0) {
+                       debug("getpeername: %.100s", strerror(errno));
+                       cleanup_exit(255);
+               }
+       }
+
+       /* Record that there was a login on that tty from the remote host. */
+       if (!use_privsep)
+               record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
+                   get_remote_name_or_ip(utmp_len,
+                   options.use_dns),
+                   (struct sockaddr *)&from, fromlen);
+
+#ifdef USE_PAM
+       /*
+        * If password change is needed, do it now.
+        * This needs to occur before the ~/.hushlogin check.
+        */
+       if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {
+               display_loginmsg();
+               do_pam_chauthtok();
+               s->authctxt->force_pwchange = 0;
+               /* XXX - signal [net] parent to enable forwardings */
+       }
+#endif
+
+       if (check_quietlogin(s, command))
+               return;
+
+       display_loginmsg();
+
+       do_motd();
+}
+
+/*
+ * Display the message of the day.
+ */
+void
+do_motd(void)
+{
+       FILE *f;
+       char buf[256];
+
+       if (options.print_motd) {
+#ifdef HAVE_LOGIN_CAP
+               f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
+                   "/etc/motd"), "r");
+#else
+               f = fopen("/etc/motd", "r");
+#endif
+               if (f) {
+                       while (fgets(buf, sizeof(buf), f))
+                               fputs(buf, stdout);
+                       fclose(f);
+               }
+       }
+}
+
+
+/*
+ * Check for quiet login, either .hushlogin or command given.
+ */
+int
+check_quietlogin(Session *s, const char *command)
+{
+       char buf[256];
+       struct passwd *pw = s->pw;
+       struct stat st;
+
+       /* Return 1 if .hushlogin exists or a command given. */
+       if (command != NULL)
+               return 1;
+       snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
+#ifdef HAVE_LOGIN_CAP
+       if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
+               return 1;
+#else
+       if (stat(buf, &st) >= 0)
+               return 1;
+#endif
+       return 0;
+}
+
+/*
+ * Sets the value of the given variable in the environment.  If the variable
+ * already exists, its value is overridden.
+ */
+void
+child_set_env(char ***envp, u_int *envsizep, const char *name,
+       const char *value)
+{
+       char **env;
+       u_int envsize;
+       u_int i, namelen;
+
+       /*
+        * If we're passed an uninitialized list, allocate a single null
+        * entry before continuing.
+        */
+       if (*envp == NULL && *envsizep == 0) {
+               *envp = xmalloc(sizeof(char *));
+               *envp[0] = NULL;
+               *envsizep = 1;
+       }
+
+       /*
+        * Find the slot where the value should be stored.  If the variable
+        * already exists, we reuse the slot; otherwise we append a new slot
+        * at the end of the array, expanding if necessary.
+        */
+       env = *envp;
+       namelen = strlen(name);
+       for (i = 0; env[i]; i++)
+               if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
+                       break;
+       if (env[i]) {
+               /* Reuse the slot. */
+               xfree(env[i]);
+       } else {
+               /* New variable.  Expand if necessary. */
+               envsize = *envsizep;
+               if (i >= envsize - 1) {
+                       if (envsize >= 1000)
+                               fatal("child_set_env: too many env vars");
+                       envsize += 50;
+                       env = (*envp) = xrealloc(env, envsize, sizeof(char *));
+                       *envsizep = envsize;
+               }
+               /* Need to set the NULL pointer at end of array beyond the new slot. */
+               env[i + 1] = NULL;
+       }
+
+       /* Allocate space and format the variable in the appropriate slot. */
+       env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
+       snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
+}
+
+/*
+ * Reads environment variables from the given file and adds/overrides them
+ * into the environment.  If the file does not exist, this does nothing.
+ * Otherwise, it must consist of empty lines, comments (line starts with '#')
+ * and assignments of the form name=value.  No other forms are allowed.
+ */
+static void
+read_environment_file(char ***env, u_int *envsize,
+       const char *filename)
+{
+       FILE *f;
+       char buf[4096];
+       char *cp, *value;
+       u_int lineno = 0;
+
+       f = fopen(filename, "r");
+       if (!f)
+               return;
+
+       while (fgets(buf, sizeof(buf), f)) {
+               if (++lineno > 1000)
+                       fatal("Too many lines in environment file %s", filename);
+               for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               if (!*cp || *cp == '#' || *cp == '\n')
+                       continue;
+
+               cp[strcspn(cp, "\n")] = '\0';
+
+               value = strchr(cp, '=');
+               if (value == NULL) {
+                       fprintf(stderr, "Bad line %u in %.100s\n", lineno,
+                           filename);
+                       continue;
+               }
+               /*
+                * Replace the equals sign by nul, and advance value to
+                * the value string.
+                */
+               *value = '\0';
+               value++;
+               child_set_env(env, envsize, cp, value);
+       }
+       fclose(f);
+}
+
+#ifdef HAVE_ETC_DEFAULT_LOGIN
+/*
+ * Return named variable from specified environment, or NULL if not present.
+ */
+static char *
+child_get_env(char **env, const char *name)
+{
+       int i;
+       size_t len;
+
+       len = strlen(name);
+       for (i=0; env[i] != NULL; i++)
+               if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')
+                       return(env[i] + len + 1);
+       return NULL;
+}
+
+/*
+ * Read /etc/default/login.
+ * We pick up the PATH (or SUPATH for root) and UMASK.
+ */
+static void
+read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
+{
+       char **tmpenv = NULL, *var;
+       u_int i, tmpenvsize = 0;
+       u_long mask;
+
+       /*
+        * We don't want to copy the whole file to the child's environment,
+        * so we use a temporary environment and copy the variables we're
+        * interested in.
+        */
+       read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");
+
+       if (tmpenv == NULL)
+               return;
+
+       if (uid == 0)
+               var = child_get_env(tmpenv, "SUPATH");
+       else
+               var = child_get_env(tmpenv, "PATH");
+       if (var != NULL)
+               child_set_env(env, envsize, "PATH", var);
+
+       if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
+               if (sscanf(var, "%5lo", &mask) == 1)
+                       umask((mode_t)mask);
+
+       for (i = 0; tmpenv[i] != NULL; i++)
+               xfree(tmpenv[i]);
+       xfree(tmpenv);
+}
+#endif /* HAVE_ETC_DEFAULT_LOGIN */
+
+void
+copy_environment(char **source, char ***env, u_int *envsize)
+{
+       char *var_name, *var_val;
+       int i;
+
+       if (source == NULL)
+               return;
+
+       for(i = 0; source[i] != NULL; i++) {
+               var_name = xstrdup(source[i]);
+               if ((var_val = strstr(var_name, "=")) == NULL) {
+                       xfree(var_name);
+                       continue;
+               }
+               *var_val++ = '\0';
+
+               debug3("Copy environment: %s=%s", var_name, var_val);
+               child_set_env(env, envsize, var_name, var_val);
+
+               xfree(var_name);
+       }
+}
+
+static char **
+do_setup_env(Session *s, const char *shell)
+{
+       char buf[256];
+       u_int i, envsize;
+       char **env, *laddr;
+       struct passwd *pw = s->pw;
+#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
+       char *path = NULL;
+#endif
+
+       /* Initialize the environment. */
+       envsize = 100;
+       env = xcalloc(envsize, sizeof(char *));
+       env[0] = NULL;
+
+#ifdef HAVE_CYGWIN
+       /*
+        * The Windows environment contains some setting which are
+        * important for a running system. They must not be dropped.
+        */
+       {
+               char **p;
+
+               p = fetch_windows_environment();
+               copy_environment(p, &env, &envsize);
+               free_windows_environment(p);
+       }
+#endif
+
+#ifdef GSSAPI
+       /* Allow any GSSAPI methods that we've used to alter
+        * the childs environment as they see fit
+        */
+       ssh_gssapi_do_child(&env, &envsize);
+#endif
+
+       if (!options.use_login) {
+               /* Set basic environment. */
+               for (i = 0; i < s->num_env; i++)
+                       child_set_env(&env, &envsize, s->env[i].name,
+                           s->env[i].val);
+
+               child_set_env(&env, &envsize, "USER", pw->pw_name);
+               child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
+#ifdef _AIX
+               child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
+#endif
+               child_set_env(&env, &envsize, "HOME", pw->pw_dir);
+#ifdef HAVE_LOGIN_CAP
+               if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
+                       child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
+               else
+                       child_set_env(&env, &envsize, "PATH", getenv("PATH"));
+#else /* HAVE_LOGIN_CAP */
+# ifndef HAVE_CYGWIN
+               /*
+                * There's no standard path on Windows. The path contains
+                * important components pointing to the system directories,
+                * needed for loading shared libraries. So the path better
+                * remains intact here.
+                */
+#  ifdef HAVE_ETC_DEFAULT_LOGIN
+               read_etc_default_login(&env, &envsize, pw->pw_uid);
+               path = child_get_env(env, "PATH");
+#  endif /* HAVE_ETC_DEFAULT_LOGIN */
+               if (path == NULL || *path == '\0') {
+                       child_set_env(&env, &envsize, "PATH",
+                           s->pw->pw_uid == 0 ?
+                               SUPERUSER_PATH : _PATH_STDPATH);
+               }
+# endif /* HAVE_CYGWIN */
+#endif /* HAVE_LOGIN_CAP */
+
+               snprintf(buf, sizeof buf, "%.200s/%.50s",
+                        _PATH_MAILDIR, pw->pw_name);
+               child_set_env(&env, &envsize, "MAIL", buf);
+
+               /* Normal systems set SHELL by default. */
+               child_set_env(&env, &envsize, "SHELL", shell);
+       }
+       if (getenv("TZ"))
+               child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+
+       /* Set custom environment options from RSA authentication. */
+       if (!options.use_login) {
+               while (custom_environment) {
+                       struct envstring *ce = custom_environment;
+                       char *str = ce->s;
+
+                       for (i = 0; str[i] != '=' && str[i]; i++)
+                               ;
+                       if (str[i] == '=') {
+                               str[i] = 0;
+                               child_set_env(&env, &envsize, str, str + i + 1);
+                       }
+                       custom_environment = ce->next;
+                       xfree(ce->s);
+                       xfree(ce);
+               }
+       }
+
+       /* SSH_CLIENT deprecated */
+       snprintf(buf, sizeof buf, "%.50s %d %d",
+           get_remote_ipaddr(), get_remote_port(), get_local_port());
+       child_set_env(&env, &envsize, "SSH_CLIENT", buf);
+
+       laddr = get_local_ipaddr(packet_get_connection_in());
+       snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
+           get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
+       xfree(laddr);
+       child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
+
+       if (s->ttyfd != -1)
+               child_set_env(&env, &envsize, "SSH_TTY", s->tty);
+       if (s->term)
+               child_set_env(&env, &envsize, "TERM", s->term);
+       if (s->display)
+               child_set_env(&env, &envsize, "DISPLAY", s->display);
+       if (original_command)
+               child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
+                   original_command);
+
+#ifdef _UNICOS
+       if (cray_tmpdir[0] != '\0')
+               child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
+#endif /* _UNICOS */
+
+       /*
+        * Since we clear KRB5CCNAME at startup, if it's set now then it
+        * must have been set by a native authentication method (eg AIX or
+        * SIA), so copy it to the child.
+        */
+       {
+               char *cp;
+
+               if ((cp = getenv("KRB5CCNAME")) != NULL)
+                       child_set_env(&env, &envsize, "KRB5CCNAME", cp);
+       }
+
+#ifdef _AIX
+       {
+               char *cp;
+
+               if ((cp = getenv("AUTHSTATE")) != NULL)
+                       child_set_env(&env, &envsize, "AUTHSTATE", cp);
+               read_environment_file(&env, &envsize, "/etc/environment");
+       }
+#endif
+#ifdef KRB5
+       if (s->authctxt->krb5_ccname)
+               child_set_env(&env, &envsize, "KRB5CCNAME",
+                   s->authctxt->krb5_ccname);
+#endif
+#ifdef USE_PAM
+       /*
+        * Pull in any environment variables that may have
+        * been set by PAM.
+        */
+       if (options.use_pam) {
+               char **p;
+
+               p = fetch_pam_child_environment();
+               copy_environment(p, &env, &envsize);
+               free_pam_environment(p);
+
+               p = fetch_pam_environment();
+               copy_environment(p, &env, &envsize);
+               free_pam_environment(p);
+       }
+#endif /* USE_PAM */
+
+       if (auth_sock_name != NULL)
+               child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
+                   auth_sock_name);
+
+       /* read $HOME/.ssh/environment. */
+       if (options.permit_user_env && !options.use_login) {
+               snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
+                   strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
+               read_environment_file(&env, &envsize, buf);
+       }
+       if (debug_flag) {
+               /* dump the environment */
+               fprintf(stderr, "Environment:\n");
+               for (i = 0; env[i]; i++)
+                       fprintf(stderr, "  %.200s\n", env[i]);
+       }
+       return env;
+}
+
+/*
+ * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
+ * first in this order).
+ */
+static void
+do_rc_files(Session *s, const char *shell)
+{
+       FILE *f = NULL;
+       char cmd[1024];
+       int do_xauth;
+       struct stat st;
+
+       do_xauth =
+           s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
+
+       /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
+       if (!s->is_subsystem && options.adm_forced_command == NULL &&
+           !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) {
+               snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
+                   shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
+               if (debug_flag)
+                       fprintf(stderr, "Running %s\n", cmd);
+               f = popen(cmd, "w");
+               if (f) {
+                       if (do_xauth)
+                               fprintf(f, "%s %s\n", s->auth_proto,
+                                   s->auth_data);
+                       pclose(f);
+               } else
+                       fprintf(stderr, "Could not run %s\n",
+                           _PATH_SSH_USER_RC);
+       } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
+               if (debug_flag)
+                       fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
+                           _PATH_SSH_SYSTEM_RC);
+               f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
+               if (f) {
+                       if (do_xauth)
+                               fprintf(f, "%s %s\n", s->auth_proto,
+                                   s->auth_data);
+                       pclose(f);
+               } else
+                       fprintf(stderr, "Could not run %s\n",
+                           _PATH_SSH_SYSTEM_RC);
+       } else if (do_xauth && options.xauth_location != NULL) {
+               /* Add authority data to .Xauthority if appropriate. */
+               if (debug_flag) {
+                       fprintf(stderr,
+                           "Running %.500s remove %.100s\n",
+                           options.xauth_location, s->auth_display);
+                       fprintf(stderr,
+                           "%.500s add %.100s %.100s %.100s\n",
+                           options.xauth_location, s->auth_display,
+                           s->auth_proto, s->auth_data);
+               }
+               snprintf(cmd, sizeof cmd, "%s -q -",
+                   options.xauth_location);
+               f = popen(cmd, "w");
+               if (f) {
+                       fprintf(f, "remove %s\n",
+                           s->auth_display);
+                       fprintf(f, "add %s %s %s\n",
+                           s->auth_display, s->auth_proto,
+                           s->auth_data);
+                       pclose(f);
+               } else {
+                       fprintf(stderr, "Could not run %s\n",
+                           cmd);
+               }
+       }
+}
+
+static void
+do_nologin(struct passwd *pw)
+{
+       FILE *f = NULL;
+       char buf[1024], *nl, *def_nl = _PATH_NOLOGIN;
+       struct stat sb;
+
+#ifdef HAVE_LOGIN_CAP
+       if (login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
+               return;
+       nl = login_getcapstr(lc, "nologin", def_nl, def_nl);
+#else
+       if (pw->pw_uid == 0)
+               return;
+       nl = def_nl;
+#endif
+       if (stat(nl, &sb) == -1) {
+               if (nl != def_nl)
+                       xfree(nl);
+               return;
+       }
+
+       /* /etc/nologin exists.  Print its contents if we can and exit. */
+       logit("User %.100s not allowed because %s exists", pw->pw_name, nl);
+       if ((f = fopen(nl, "r")) != NULL) {
+               while (fgets(buf, sizeof(buf), f))
+                       fputs(buf, stderr);
+               fclose(f);
+       }
+       exit(254);
+}
+
+/*
+ * Chroot into a directory after checking it for safety: all path components
+ * must be root-owned directories with strict permissions.
+ */
+static void
+safely_chroot(const char *path, uid_t uid)
+{
+       const char *cp;
+       char component[MAXPATHLEN];
+       struct stat st;
+
+       if (*path != '/')
+               fatal("chroot path does not begin at root");
+       if (strlen(path) >= sizeof(component))
+               fatal("chroot path too long");
+
+       /*
+        * Descend the path, checking that each component is a
+        * root-owned directory with strict permissions.
+        */
+       for (cp = path; cp != NULL;) {
+               if ((cp = strchr(cp, '/')) == NULL)
+                       strlcpy(component, path, sizeof(component));
+               else {
+                       cp++;
+                       memcpy(component, path, cp - path);
+                       component[cp - path] = '\0';
+               }
+       
+               debug3("%s: checking '%s'", __func__, component);
+
+               if (stat(component, &st) != 0)
+                       fatal("%s: stat(\"%s\"): %s", __func__,
+                           component, strerror(errno));
+               if (st.st_uid != 0 || (st.st_mode & 022) != 0)
+                       fatal("bad ownership or modes for chroot "
+                           "directory %s\"%s\"", 
+                           cp == NULL ? "" : "component ", component);
+               if (!S_ISDIR(st.st_mode))
+                       fatal("chroot path %s\"%s\" is not a directory",
+                           cp == NULL ? "" : "component ", component);
+
+       }
+
+       if (chdir(path) == -1)
+               fatal("Unable to chdir to chroot path \"%s\": "
+                   "%s", path, strerror(errno));
+       if (chroot(path) == -1)
+               fatal("chroot(\"%s\"): %s", path, strerror(errno));
+       if (chdir("/") == -1)
+               fatal("%s: chdir(/) after chroot: %s",
+                   __func__, strerror(errno));
+       verbose("Changed root directory to \"%s\"", path);
+}
+
+/* Set login name, uid, gid, and groups. */
+void
+do_setusercontext(struct passwd *pw)
+{
+       char *chroot_path, *tmp;
+
+       platform_setusercontext(pw);
+
+       if (platform_privileged_uidswap()) {
+#ifdef HAVE_LOGIN_CAP
+               if (setusercontext(lc, pw, pw->pw_uid,
+                   (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
+                       perror("unable to set user context");
+                       exit(1);
+               }
+#else
+               if (setlogin(pw->pw_name) < 0)
+                       error("setlogin failed: %s", strerror(errno));
+               if (setgid(pw->pw_gid) < 0) {
+                       perror("setgid");
+                       exit(1);
+               }
+               /* Initialize the group list. */
+               if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
+                       perror("initgroups");
+                       exit(1);
+               }
+               endgrent();
+#endif
+
+               platform_setusercontext_post_groups(pw);
+
+               if (options.chroot_directory != NULL &&
+                   strcasecmp(options.chroot_directory, "none") != 0) {
+                        tmp = tilde_expand_filename(options.chroot_directory,
+                           pw->pw_uid);
+                       chroot_path = percent_expand(tmp, "h", pw->pw_dir,
+                           "u", pw->pw_name, (char *)NULL);
+                       safely_chroot(chroot_path, pw->pw_uid);
+                       free(tmp);
+                       free(chroot_path);
+               }
+
+#ifdef HAVE_LOGIN_CAP
+               if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
+                       perror("unable to set user context (setuser)");
+                       exit(1);
+               }
+#else
+               /* Permanently switch to the desired uid. */
+               permanently_set_uid(pw);
+#endif
+       }
+
+       if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
+               fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
+}
+
+static void
+do_pwchange(Session *s)
+{
+       fflush(NULL);
+       fprintf(stderr, "WARNING: Your password has expired.\n");
+       if (s->ttyfd != -1) {
+               fprintf(stderr,
+                   "You must change your password now and login again!\n");
+#ifdef WITH_SELINUX
+               setexeccon(NULL);
+#endif
+#ifdef PASSWD_NEEDS_USERNAME
+               execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
+                   (char *)NULL);
+#else
+               execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
+#endif
+               perror("passwd");
+       } else {
+               fprintf(stderr,
+                   "Password change required but no TTY available.\n");
+       }
+       exit(1);
+}
+
+static void
+launch_login(struct passwd *pw, const char *hostname)
+{
+       /* Launch login(1). */
+
+       execl(LOGIN_PROGRAM, "login", "-h", hostname,
+#ifdef xxxLOGIN_NEEDS_TERM
+                   (s->term ? s->term : "unknown"),
+#endif /* LOGIN_NEEDS_TERM */
+#ifdef LOGIN_NO_ENDOPT
+           "-p", "-f", pw->pw_name, (char *)NULL);
+#else
+           "-p", "-f", "--", pw->pw_name, (char *)NULL);
+#endif
+
+       /* Login couldn't be executed, die. */
+
+       perror("login");
+       exit(1);
+}
+
+static void
+child_close_fds(void)
+{
+       if (packet_get_connection_in() == packet_get_connection_out())
+               close(packet_get_connection_in());
+       else {
+               close(packet_get_connection_in());
+               close(packet_get_connection_out());
+       }
+       /*
+        * Close all descriptors related to channels.  They will still remain
+        * open in the parent.
+        */
+       /* XXX better use close-on-exec? -markus */
+       channel_close_all();
+
+       /*
+        * Close any extra file descriptors.  Note that there may still be
+        * descriptors left by system functions.  They will be closed later.
+        */
+       endpwent();
+
+       /*
+        * Close any extra open file descriptors so that we don't have them
+        * hanging around in clients.  Note that we want to do this after
+        * initgroups, because at least on Solaris 2.3 it leaves file
+        * descriptors open.
+        */
+       closefrom(STDERR_FILENO + 1);
+}
+
+/*
+ * Performs common processing for the child, such as setting up the
+ * environment, closing extra file descriptors, setting the user and group
+ * ids, and executing the command or shell.
+ */
+#define ARGV_MAX 10
+void
+do_child(Session *s, const char *command)
+{
+       extern char **environ;
+       char **env;
+       char *argv[ARGV_MAX];
+       const char *shell, *shell0, *hostname = NULL;
+       struct passwd *pw = s->pw;
+       int r = 0;
+
+       /* remove hostkey from the child's memory */
+       destroy_sensitive_data();
+
+       /* Force a password change */
+       if (s->authctxt->force_pwchange) {
+               do_setusercontext(pw);
+               child_close_fds();
+               do_pwchange(s);
+               exit(1);
+       }
+
+       /* login(1) is only called if we execute the login shell */
+       if (options.use_login && command != NULL)
+               options.use_login = 0;
+
+#ifdef _UNICOS
+       cray_setup(pw->pw_uid, pw->pw_name, command);
+#endif /* _UNICOS */
+
+       /*
+        * Login(1) does this as well, and it needs uid 0 for the "-h"
+        * switch, so we let login(1) to this for us.
+        */
+       if (!options.use_login) {
+#ifdef HAVE_OSF_SIA
+               session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
+               if (!check_quietlogin(s, command))
+                       do_motd();
+#else /* HAVE_OSF_SIA */
+               /* When PAM is enabled we rely on it to do the nologin check */
+               if (!options.use_pam)
+                       do_nologin(pw);
+               do_setusercontext(pw);
+               /*
+                * PAM session modules in do_setusercontext may have
+                * generated messages, so if this in an interactive
+                * login then display them too.
+                */
+               if (!check_quietlogin(s, command))
+                       display_loginmsg();
+#endif /* HAVE_OSF_SIA */
+       }
+
+#ifdef USE_PAM
+       if (options.use_pam && !options.use_login && !is_pam_session_open()) {
+               debug3("PAM session not opened, exiting");
+               display_loginmsg();
+               exit(254);
+       }
+#endif
+
+       /*
+        * Get the shell from the password data.  An empty shell field is
+        * legal, and means /bin/sh.
+        */
+       shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
+
+       /*
+        * Make sure $SHELL points to the shell from the password file,
+        * even if shell is overridden from login.conf
+        */
+       env = do_setup_env(s, shell);
+
+#ifdef HAVE_LOGIN_CAP
+       shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
+#endif
+
+       /* we have to stash the hostname before we close our socket. */
+       if (options.use_login)
+               hostname = get_remote_name_or_ip(utmp_len,
+                   options.use_dns);
+       /*
+        * Close the connection descriptors; note that this is the child, and
+        * the server will still have the socket open, and it is important
+        * that we do not shutdown it.  Note that the descriptors cannot be
+        * closed before building the environment, as we call
+        * get_remote_ipaddr there.
+        */
+       child_close_fds();
+
+       /*
+        * Must take new environment into use so that .ssh/rc,
+        * /etc/ssh/sshrc and xauth are run in the proper environment.
+        */
+       environ = env;
+
+#if defined(KRB5) && defined(USE_AFS)
+       /*
+        * At this point, we check to see if AFS is active and if we have
+        * a valid Kerberos 5 TGT. If so, it seems like a good idea to see
+        * if we can (and need to) extend the ticket into an AFS token. If
+        * we don't do this, we run into potential problems if the user's
+        * home directory is in AFS and it's not world-readable.
+        */
+
+       if (options.kerberos_get_afs_token && k_hasafs() &&
+           (s->authctxt->krb5_ctx != NULL)) {
+               char cell[64];
+
+               debug("Getting AFS token");
+
+               k_setpag();
+
+               if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
+                       krb5_afslog(s->authctxt->krb5_ctx,
+                           s->authctxt->krb5_fwd_ccache, cell, NULL);
+
+               krb5_afslog_home(s->authctxt->krb5_ctx,
+                   s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir);
+       }
+#endif
+
+       /* Change current directory to the user's home directory. */
+       if (chdir(pw->pw_dir) < 0) {
+               /* Suppress missing homedir warning for chroot case */
+#ifdef HAVE_LOGIN_CAP
+               r = login_getcapbool(lc, "requirehome", 0);
+#endif
+               if (r || options.chroot_directory == NULL ||
+                   strcasecmp(options.chroot_directory, "none") == 0)
+                       fprintf(stderr, "Could not chdir to home "
+                           "directory %s: %s\n", pw->pw_dir,
+                           strerror(errno));
+               if (r)
+                       exit(1);
+       }
+
+       closefrom(STDERR_FILENO + 1);
+
+       if (!options.use_login)
+               do_rc_files(s, shell);
+
+       /* restore SIGPIPE for child */
+       signal(SIGPIPE, SIG_DFL);
+
+       if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {
+               printf("This service allows sftp connections only.\n");
+               fflush(NULL);
+               exit(1);
+       } else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
+               extern int optind, optreset;
+               int i;
+               char *p, *args;
+
+               setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME);
+               args = xstrdup(command ? command : "sftp-server");
+               for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
+                       if (i < ARGV_MAX - 1)
+                               argv[i++] = p;
+               argv[i] = NULL;
+               optind = optreset = 1;
+               __progname = argv[0];
+#ifdef WITH_SELINUX
+               ssh_selinux_change_context("sftpd_t");
+#endif
+               exit(sftp_server_main(i, argv, s->pw));
+       }
+
+       fflush(NULL);
+
+       if (options.use_login) {
+               launch_login(pw, hostname);
+               /* NEVERREACHED */
+       }
+
+       /* Get the last component of the shell name. */
+       if ((shell0 = strrchr(shell, '/')) != NULL)
+               shell0++;
+       else
+               shell0 = shell;
+
+       /*
+        * If we have no command, execute the shell.  In this case, the shell
+        * name to be passed in argv[0] is preceded by '-' to indicate that
+        * this is a login shell.
+        */
+       if (!command) {
+               char argv0[256];
+
+               /* Start the shell.  Set initial character to '-'. */
+               argv0[0] = '-';
+
+               if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1)
+                   >= sizeof(argv0) - 1) {
+                       errno = EINVAL;
+                       perror(shell);
+                       exit(1);
+               }
+
+               /* Execute the shell. */
+               argv[0] = argv0;
+               argv[1] = NULL;
+               execve(shell, argv, env);
+
+               /* Executing the shell failed. */
+               perror(shell);
+               exit(1);
+       }
+       /*
+        * Execute the command using the user's shell.  This uses the -c
+        * option to execute the command.
+        */
+       argv[0] = (char *) shell0;
+       argv[1] = "-c";
+       argv[2] = (char *) command;
+       argv[3] = NULL;
+       execve(shell, argv, env);
+       perror(shell);
+       exit(1);
+}
+
+void
+session_unused(int id)
+{
+       debug3("%s: session id %d unused", __func__, id);
+       if (id >= options.max_sessions ||
+           id >= sessions_nalloc) {
+               fatal("%s: insane session id %d (max %d nalloc %d)",
+                   __func__, id, options.max_sessions, sessions_nalloc);
+       }
+       bzero(&sessions[id], sizeof(*sessions));
+       sessions[id].self = id;
+       sessions[id].used = 0;
+       sessions[id].chanid = -1;
+       sessions[id].ptyfd = -1;
+       sessions[id].ttyfd = -1;
+       sessions[id].ptymaster = -1;
+       sessions[id].x11_chanids = NULL;
+       sessions[id].next_unused = sessions_first_unused;
+       sessions_first_unused = id;
+}
+
+Session *
+session_new(void)
+{
+       Session *s, *tmp;
+
+       if (sessions_first_unused == -1) {
+               if (sessions_nalloc >= options.max_sessions)
+                       return NULL;
+               debug2("%s: allocate (allocated %d max %d)",
+                   __func__, sessions_nalloc, options.max_sessions);
+               tmp = xrealloc(sessions, sessions_nalloc + 1,
+                   sizeof(*sessions));
+               if (tmp == NULL) {
+                       error("%s: cannot allocate %d sessions",
+                           __func__, sessions_nalloc + 1);
+                       return NULL;
+               }
+               sessions = tmp;
+               session_unused(sessions_nalloc++);
+       }
+
+       if (sessions_first_unused >= sessions_nalloc ||
+           sessions_first_unused < 0) {
+               fatal("%s: insane first_unused %d max %d nalloc %d",
+                   __func__, sessions_first_unused, options.max_sessions,
+                   sessions_nalloc);
+       }
+
+       s = &sessions[sessions_first_unused];
+       if (s->used) {
+               fatal("%s: session %d already used",
+                   __func__, sessions_first_unused);
+       }
+       sessions_first_unused = s->next_unused;
+       s->used = 1;
+       s->next_unused = -1;
+       debug("session_new: session %d", s->self);
+
+       return s;
+}
+
+static void
+session_dump(void)
+{
+       int i;
+       for (i = 0; i < sessions_nalloc; i++) {
+               Session *s = &sessions[i];
+
+               debug("dump: used %d next_unused %d session %d %p "
+                   "channel %d pid %ld",
+                   s->used,
+                   s->next_unused,
+                   s->self,
+                   s,
+                   s->chanid,
+                   (long)s->pid);
+       }
+}
+
+int
+session_open(Authctxt *authctxt, int chanid)
+{
+       Session *s = session_new();
+       debug("session_open: channel %d", chanid);
+       if (s == NULL) {
+               error("no more sessions");
+               return 0;
+       }
+       s->authctxt = authctxt;
+       s->pw = authctxt->pw;
+       if (s->pw == NULL || !authctxt->valid)
+               fatal("no user for session %d", s->self);
+       debug("session_open: session %d: link with channel %d", s->self, chanid);
+       s->chanid = chanid;
+       return 1;
+}
+
+Session *
+session_by_tty(char *tty)
+{
+       int i;
+       for (i = 0; i < sessions_nalloc; i++) {
+               Session *s = &sessions[i];
+               if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
+                       debug("session_by_tty: session %d tty %s", i, tty);
+                       return s;
+               }
+       }
+       debug("session_by_tty: unknown tty %.100s", tty);
+       session_dump();
+       return NULL;
+}
+
+static Session *
+session_by_channel(int id)
+{
+       int i;
+       for (i = 0; i < sessions_nalloc; i++) {
+               Session *s = &sessions[i];
+               if (s->used && s->chanid == id) {
+                       debug("session_by_channel: session %d channel %d",
+                           i, id);
+                       return s;
+               }
+       }
+       debug("session_by_channel: unknown channel %d", id);
+       session_dump();
+       return NULL;
+}
+
+static Session *
+session_by_x11_channel(int id)
+{
+       int i, j;
+
+       for (i = 0; i < sessions_nalloc; i++) {
+               Session *s = &sessions[i];
+
+               if (s->x11_chanids == NULL || !s->used)
+                       continue;
+               for (j = 0; s->x11_chanids[j] != -1; j++) {
+                       if (s->x11_chanids[j] == id) {
+                               debug("session_by_x11_channel: session %d "
+                                   "channel %d", s->self, id);
+                               return s;
+                       }
+               }
+       }
+       debug("session_by_x11_channel: unknown channel %d", id);
+       session_dump();
+       return NULL;
+}
+
+static Session *
+session_by_pid(pid_t pid)
+{
+       int i;
+       debug("session_by_pid: pid %ld", (long)pid);
+       for (i = 0; i < sessions_nalloc; i++) {
+               Session *s = &sessions[i];
+               if (s->used && s->pid == pid)
+                       return s;
+       }
+       error("session_by_pid: unknown pid %ld", (long)pid);
+       session_dump();
+       return NULL;
+}
+
+static int
+session_window_change_req(Session *s)
+{
+       s->col = packet_get_int();
+       s->row = packet_get_int();
+       s->xpixel = packet_get_int();
+       s->ypixel = packet_get_int();
+       packet_check_eom();
+       pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
+       return 1;
+}
+
+static int
+session_pty_req(Session *s)
+{
+       u_int len;
+       int n_bytes;
+
+       if (no_pty_flag) {
+               debug("Allocating a pty not permitted for this authentication.");
+               return 0;
+       }
+       if (s->ttyfd != -1) {
+               packet_disconnect("Protocol error: you already have a pty.");
+               return 0;
+       }
+
+       s->term = packet_get_string(&len);
+
+       if (compat20) {
+               s->col = packet_get_int();
+               s->row = packet_get_int();
+       } else {
+               s->row = packet_get_int();
+               s->col = packet_get_int();
+       }
+       s->xpixel = packet_get_int();
+       s->ypixel = packet_get_int();
+
+       if (strcmp(s->term, "") == 0) {
+               xfree(s->term);
+               s->term = NULL;
+       }
+
+       /* Allocate a pty and open it. */
+       debug("Allocating pty.");
+       if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
+           sizeof(s->tty)))) {
+               if (s->term)
+                       xfree(s->term);
+               s->term = NULL;
+               s->ptyfd = -1;
+               s->ttyfd = -1;
+               error("session_pty_req: session %d alloc failed", s->self);
+               return 0;
+       }
+       debug("session_pty_req: session %d alloc %s", s->self, s->tty);
+
+       /* for SSH1 the tty modes length is not given */
+       if (!compat20)
+               n_bytes = packet_remaining();
+       tty_parse_modes(s->ttyfd, &n_bytes);
+
+       if (!use_privsep)
+               pty_setowner(s->pw, s->tty);
+
+       /* Set window size from the packet. */
+       pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
+
+       packet_check_eom();
+       session_proctitle(s);
+       return 1;
+}
+
+static int
+session_subsystem_req(Session *s)
+{
+       struct stat st;
+       u_int len;
+       int success = 0;
+       char *prog, *cmd, *subsys = packet_get_string(&len);
+       u_int i;
+
+       packet_check_eom();
+       logit("subsystem request for %.100s by user %s", subsys,
+           s->pw->pw_name);
+
+       for (i = 0; i < options.num_subsystems; i++) {
+               if (strcmp(subsys, options.subsystem_name[i]) == 0) {
+                       prog = options.subsystem_command[i];
+                       cmd = options.subsystem_args[i];
+                       if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) {
+                               s->is_subsystem = SUBSYSTEM_INT_SFTP;
+                               debug("subsystem: %s", prog);
+                       } else {
+                               if (stat(prog, &st) < 0)
+                                       debug("subsystem: cannot stat %s: %s",
+                                           prog, strerror(errno));
+                               s->is_subsystem = SUBSYSTEM_EXT;
+                               debug("subsystem: exec() %s", cmd);
+                       }
+                       success = do_exec(s, cmd) == 0;
+                       break;
+               }
+       }
+
+       if (!success)
+               logit("subsystem request for %.100s failed, subsystem not found",
+                   subsys);
+
+       xfree(subsys);
+       return success;
+}
+
+static int
+session_x11_req(Session *s)
+{
+       int success;
+
+       if (s->auth_proto != NULL || s->auth_data != NULL) {
+               error("session_x11_req: session %d: "
+                   "x11 forwarding already active", s->self);
+               return 0;
+       }
+       s->single_connection = packet_get_char();
+       s->auth_proto = packet_get_string(NULL);
+       s->auth_data = packet_get_string(NULL);
+       s->screen = packet_get_int();
+       packet_check_eom();
+
+       success = session_setup_x11fwd(s);
+       if (!success) {
+               xfree(s->auth_proto);
+               xfree(s->auth_data);
+               s->auth_proto = NULL;
+               s->auth_data = NULL;
+       }
+       return success;
+}
+
+static int
+session_shell_req(Session *s)
+{
+       packet_check_eom();
+       return do_exec(s, NULL) == 0;
+}
+
+static int
+session_exec_req(Session *s)
+{
+       u_int len, success;
+
+       char *command = packet_get_string(&len);
+       packet_check_eom();
+       success = do_exec(s, command) == 0;
+       xfree(command);
+       return success;
+}
+
+static int
+session_break_req(Session *s)
+{
+
+       packet_get_int();       /* ignored */
+       packet_check_eom();
+
+       if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0)
+               return 0;
+       return 1;
+}
+
+static int
+session_env_req(Session *s)
+{
+       char *name, *val;
+       u_int name_len, val_len, i;
+
+       name = packet_get_string(&name_len);
+       val = packet_get_string(&val_len);
+       packet_check_eom();
+
+       /* Don't set too many environment variables */
+       if (s->num_env > 128) {
+               debug2("Ignoring env request %s: too many env vars", name);
+               goto fail;
+       }
+
+       for (i = 0; i < options.num_accept_env; i++) {
+               if (match_pattern(name, options.accept_env[i])) {
+                       debug2("Setting env %d: %s=%s", s->num_env, name, val);
+                       s->env = xrealloc(s->env, s->num_env + 1,
+                           sizeof(*s->env));
+                       s->env[s->num_env].name = name;
+                       s->env[s->num_env].val = val;
+                       s->num_env++;
+                       return (1);
+               }
+       }
+       debug2("Ignoring env request %s: disallowed name", name);
+
+ fail:
+       xfree(name);
+       xfree(val);
+       return (0);
+}
+
+static int
+session_auth_agent_req(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");
+               return 0;
+       }
+       if (called) {
+               return 0;
+       } else {
+               called = 1;
+               return auth_input_request_forwarding(s->pw);
+       }
+}
+
+int
+session_input_channel_req(Channel *c, const char *rtype)
+{
+       int success = 0;
+       Session *s;
+
+       if ((s = session_by_channel(c->self)) == NULL) {
+               logit("session_input_channel_req: no session %d req %.100s",
+                   c->self, rtype);
+               return 0;
+       }
+       debug("session_input_channel_req: session %d req %s", s->self, rtype);
+
+       /*
+        * a session is in LARVAL state until a shell, a command
+        * or a subsystem is executed
+        */
+       if (c->type == SSH_CHANNEL_LARVAL) {
+               if (strcmp(rtype, "shell") == 0) {
+                       success = session_shell_req(s);
+               } else if (strcmp(rtype, "exec") == 0) {
+                       success = session_exec_req(s);
+               } else if (strcmp(rtype, "pty-req") == 0) {
+                       success = session_pty_req(s);
+               } else if (strcmp(rtype, "x11-req") == 0) {
+                       success = session_x11_req(s);
+               } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
+                       success = session_auth_agent_req(s);
+               } else if (strcmp(rtype, "subsystem") == 0) {
+                       success = session_subsystem_req(s);
+               } else if (strcmp(rtype, "env") == 0) {
+                       success = session_env_req(s);
+               }
+       }
+       if (strcmp(rtype, "window-change") == 0) {
+               success = session_window_change_req(s);
+       } else if (strcmp(rtype, "break") == 0) {
+               success = session_break_req(s);
+       }
+
+       return success;
+}
+
+void
+session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr,
+    int is_tty)
+{
+       if (!compat20)
+               fatal("session_set_fds: called for proto != 2.0");
+       /*
+        * now that have a child and a pipe to the child,
+        * we can activate our channel and register the fd's
+        */
+       if (s->chanid == -1)
+               fatal("no channel for session %d", s->self);
+       channel_set_fds(s->chanid,
+           fdout, fdin, fderr,
+           ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+           1, is_tty, CHAN_SES_WINDOW_DEFAULT);
+}
+
+/*
+ * Function to perform pty cleanup. Also called if we get aborted abnormally
+ * (e.g., due to a dropped connection).
+ */
+void
+session_pty_cleanup2(Session *s)
+{
+       if (s == NULL) {
+               error("session_pty_cleanup: no session");
+               return;
+       }
+       if (s->ttyfd == -1)
+               return;
+
+       debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
+
+       /* Record that the user has logged out. */
+       if (s->pid != 0)
+               record_logout(s->pid, s->tty, s->pw->pw_name);
+
+       /* Release the pseudo-tty. */
+       if (getuid() == 0)
+               pty_release(s->tty);
+
+       /*
+        * Close the server side of the socket pairs.  We must do this after
+        * the pty cleanup, so that another process doesn't get this pty
+        * while we're still cleaning up.
+        */
+       if (s->ptymaster != -1 && close(s->ptymaster) < 0)
+               error("close(s->ptymaster/%d): %s",
+                   s->ptymaster, strerror(errno));
+
+       /* unlink pty from session */
+       s->ttyfd = -1;
+}
+
+void
+session_pty_cleanup(Session *s)
+{
+       PRIVSEP(session_pty_cleanup2(s));
+}
+
+static char *
+sig2name(int sig)
+{
+#define SSH_SIG(x) if (sig == SIG ## x) return #x
+       SSH_SIG(ABRT);
+       SSH_SIG(ALRM);
+       SSH_SIG(FPE);
+       SSH_SIG(HUP);
+       SSH_SIG(ILL);
+       SSH_SIG(INT);
+       SSH_SIG(KILL);
+       SSH_SIG(PIPE);
+       SSH_SIG(QUIT);
+       SSH_SIG(SEGV);
+       SSH_SIG(TERM);
+       SSH_SIG(USR1);
+       SSH_SIG(USR2);
+#undef SSH_SIG
+       return "SIG@openssh.com";
+}
+
+static void
+session_close_x11(int id)
+{
+       Channel *c;
+
+       if ((c = channel_by_id(id)) == NULL) {
+               debug("session_close_x11: x11 channel %d missing", id);
+       } else {
+               /* Detach X11 listener */
+               debug("session_close_x11: detach x11 channel %d", id);
+               channel_cancel_cleanup(id);
+               if (c->ostate != CHAN_OUTPUT_CLOSED)
+                       chan_mark_dead(c);
+       }
+}
+
+static void
+session_close_single_x11(int id, void *arg)
+{
+       Session *s;
+       u_int i;
+
+       debug3("session_close_single_x11: channel %d", id);
+       channel_cancel_cleanup(id);
+       if ((s = session_by_x11_channel(id)) == NULL)
+               fatal("session_close_single_x11: no x11 channel %d", id);
+       for (i = 0; s->x11_chanids[i] != -1; i++) {
+               debug("session_close_single_x11: session %d: "
+                   "closing channel %d", s->self, s->x11_chanids[i]);
+               /*
+                * The channel "id" is already closing, but make sure we
+                * close all of its siblings.
+                */
+               if (s->x11_chanids[i] != id)
+                       session_close_x11(s->x11_chanids[i]);
+       }
+       xfree(s->x11_chanids);
+       s->x11_chanids = NULL;
+       if (s->display) {
+               xfree(s->display);
+               s->display = NULL;
+       }
+       if (s->auth_proto) {
+               xfree(s->auth_proto);
+               s->auth_proto = NULL;
+       }
+       if (s->auth_data) {
+               xfree(s->auth_data);
+               s->auth_data = NULL;
+       }
+       if (s->auth_display) {
+               xfree(s->auth_display);
+               s->auth_display = NULL;
+       }
+}
+
+static void
+session_exit_message(Session *s, int status)
+{
+       Channel *c;
+
+       if ((c = channel_lookup(s->chanid)) == NULL)
+               fatal("session_exit_message: session %d: no channel %d",
+                   s->self, s->chanid);
+       debug("session_exit_message: session %d channel %d pid %ld",
+           s->self, s->chanid, (long)s->pid);
+
+       if (WIFEXITED(status)) {
+               channel_request_start(s->chanid, "exit-status", 0);
+               packet_put_int(WEXITSTATUS(status));
+               packet_send();
+       } else if (WIFSIGNALED(status)) {
+               channel_request_start(s->chanid, "exit-signal", 0);
+               packet_put_cstring(sig2name(WTERMSIG(status)));
+#ifdef WCOREDUMP
+               packet_put_char(WCOREDUMP(status)? 1 : 0);
+#else /* WCOREDUMP */
+               packet_put_char(0);
+#endif /* WCOREDUMP */
+               packet_put_cstring("");
+               packet_put_cstring("");
+               packet_send();
+       } else {
+               /* Some weird exit cause.  Just exit. */
+               packet_disconnect("wait returned status %04x.", status);
+       }
+
+       /* disconnect channel */
+       debug("session_exit_message: release channel %d", s->chanid);
+
+       /*
+        * Adjust cleanup callback attachment to send close messages when
+        * the channel gets EOF. The session will be then be closed
+        * by session_close_by_channel when the childs close their fds.
+        */
+       channel_register_cleanup(c->self, session_close_by_channel, 1);
+
+       /*
+        * emulate a write failure with 'chan_write_failed', nobody will be
+        * interested in data we write.
+        * Note that we must not call 'chan_read_failed', since there could
+        * be some more data waiting in the pipe.
+        */
+       if (c->ostate != CHAN_OUTPUT_CLOSED)
+               chan_write_failed(c);
+}
+
+void
+session_close(Session *s)
+{
+       u_int i;
+
+       debug("session_close: session %d pid %ld", s->self, (long)s->pid);
+       if (s->ttyfd != -1)
+               session_pty_cleanup(s);
+       if (s->term)
+               xfree(s->term);
+       if (s->display)
+               xfree(s->display);
+       if (s->x11_chanids)
+               xfree(s->x11_chanids);
+       if (s->auth_display)
+               xfree(s->auth_display);
+       if (s->auth_data)
+               xfree(s->auth_data);
+       if (s->auth_proto)
+               xfree(s->auth_proto);
+       if (s->env != NULL) {
+               for (i = 0; i < s->num_env; i++) {
+                       xfree(s->env[i].name);
+                       xfree(s->env[i].val);
+               }
+               xfree(s->env);
+       }
+       session_proctitle(s);
+       session_unused(s->self);
+}
+
+void
+session_close_by_pid(pid_t pid, int status)
+{
+       Session *s = session_by_pid(pid);
+       if (s == NULL) {
+               debug("session_close_by_pid: no session for pid %ld",
+                   (long)pid);
+               return;
+       }
+       if (s->chanid != -1)
+               session_exit_message(s, status);
+       if (s->ttyfd != -1)
+               session_pty_cleanup(s);
+       s->pid = 0;
+}
+
+/*
+ * this is called when a channel dies before
+ * the session 'child' itself dies
+ */
+void
+session_close_by_channel(int id, void *arg)
+{
+       Session *s = session_by_channel(id);
+       u_int i;
+
+       if (s == NULL) {
+               debug("session_close_by_channel: no session for id %d", id);
+               return;
+       }
+       debug("session_close_by_channel: channel %d child %ld",
+           id, (long)s->pid);
+       if (s->pid != 0) {
+               debug("session_close_by_channel: channel %d: has child", id);
+               /*
+                * delay detach of session, but release pty, since
+                * the fd's to the child are already closed
+                */
+               if (s->ttyfd != -1)
+                       session_pty_cleanup(s);
+               return;
+       }
+       /* detach by removing callback */
+       channel_cancel_cleanup(s->chanid);
+
+       /* Close any X11 listeners associated with this session */
+       if (s->x11_chanids != NULL) {
+               for (i = 0; s->x11_chanids[i] != -1; i++) {
+                       session_close_x11(s->x11_chanids[i]);
+                       s->x11_chanids[i] = -1;
+               }
+       }
+
+       s->chanid = -1;
+       session_close(s);
+}
+
+void
+session_destroy_all(void (*closefunc)(Session *))
+{
+       int i;
+       for (i = 0; i < sessions_nalloc; i++) {
+               Session *s = &sessions[i];
+               if (s->used) {
+                       if (closefunc != NULL)
+                               closefunc(s);
+                       else
+                               session_close(s);
+               }
+       }
+}
+
+static char *
+session_tty_list(void)
+{
+       static char buf[1024];
+       int i;
+       char *cp;
+
+       buf[0] = '\0';
+       for (i = 0; i < sessions_nalloc; i++) {
+               Session *s = &sessions[i];
+               if (s->used && s->ttyfd != -1) {
+
+                       if (strncmp(s->tty, "/dev/", 5) != 0) {
+                               cp = strrchr(s->tty, '/');
+                               cp = (cp == NULL) ? s->tty : cp + 1;
+                       } else
+                               cp = s->tty + 5;
+
+                       if (buf[0] != '\0')
+                               strlcat(buf, ",", sizeof buf);
+                       strlcat(buf, cp, sizeof buf);
+               }
+       }
+       if (buf[0] == '\0')
+               strlcpy(buf, "notty", sizeof buf);
+       return buf;
+}
+
+void
+session_proctitle(Session *s)
+{
+       if (s->pw == NULL)
+               error("no user for session %d", s->self);
+       else
+               setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
+}
+
+int
+session_setup_x11fwd(Session *s)
+{
+       struct stat st;
+       char display[512], auth_display[512];
+       char hostname[MAXHOSTNAMELEN];
+       u_int i;
+
+       if (no_x11_forwarding_flag) {
+               packet_send_debug("X11 forwarding disabled in user configuration file.");
+               return 0;
+       }
+       if (!options.x11_forwarding) {
+               debug("X11 forwarding disabled in server configuration file.");
+               return 0;
+       }
+       if (!options.xauth_location ||
+           (stat(options.xauth_location, &st) == -1)) {
+               packet_send_debug("No xauth program; cannot forward with spoofing.");
+               return 0;
+       }
+       if (options.use_login) {
+               packet_send_debug("X11 forwarding disabled; "
+                   "not compatible with UseLogin=yes.");
+               return 0;
+       }
+       if (s->display != NULL) {
+               debug("X11 display already set.");
+               return 0;
+       }
+       if (x11_create_display_inet(options.x11_display_offset,
+           options.x11_use_localhost, s->single_connection,
+           &s->display_number, &s->x11_chanids) == -1) {
+               debug("x11_create_display_inet failed.");
+               return 0;
+       }
+       for (i = 0; s->x11_chanids[i] != -1; i++) {
+               channel_register_cleanup(s->x11_chanids[i],
+                   session_close_single_x11, 0);
+       }
+
+       /* Set up a suitable value for the DISPLAY variable. */
+       if (gethostname(hostname, sizeof(hostname)) < 0)
+               fatal("gethostname: %.100s", strerror(errno));
+       /*
+        * auth_display must be used as the displayname when the
+        * authorization entry is added with xauth(1).  This will be
+        * different than the DISPLAY string for localhost displays.
+        */
+       if (options.x11_use_localhost) {
+               snprintf(display, sizeof display, "localhost:%u.%u",
+                   s->display_number, s->screen);
+               snprintf(auth_display, sizeof auth_display, "unix:%u.%u",
+                   s->display_number, s->screen);
+               s->display = xstrdup(display);
+               s->auth_display = xstrdup(auth_display);
+       } else {
+#ifdef IPADDR_IN_DISPLAY
+               struct hostent *he;
+               struct in_addr my_addr;
+
+               he = gethostbyname(hostname);
+               if (he == NULL) {
+                       error("Can't get IP address for X11 DISPLAY.");
+                       packet_send_debug("Can't get IP address for X11 DISPLAY.");
+                       return 0;
+               }
+               memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
+               snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr),
+                   s->display_number, s->screen);
+#else
+               snprintf(display, sizeof display, "%.400s:%u.%u", hostname,
+                   s->display_number, s->screen);
+#endif
+               s->display = xstrdup(display);
+               s->auth_display = xstrdup(display);
+       }
+
+       return 1;
+}
+
+static void
+do_authenticated2(Authctxt *authctxt)
+{
+       server_loop2(authctxt);
+}
+
+void
+do_cleanup(Authctxt *authctxt)
+{
+       static int called = 0;
+
+       debug("do_cleanup");
+
+       /* no cleanup if we're in the child for login shell */
+       if (is_child)
+               return;
+
+       /* avoid double cleanup */
+       if (called)
+               return;
+       called = 1;
+
+       if (authctxt == NULL)
+               return;
+
+#ifdef USE_PAM
+       if (options.use_pam) {
+               sshpam_cleanup();
+               sshpam_thread_cleanup();
+       }
+#endif
+
+       if (!authctxt->authenticated)
+               return;
+
+#ifdef KRB5
+       if (options.kerberos_ticket_cleanup &&
+           authctxt->krb5_ctx)
+               krb5_cleanup_proc(authctxt);
+#endif
+
+#ifdef GSSAPI
+       if (compat20 && options.gss_cleanup_creds)
+               ssh_gssapi_cleanup_creds();
+#endif
+
+       /* remove agent socket */
+       auth_sock_cleanup_proc(authctxt->pw);
+
+       /*
+        * Cleanup ptys/utmp only if privsep is disabled,
+        * or if running in monitor.
+        */
+       if (!use_privsep || mm_is_monitor())
+               session_destroy_all(session_pty_cleanup2);
+}
diff --git a/.pc/selinux-role.patch/session.h b/.pc/selinux-role.patch/session.h
new file mode 100644 (file)
index 0000000..cbb8e3a
--- /dev/null
@@ -0,0 +1,83 @@
+/* $OpenBSD: session.h,v 1.30 2008/05/08 12:21:16 djm Exp $ */
+
+/*
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SESSION_H
+#define SESSION_H
+
+#define TTYSZ 64
+typedef struct Session Session;
+struct Session {
+       int     used;
+       int     self;
+       int     next_unused;
+       struct passwd *pw;
+       Authctxt *authctxt;
+       pid_t   pid;
+
+       /* tty */
+       char    *term;
+       int     ptyfd, ttyfd, ptymaster;
+       u_int   row, col, xpixel, ypixel;
+       char    tty[TTYSZ];
+
+       /* X11 */
+       u_int   display_number;
+       char    *display;
+       u_int   screen;
+       char    *auth_display;
+       char    *auth_proto;
+       char    *auth_data;
+       int     single_connection;
+
+       /* proto 2 */
+       int     chanid;
+       int     *x11_chanids;
+       int     is_subsystem;
+       u_int   num_env;
+       struct {
+               char    *name;
+               char    *val;
+       } *env;
+};
+
+void    do_authenticated(Authctxt *);
+void    do_cleanup(Authctxt *);
+
+int     session_open(Authctxt *, int);
+void    session_unused(int);
+int     session_input_channel_req(Channel *, const char *);
+void    session_close_by_pid(pid_t, int);
+void    session_close_by_channel(int, void *);
+void    session_destroy_all(void (*)(Session *));
+void    session_pty_cleanup2(Session *);
+
+Session        *session_new(void);
+Session        *session_by_tty(char *);
+void    session_close(Session *);
+void    do_setusercontext(struct passwd *);
+void    child_set_env(char ***envp, u_int *envsizep, const char *name,
+                      const char *value);
+
+#endif
diff --git a/.pc/selinux-role.patch/sshd.c b/.pc/selinux-role.patch/sshd.c
new file mode 100644 (file)
index 0000000..112a5f9
--- /dev/null
@@ -0,0 +1,2481 @@
+/* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * This program is the ssh daemon.  It listens for connections from clients,
+ * and performs authentication, executes use commands or shell, and forwards
+ * information to/from the application to the user client over an encrypted
+ * connection.  This can also handle forwarding of X11, TCP/IP, and
+ * authentication agent connections.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 implementation:
+ * Privilege Separation:
+ *
+ * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2002 Niels Provos.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include "openbsd-compat/sys-tree.h"
+#include "openbsd-compat/sys-queue.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/md5.h>
+#include <openssl/rand.h>
+#include "openbsd-compat/openssl-compat.h"
+
+#ifdef HAVE_SECUREWARE
+#include <sys/security.h>
+#include <prot.h>
+#endif
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "rsa.h"
+#include "sshpty.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "dh.h"
+#include "myproposal.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "atomicio.h"
+#include "canohost.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "misc.h"
+#include "msg.h"
+#include "dispatch.h"
+#include "channels.h"
+#include "session.h"
+#include "monitor_mm.h"
+#include "monitor.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "roaming.h"
+#include "ssh-sandbox.h"
+#include "version.h"
+
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
+
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int allow_severity;
+int deny_severity;
+#endif /* LIBWRAP */
+
+#ifndef O_NOCTTY
+#define O_NOCTTY       0
+#endif
+
+/* Re-exec fds */
+#define REEXEC_DEVCRYPTO_RESERVED_FD   (STDERR_FILENO + 1)
+#define REEXEC_STARTUP_PIPE_FD         (STDERR_FILENO + 2)
+#define REEXEC_CONFIG_PASS_FD          (STDERR_FILENO + 3)
+#define REEXEC_MIN_FREE_FD             (STDERR_FILENO + 4)
+
+extern char *__progname;
+
+/* Server configuration options. */
+ServerOptions options;
+
+/* Name of the server configuration file. */
+char *config_file_name = _PATH_SERVER_CONFIG_FILE;
+
+/*
+ * Debug mode flag.  This can be set on the command line.  If debug
+ * mode is enabled, extra debugging output will be sent to the system
+ * log, the daemon will not go to background, and will exit after processing
+ * the first connection.
+ */
+int debug_flag = 0;
+
+/* Flag indicating that the daemon should only test the configuration and keys. */
+int test_flag = 0;
+
+/* Flag indicating that the daemon is being started from inetd. */
+int inetd_flag = 0;
+
+/* Flag indicating that sshd should not detach and become a daemon. */
+int no_daemon_flag = 0;
+
+/* debug goes to stderr unless inetd_flag is set */
+int log_stderr = 0;
+
+/* Saved arguments to main(). */
+char **saved_argv;
+int saved_argc;
+
+/* re-exec */
+int rexeced_flag = 0;
+int rexec_flag = 1;
+int rexec_argc = 0;
+char **rexec_argv;
+
+/*
+ * The sockets that the server is listening; this is used in the SIGHUP
+ * signal handler.
+ */
+#define        MAX_LISTEN_SOCKS        16
+int listen_socks[MAX_LISTEN_SOCKS];
+int num_listen_socks = 0;
+
+/*
+ * the client's version string, passed by sshd2 in compat mode. if != NULL,
+ * sshd will skip the version-number exchange
+ */
+char *client_version_string = NULL;
+char *server_version_string = NULL;
+
+/* for rekeying XXX fixme */
+Kex *xxx_kex;
+
+/*
+ * Any really sensitive data in the application is contained in this
+ * structure. The idea is that this structure could be locked into memory so
+ * that the pages do not get written into swap.  However, there are some
+ * problems. The private key contains BIGNUMs, and we do not (in principle)
+ * have access to the internals of them, and locking just the structure is
+ * not very useful.  Currently, memory locking is not implemented.
+ */
+struct {
+       Key     *server_key;            /* ephemeral server key */
+       Key     *ssh1_host_key;         /* ssh1 host key */
+       Key     **host_keys;            /* all private host keys */
+       Key     **host_certificates;    /* all public host certificates */
+       int     have_ssh1_key;
+       int     have_ssh2_key;
+       u_char  ssh1_cookie[SSH_SESSION_KEY_LENGTH];
+} sensitive_data;
+
+/*
+ * Flag indicating whether the RSA server key needs to be regenerated.
+ * Is set in the SIGALRM handler and cleared when the key is regenerated.
+ */
+static volatile sig_atomic_t key_do_regen = 0;
+
+/* This is set to true when a signal is received. */
+static volatile sig_atomic_t received_sighup = 0;
+static volatile sig_atomic_t received_sigterm = 0;
+
+/* session identifier, used by RSA-auth */
+u_char session_id[16];
+
+/* same for ssh2 */
+u_char *session_id2 = NULL;
+u_int session_id2_len = 0;
+
+/* record remote hostname or ip */
+u_int utmp_len = MAXHOSTNAMELEN;
+
+/* options.max_startup sized array of fd ints */
+int *startup_pipes = NULL;
+int startup_pipe;              /* in child */
+
+/* variables used for privilege separation */
+int use_privsep = -1;
+struct monitor *pmonitor = NULL;
+
+/* global authentication context */
+Authctxt *the_authctxt = NULL;
+
+/* sshd_config buffer */
+Buffer cfg;
+
+/* message to be displayed after login */
+Buffer loginmsg;
+
+/* Unprivileged user */
+struct passwd *privsep_pw = NULL;
+
+/* Prototypes for various functions defined later in this file. */
+void destroy_sensitive_data(void);
+void demote_sensitive_data(void);
+
+static void do_ssh1_kex(void);
+static void do_ssh2_kex(void);
+
+/*
+ * Close all listening sockets
+ */
+static void
+close_listen_socks(void)
+{
+       int i;
+
+       for (i = 0; i < num_listen_socks; i++)
+               close(listen_socks[i]);
+       num_listen_socks = -1;
+}
+
+static void
+close_startup_pipes(void)
+{
+       int i;
+
+       if (startup_pipes)
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               close(startup_pipes[i]);
+}
+
+/*
+ * Signal handler for SIGHUP.  Sshd execs itself when it receives SIGHUP;
+ * the effect is to reread the configuration file (and to regenerate
+ * the server key).
+ */
+
+/*ARGSUSED*/
+static void
+sighup_handler(int sig)
+{
+       int save_errno = errno;
+
+       received_sighup = 1;
+       signal(SIGHUP, sighup_handler);
+       errno = save_errno;
+}
+
+/*
+ * Called from the main program after receiving SIGHUP.
+ * Restarts the server.
+ */
+static void
+sighup_restart(void)
+{
+       logit("Received SIGHUP; restarting.");
+       close_listen_socks();
+       close_startup_pipes();
+       alarm(0);  /* alarm timer persists across exec */
+       signal(SIGHUP, SIG_IGN); /* will be restored after exec */
+       execv(saved_argv[0], saved_argv);
+       logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
+           strerror(errno));
+       exit(1);
+}
+
+/*
+ * Generic signal handler for terminating signals in the master daemon.
+ */
+/*ARGSUSED*/
+static void
+sigterm_handler(int sig)
+{
+       received_sigterm = sig;
+}
+
+/*
+ * SIGCHLD handler.  This is called whenever a child dies.  This will then
+ * reap any zombies left by exited children.
+ */
+/*ARGSUSED*/
+static void
+main_sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+           (pid < 0 && errno == EINTR))
+               ;
+
+       signal(SIGCHLD, main_sigchld_handler);
+       errno = save_errno;
+}
+
+/*
+ * Signal handler for the alarm after the login grace period has expired.
+ */
+/*ARGSUSED*/
+static void
+grace_alarm_handler(int sig)
+{
+       if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
+               kill(pmonitor->m_pid, SIGALRM);
+
+       /* Log error and exit. */
+       sigdie("Timeout before authentication for %s", get_remote_ipaddr());
+}
+
+/*
+ * Signal handler for the key regeneration alarm.  Note that this
+ * alarm only occurs in the daemon waiting for connections, and it does not
+ * do anything with the private key or random state before forking.
+ * Thus there should be no concurrency control/asynchronous execution
+ * problems.
+ */
+static void
+generate_ephemeral_server_key(void)
+{
+       verbose("Generating %s%d bit RSA key.",
+           sensitive_data.server_key ? "new " : "", options.server_key_bits);
+       if (sensitive_data.server_key != NULL)
+               key_free(sensitive_data.server_key);
+       sensitive_data.server_key = key_generate(KEY_RSA1,
+           options.server_key_bits);
+       verbose("RSA key generation complete.");
+
+       arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+       arc4random_stir();
+}
+
+/*ARGSUSED*/
+static void
+key_regeneration_alarm(int sig)
+{
+       int save_errno = errno;
+
+       signal(SIGALRM, SIG_DFL);
+       errno = save_errno;
+       key_do_regen = 1;
+}
+
+static void
+sshd_exchange_identification(int sock_in, int sock_out)
+{
+       u_int i;
+       int mismatch;
+       int remote_major, remote_minor;
+       int major, minor;
+       char *s, *newline = "\n";
+       char buf[256];                  /* Must not be larger than remote_version. */
+       char remote_version[256];       /* Must be at least as big as buf. */
+
+       if ((options.protocol & SSH_PROTO_1) &&
+           (options.protocol & SSH_PROTO_2)) {
+               major = PROTOCOL_MAJOR_1;
+               minor = 99;
+       } else if (options.protocol & SSH_PROTO_2) {
+               major = PROTOCOL_MAJOR_2;
+               minor = PROTOCOL_MINOR_2;
+               newline = "\r\n";
+       } else {
+               major = PROTOCOL_MAJOR_1;
+               minor = PROTOCOL_MINOR_1;
+       }
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+           SSH_VERSION, newline);
+       server_version_string = xstrdup(buf);
+
+       /* Send our protocol version identification. */
+       if (roaming_atomicio(vwrite, sock_out, server_version_string,
+           strlen(server_version_string))
+           != strlen(server_version_string)) {
+               logit("Could not write ident string to %s", get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+
+       /* Read other sides version identification. */
+       memset(buf, 0, sizeof(buf));
+       for (i = 0; i < sizeof(buf) - 1; i++) {
+               if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {
+                       logit("Did not receive identification string from %s",
+                           get_remote_ipaddr());
+                       cleanup_exit(255);
+               }
+               if (buf[i] == '\r') {
+                       buf[i] = 0;
+                       /* Kludge for F-Secure Macintosh < 1.0.2 */
+                       if (i == 12 &&
+                           strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
+                               break;
+                       continue;
+               }
+               if (buf[i] == '\n') {
+                       buf[i] = 0;
+                       break;
+               }
+       }
+       buf[sizeof(buf) - 1] = 0;
+       client_version_string = xstrdup(buf);
+
+       /*
+        * Check that the versions match.  In future this might accept
+        * several versions and set appropriate flags to handle them.
+        */
+       if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
+           &remote_major, &remote_minor, remote_version) != 3) {
+               s = "Protocol mismatch.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Bad protocol version identification '%.100s' from %s",
+                   client_version_string, get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+       debug("Client protocol version %d.%d; client software version %.100s",
+           remote_major, remote_minor, remote_version);
+
+       compat_datafellows(remote_version);
+
+       if (datafellows & SSH_BUG_PROBE) {
+               logit("probed from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       if (datafellows & SSH_BUG_SCANNER) {
+               logit("scanned from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       mismatch = 0;
+       switch (remote_major) {
+       case 1:
+               if (remote_minor == 99) {
+                       if (options.protocol & SSH_PROTO_2)
+                               enable_compat20();
+                       else
+                               mismatch = 1;
+                       break;
+               }
+               if (!(options.protocol & SSH_PROTO_1)) {
+                       mismatch = 1;
+                       break;
+               }
+               if (remote_minor < 3) {
+                       packet_disconnect("Your ssh version is too old and "
+                           "is no longer supported.  Please install a newer version.");
+               } else if (remote_minor == 3) {
+                       /* note that this disables agent-forwarding */
+                       enable_compat13();
+               }
+               break;
+       case 2:
+               if (options.protocol & SSH_PROTO_2) {
+                       enable_compat20();
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               mismatch = 1;
+               break;
+       }
+       chop(server_version_string);
+       debug("Local version string %.200s", server_version_string);
+
+       if (mismatch) {
+               s = "Protocol major versions differ.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Protocol major versions differ for %s: %.200s vs. %.200s",
+                   get_remote_ipaddr(),
+                   server_version_string, client_version_string);
+               cleanup_exit(255);
+       }
+}
+
+/* Destroy the host and server keys.  They will no longer be needed. */
+void
+destroy_sensitive_data(void)
+{
+       int i;
+
+       if (sensitive_data.server_key) {
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = NULL;
+       }
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = NULL;
+               }
+               if (sensitive_data.host_certificates[i]) {
+                       key_free(sensitive_data.host_certificates[i]);
+                       sensitive_data.host_certificates[i] = NULL;
+               }
+       }
+       sensitive_data.ssh1_host_key = NULL;
+       memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
+}
+
+/* Demote private to public keys for network child */
+void
+demote_sensitive_data(void)
+{
+       Key *tmp;
+       int i;
+
+       if (sensitive_data.server_key) {
+               tmp = key_demote(sensitive_data.server_key);
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = tmp;
+       }
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       tmp = key_demote(sensitive_data.host_keys[i]);
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = tmp;
+                       if (tmp->type == KEY_RSA1)
+                               sensitive_data.ssh1_host_key = tmp;
+               }
+               /* Certs do not need demotion */
+       }
+
+       /* We do not clear ssh1_host key and cookie.  XXX - Okay Niels? */
+}
+
+static void
+privsep_preauth_child(void)
+{
+       u_int32_t rnd[256];
+       gid_t gidset[1];
+
+       /* Enable challenge-response authentication for privilege separation */
+       privsep_challenge_enable();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       /* Change our root directory */
+       if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+               fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+                   strerror(errno));
+       if (chdir("/") == -1)
+               fatal("chdir(\"/\"): %s", strerror(errno));
+
+       /* Drop our privileges */
+       debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
+           (u_int)privsep_pw->pw_gid);
+#if 0
+       /* XXX not ready, too heavy after chroot */
+       do_setusercontext(privsep_pw);
+#else
+       gidset[0] = privsep_pw->pw_gid;
+       if (setgroups(1, gidset) < 0)
+               fatal("setgroups: %.100s", strerror(errno));
+       permanently_set_uid(privsep_pw);
+#endif
+}
+
+static int
+privsep_preauth(Authctxt *authctxt)
+{
+       int status;
+       pid_t pid;
+       struct ssh_sandbox *box = NULL;
+
+       /* Set up unprivileged child process to deal with network data */
+       pmonitor = monitor_init();
+       /* Store a pointer to the kex for later rekeying */
+       pmonitor->m_pkex = &xxx_kex;
+
+       if (use_privsep == PRIVSEP_SANDBOX)
+               box = ssh_sandbox_init();
+       pid = fork();
+       if (pid == -1) {
+               fatal("fork of unprivileged child failed");
+       } else if (pid != 0) {
+               debug2("Network child is on pid %ld", (long)pid);
+
+               if (box != NULL)
+                       ssh_sandbox_parent_preauth(box, pid);
+               pmonitor->m_pid = pid;
+               monitor_child_preauth(authctxt, pmonitor);
+
+               /* Sync memory */
+               monitor_sync(pmonitor);
+
+               /* Wait for the child's exit status */
+               while (waitpid(pid, &status, 0) < 0) {
+                       if (errno != EINTR)
+                               fatal("%s: waitpid: %s", __func__,
+                                   strerror(errno));
+               }
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status) != 0)
+                               fatal("%s: preauth child exited with status %d",
+                                   __func__, WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status))
+                       fatal("%s: preauth child terminated by signal %d",
+                           __func__, WTERMSIG(status));
+               if (box != NULL)
+                       ssh_sandbox_parent_finish(box);
+               return 1;
+       } else {
+               /* child */
+               close(pmonitor->m_sendfd);
+               close(pmonitor->m_log_recvfd);
+
+               /* Arrange for logging to be sent to the monitor */
+               set_log_handler(mm_log_handler, pmonitor);
+
+               /* Demote the child */
+               if (getuid() == 0 || geteuid() == 0)
+                       privsep_preauth_child();
+               setproctitle("%s", "[net]");
+               if (box != NULL)
+                       ssh_sandbox_child(box);
+
+               return 0;
+       }
+}
+
+static void
+privsep_postauth(Authctxt *authctxt)
+{
+       u_int32_t rnd[256];
+
+#ifdef DISABLE_FD_PASSING
+       if (1) {
+#else
+       if (authctxt->pw->pw_uid == 0 || options.use_login) {
+#endif
+               /* File descriptor passing is broken or root login */
+               use_privsep = 0;
+               goto skip;
+       }
+
+       /* New socket pair */
+       monitor_reinit(pmonitor);
+
+       pmonitor->m_pid = fork();
+       if (pmonitor->m_pid == -1)
+               fatal("fork of unprivileged child failed");
+       else if (pmonitor->m_pid != 0) {
+               verbose("User child is on pid %ld", (long)pmonitor->m_pid);
+               buffer_clear(&loginmsg);
+               monitor_child_postauth(pmonitor);
+
+               /* NEVERREACHED */
+               exit(0);
+       }
+
+       /* child */
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Drop privileges */
+       do_setusercontext(authctxt->pw);
+
+ skip:
+       /* It is safe now to apply the key state */
+       monitor_apply_keystate(pmonitor);
+
+       /*
+        * Tell the packet layer that authentication was successful, since
+        * this information is not part of the key state.
+        */
+       packet_set_authenticated();
+}
+
+static char *
+list_hostkey_types(void)
+{
+       Buffer b;
+       const char *p;
+       char *ret;
+       int i;
+       Key *key;
+
+       buffer_init(&b);
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = sensitive_data.host_keys[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+               /* If the private key has a cert peer, then list that too */
+               key = sensitive_data.host_certificates[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       ret = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       debug("list_hostkey_types: %s", ret);
+       return ret;
+}
+
+static Key *
+get_hostkey_by_type(int type, int need_private)
+{
+       int i;
+       Key *key;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               switch (type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       key = sensitive_data.host_certificates[i];
+                       break;
+               default:
+                       key = sensitive_data.host_keys[i];
+                       break;
+               }
+               if (key != NULL && key->type == type)
+                       return need_private ?
+                           sensitive_data.host_keys[i] : key;
+       }
+       return NULL;
+}
+
+Key *
+get_hostkey_public_by_type(int type)
+{
+       return get_hostkey_by_type(type, 0);
+}
+
+Key *
+get_hostkey_private_by_type(int type)
+{
+       return get_hostkey_by_type(type, 1);
+}
+
+Key *
+get_hostkey_by_index(int ind)
+{
+       if (ind < 0 || ind >= options.num_host_key_files)
+               return (NULL);
+       return (sensitive_data.host_keys[ind]);
+}
+
+int
+get_hostkey_index(Key *key)
+{
+       int i;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (key_is_cert(key)) {
+                       if (key == sensitive_data.host_certificates[i])
+                               return (i);
+               } else {
+                       if (key == sensitive_data.host_keys[i])
+                               return (i);
+               }
+       }
+       return (-1);
+}
+
+/*
+ * returns 1 if connection should be dropped, 0 otherwise.
+ * dropping starts at connection #max_startups_begin with a probability
+ * of (max_startups_rate/100). the probability increases linearly until
+ * all connections are dropped for startups > max_startups
+ */
+static int
+drop_connection(int startups)
+{
+       int p, r;
+
+       if (startups < options.max_startups_begin)
+               return 0;
+       if (startups >= options.max_startups)
+               return 1;
+       if (options.max_startups_rate == 100)
+               return 1;
+
+       p  = 100 - options.max_startups_rate;
+       p *= startups - options.max_startups_begin;
+       p /= options.max_startups - options.max_startups_begin;
+       p += options.max_startups_rate;
+       r = arc4random_uniform(100);
+
+       debug("drop_connection: p %d, r %d", p, r);
+       return (r < p) ? 1 : 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "%s, %s\n",
+           SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+       fprintf(stderr,
+"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
+"            [-f config_file] [-g login_grace_time] [-h host_key_file]\n"
+"            [-k key_gen_time] [-o option] [-p port] [-u len]\n"
+       );
+       exit(1);
+}
+
+static void
+send_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+
+       debug3("%s: entering fd = %d config len %d", __func__, fd,
+           buffer_len(conf));
+
+       /*
+        * Protocol from reexec master to child:
+        *      string  configuration
+        *      u_int   ephemeral_key_follows
+        *      bignum  e               (only if ephemeral_key_follows == 1)
+        *      bignum  n                       "
+        *      bignum  d                       "
+        *      bignum  iqmp                    "
+        *      bignum  p                       "
+        *      bignum  q                       "
+        *      string rngseed          (only if OpenSSL is not self-seeded)
+        */
+       buffer_init(&m);
+       buffer_put_cstring(&m, buffer_ptr(conf));
+
+       if (sensitive_data.server_key != NULL &&
+           sensitive_data.server_key->type == KEY_RSA1) {
+               buffer_put_int(&m, 1);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
+       } else
+               buffer_put_int(&m, 0);
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_send_rng_seed(&m);
+#endif
+
+       if (ssh_msg_send(fd, 0, &m) == -1)
+               fatal("%s: ssh_msg_send failed", __func__);
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+static void
+recv_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+       char *cp;
+       u_int len;
+
+       debug3("%s: entering fd = %d", __func__, fd);
+
+       buffer_init(&m);
+
+       if (ssh_msg_recv(fd, &m) == -1)
+               fatal("%s: ssh_msg_recv failed", __func__);
+       if (buffer_get_char(&m) != 0)
+               fatal("%s: rexec version mismatch", __func__);
+
+       cp = buffer_get_string(&m, &len);
+       if (conf != NULL)
+               buffer_append(conf, cp, len + 1);
+       xfree(cp);
+
+       if (buffer_get_int(&m)) {
+               if (sensitive_data.server_key != NULL)
+                       key_free(sensitive_data.server_key);
+               sensitive_data.server_key = key_new_private(KEY_RSA1);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
+               rsa_generate_additional_parameters(
+                   sensitive_data.server_key->rsa);
+       }
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_recv_rng_seed(&m);
+#endif
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+/* Accept a connection from inetd */
+static void
+server_accept_inetd(int *sock_in, int *sock_out)
+{
+       int fd;
+
+       startup_pipe = -1;
+       if (rexeced_flag) {
+               close(REEXEC_CONFIG_PASS_FD);
+               *sock_in = *sock_out = dup(STDIN_FILENO);
+               if (!debug_flag) {
+                       startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+                       close(REEXEC_STARTUP_PIPE_FD);
+               }
+       } else {
+               *sock_in = dup(STDIN_FILENO);
+               *sock_out = dup(STDOUT_FILENO);
+       }
+       /*
+        * We intentionally do not close the descriptors 0, 1, and 2
+        * as our code for setting the descriptors won't work if
+        * ttyfd happens to be one of those.
+        */
+       if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+               dup2(fd, STDIN_FILENO);
+               dup2(fd, STDOUT_FILENO);
+               if (fd > STDOUT_FILENO)
+                       close(fd);
+       }
+       debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
+}
+
+/*
+ * Listen for TCP connections
+ */
+static void
+server_listen(void)
+{
+       int ret, listen_sock, on = 1;
+       struct addrinfo *ai;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+
+       for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                       continue;
+               if (num_listen_socks >= MAX_LISTEN_SOCKS)
+                       fatal("Too many listen sockets. "
+                           "Enlarge MAX_LISTEN_SOCKS");
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                   ntop, sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           ssh_gai_strerror(ret));
+                       continue;
+               }
+               /* Create socket for listening. */
+               listen_sock = socket(ai->ai_family, ai->ai_socktype,
+                   ai->ai_protocol);
+               if (listen_sock < 0) {
+                       /* kernel may not support ipv6 */
+                       verbose("socket: %.100s", strerror(errno));
+                       continue;
+               }
+               if (set_nonblock(listen_sock) == -1) {
+                       close(listen_sock);
+                       continue;
+               }
+               /*
+                * Set socket options.
+                * Allow local port reuse in TIME_WAIT.
+                */
+               if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
+                   &on, sizeof(on)) == -1)
+                       error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+
+               /* Only communicate in IPv6 over AF_INET6 sockets. */
+               if (ai->ai_family == AF_INET6)
+                       sock_set_v6only(listen_sock);
+
+               debug("Bind to port %s on %s.", strport, ntop);
+
+               /* Bind the socket to the desired port. */
+               if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       error("Bind to port %s on %s failed: %.200s.",
+                           strport, ntop, strerror(errno));
+                       close(listen_sock);
+                       continue;
+               }
+               listen_socks[num_listen_socks] = listen_sock;
+               num_listen_socks++;
+
+               /* Start listening on the port. */
+               if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
+                       fatal("listen on [%s]:%s: %.100s",
+                           ntop, strport, strerror(errno));
+               logit("Server listening on %s port %s.", ntop, strport);
+       }
+       freeaddrinfo(options.listen_addrs);
+
+       if (!num_listen_socks)
+               fatal("Cannot bind any address.");
+}
+
+/*
+ * The main TCP accept loop. Note that, for the non-debug case, returns
+ * from this function are in a forked subprocess.
+ */
+static void
+server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
+{
+       fd_set *fdset;
+       int i, j, ret, maxfd;
+       int key_used = 0, startups = 0;
+       int startup_p[2] = { -1 , -1 };
+       struct sockaddr_storage from;
+       socklen_t fromlen;
+       pid_t pid;
+
+       /* setup fd set for accept */
+       fdset = NULL;
+       maxfd = 0;
+       for (i = 0; i < num_listen_socks; i++)
+               if (listen_socks[i] > maxfd)
+                       maxfd = listen_socks[i];
+       /* pipes connected to unauthenticated childs */
+       startup_pipes = xcalloc(options.max_startups, sizeof(int));
+       for (i = 0; i < options.max_startups; i++)
+               startup_pipes[i] = -1;
+
+       /*
+        * Stay listening for connections until the system crashes or
+        * the daemon is killed with a signal.
+        */
+       for (;;) {
+               if (received_sighup)
+                       sighup_restart();
+               if (fdset != NULL)
+                       xfree(fdset);
+               fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),
+                   sizeof(fd_mask));
+
+               for (i = 0; i < num_listen_socks; i++)
+                       FD_SET(listen_socks[i], fdset);
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               FD_SET(startup_pipes[i], fdset);
+
+               /* Wait in select until there is a connection. */
+               ret = select(maxfd+1, fdset, NULL, NULL, NULL);
+               if (ret < 0 && errno != EINTR)
+                       error("select: %.100s", strerror(errno));
+               if (received_sigterm) {
+                       logit("Received signal %d; terminating.",
+                           (int) received_sigterm);
+                       close_listen_socks();
+                       unlink(options.pid_file);
+                       exit(received_sigterm == SIGTERM ? 0 : 255);
+               }
+               if (key_used && key_do_regen) {
+                       generate_ephemeral_server_key();
+                       key_used = 0;
+                       key_do_regen = 0;
+               }
+               if (ret < 0)
+                       continue;
+
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1 &&
+                           FD_ISSET(startup_pipes[i], fdset)) {
+                               /*
+                                * the read end of the pipe is ready
+                                * if the child has closed the pipe
+                                * after successful authentication
+                                * or if the child has died
+                                */
+                               close(startup_pipes[i]);
+                               startup_pipes[i] = -1;
+                               startups--;
+                       }
+               for (i = 0; i < num_listen_socks; i++) {
+                       if (!FD_ISSET(listen_socks[i], fdset))
+                               continue;
+                       fromlen = sizeof(from);
+                       *newsock = accept(listen_socks[i],
+                           (struct sockaddr *)&from, &fromlen);
+                       if (*newsock < 0) {
+                               if (errno != EINTR && errno != EAGAIN &&
+                                   errno != EWOULDBLOCK)
+                                       error("accept: %.100s", strerror(errno));
+                               continue;
+                       }
+                       if (unset_nonblock(*newsock) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+                       if (drop_connection(startups) == 1) {
+                               debug("drop connection #%d", startups);
+                               close(*newsock);
+                               continue;
+                       }
+                       if (pipe(startup_p) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+
+                       if (rexec_flag && socketpair(AF_UNIX,
+                           SOCK_STREAM, 0, config_s) == -1) {
+                               error("reexec socketpair: %s",
+                                   strerror(errno));
+                               close(*newsock);
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               continue;
+                       }
+
+                       for (j = 0; j < options.max_startups; j++)
+                               if (startup_pipes[j] == -1) {
+                                       startup_pipes[j] = startup_p[0];
+                                       if (maxfd < startup_p[0])
+                                               maxfd = startup_p[0];
+                                       startups++;
+                                       break;
+                               }
+
+                       /*
+                        * Got connection.  Fork a child to handle it, unless
+                        * we are in debugging mode.
+                        */
+                       if (debug_flag) {
+                               /*
+                                * In debugging mode.  Close the listening
+                                * socket, and start processing the
+                                * connection without forking.
+                                */
+                               debug("Server will not fork when running in debugging mode.");
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               startup_pipe = -1;
+                               pid = getpid();
+                               if (rexec_flag) {
+                                       send_rexec_state(config_s[0],
+                                           &cfg);
+                                       close(config_s[0]);
+                               }
+                               break;
+                       }
+
+                       /*
+                        * Normal production daemon.  Fork, and have
+                        * the child process the connection. The
+                        * parent continues listening.
+                        */
+                       platform_pre_fork();
+                       if ((pid = fork()) == 0) {
+                               /*
+                                * Child.  Close the listening and
+                                * max_startup sockets.  Start using
+                                * the accepted socket. Reinitialize
+                                * logging (since our pid has changed).
+                                * We break out of the loop to handle
+                                * the connection.
+                                */
+                               platform_post_fork_child();
+                               startup_pipe = startup_p[1];
+                               close_startup_pipes();
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               log_init(__progname,
+                                   options.log_level,
+                                   options.log_facility,
+                                   log_stderr);
+                               if (rexec_flag)
+                                       close(config_s[0]);
+                               break;
+                       }
+
+                       /* Parent.  Stay in the loop. */
+                       platform_post_fork_parent(pid);
+                       if (pid < 0)
+                               error("fork: %.100s", strerror(errno));
+                       else
+                               debug("Forked child %ld.", (long)pid);
+
+                       close(startup_p[1]);
+
+                       if (rexec_flag) {
+                               send_rexec_state(config_s[0], &cfg);
+                               close(config_s[0]);
+                               close(config_s[1]);
+                       }
+
+                       /*
+                        * Mark that the key has been used (it
+                        * was "given" to the child).
+                        */
+                       if ((options.protocol & SSH_PROTO_1) &&
+                           key_used == 0) {
+                               /* Schedule server key regeneration alarm. */
+                               signal(SIGALRM, key_regeneration_alarm);
+                               alarm(options.key_regeneration_time);
+                               key_used = 1;
+                       }
+
+                       close(*newsock);
+
+                       /*
+                        * Ensure that our random state differs
+                        * from that of the child
+                        */
+                       arc4random_stir();
+               }
+
+               /* child process check (or debug mode) */
+               if (num_listen_socks < 0)
+                       break;
+       }
+}
+
+
+/*
+ * Main program for the daemon.
+ */
+int
+main(int ac, char **av)
+{
+       extern char *optarg;
+       extern int optind;
+       int opt, i, j, on = 1;
+       int sock_in = -1, sock_out = -1, newsock = -1;
+       const char *remote_ip;
+       char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
+       int remote_port;
+       char *line, *p, *cp;
+       int config_s[2] = { -1 , -1 };
+       u_int64_t ibytes, obytes;
+       mode_t new_umask;
+       Key *key;
+       Authctxt *authctxt;
+
+#ifdef HAVE_SECUREWARE
+       (void)set_auth_parameters(ac, av);
+#endif
+       __progname = ssh_get_progname(av[0]);
+
+       /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
+       saved_argc = ac;
+       rexec_argc = ac;
+       saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
+       for (i = 0; i < ac; i++)
+               saved_argv[i] = xstrdup(av[i]);
+       saved_argv[i] = NULL;
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       compat_init_setproctitle(ac, av);
+       av = saved_argv;
+#endif
+
+       if (geteuid() == 0 && setgroups(0, NULL) == -1)
+               debug("setgroups(): %.200s", strerror(errno));
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       /* Initialize configuration options to their default values. */
+       initialize_server_options(&options);
+
+       /* Parse command-line arguments. */
+       while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) {
+               switch (opt) {
+               case '4':
+                       options.address_family = AF_INET;
+                       break;
+               case '6':
+                       options.address_family = AF_INET6;
+                       break;
+               case 'f':
+                       config_file_name = optarg;
+                       break;
+               case 'c':
+                       if (options.num_host_cert_files >= MAX_HOSTCERTS) {
+                               fprintf(stderr, "too many host certificates.\n");
+                               exit(1);
+                       }
+                       options.host_cert_files[options.num_host_cert_files++] =
+                          derelativise_path(optarg);
+                       break;
+               case 'd':
+                       if (debug_flag == 0) {
+                               debug_flag = 1;
+                               options.log_level = SYSLOG_LEVEL_DEBUG1;
+                       } else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                               options.log_level++;
+                       break;
+               case 'D':
+                       no_daemon_flag = 1;
+                       break;
+               case 'e':
+                       log_stderr = 1;
+                       break;
+               case 'i':
+                       inetd_flag = 1;
+                       break;
+               case 'r':
+                       rexec_flag = 0;
+                       break;
+               case 'R':
+                       rexeced_flag = 1;
+                       inetd_flag = 1;
+                       break;
+               case 'Q':
+                       /* ignored */
+                       break;
+               case 'q':
+                       options.log_level = SYSLOG_LEVEL_QUIET;
+                       break;
+               case 'b':
+                       options.server_key_bits = (int)strtonum(optarg, 256,
+                           32768, NULL);
+                       break;
+               case 'p':
+                       options.ports_from_cmdline = 1;
+                       if (options.num_ports >= MAX_PORTS) {
+                               fprintf(stderr, "too many ports.\n");
+                               exit(1);
+                       }
+                       options.ports[options.num_ports++] = a2port(optarg);
+                       if (options.ports[options.num_ports-1] <= 0) {
+                               fprintf(stderr, "Bad port number.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'g':
+                       if ((options.login_grace_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid login grace time.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'k':
+                       if ((options.key_regeneration_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid key regeneration interval.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'h':
+                       if (options.num_host_key_files >= MAX_HOSTKEYS) {
+                               fprintf(stderr, "too many host keys.\n");
+                               exit(1);
+                       }
+                       options.host_key_files[options.num_host_key_files++] = 
+                          derelativise_path(optarg);
+                       break;
+               case 't':
+                       test_flag = 1;
+                       break;
+               case 'T':
+                       test_flag = 2;
+                       break;
+               case 'C':
+                       cp = optarg;
+                       while ((p = strsep(&cp, ",")) && *p != '\0') {
+                               if (strncmp(p, "addr=", 5) == 0)
+                                       test_addr = xstrdup(p + 5);
+                               else if (strncmp(p, "host=", 5) == 0)
+                                       test_host = xstrdup(p + 5);
+                               else if (strncmp(p, "user=", 5) == 0)
+                                       test_user = xstrdup(p + 5);
+                               else {
+                                       fprintf(stderr, "Invalid test "
+                                           "mode specification %s\n", p);
+                                       exit(1);
+                               }
+                       }
+                       break;
+               case 'u':
+                       utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
+                       if (utmp_len > MAXHOSTNAMELEN) {
+                               fprintf(stderr, "Invalid utmp length.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'o':
+                       line = xstrdup(optarg);
+                       if (process_server_config_line(&options, line,
+                           "command-line", 0, NULL, NULL, NULL, NULL) != 0)
+                               exit(1);
+                       xfree(line);
+                       break;
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+       }
+       if (rexeced_flag || inetd_flag)
+               rexec_flag = 0;
+       if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
+               fatal("sshd re-exec requires execution with an absolute path");
+       if (rexeced_flag)
+               closefrom(REEXEC_MIN_FREE_FD);
+       else
+               closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
+
+       OpenSSL_add_all_algorithms();
+
+       /*
+        * Force logging to stderr until we have loaded the private host
+        * key (unless started from inetd)
+        */
+       log_init(__progname,
+           options.log_level == SYSLOG_LEVEL_NOT_SET ?
+           SYSLOG_LEVEL_INFO : options.log_level,
+           options.log_facility == SYSLOG_FACILITY_NOT_SET ?
+           SYSLOG_FACILITY_AUTH : options.log_facility,
+           log_stderr || !inetd_flag);
+
+       /*
+        * Unset KRB5CCNAME, otherwise the user's session may inherit it from
+        * root's environment
+        */
+       if (getenv("KRB5CCNAME") != NULL)
+               unsetenv("KRB5CCNAME");
+
+#ifdef _UNICOS
+       /* Cray can define user privs drop all privs now!
+        * Not needed on PRIV_SU systems!
+        */
+       drop_cray_privs();
+#endif
+
+       sensitive_data.server_key = NULL;
+       sensitive_data.ssh1_host_key = NULL;
+       sensitive_data.have_ssh1_key = 0;
+       sensitive_data.have_ssh2_key = 0;
+
+       /*
+        * If we're doing an extended config test, make sure we have all of
+        * the parameters we need.  If we're not doing an extended test,
+        * do not silently ignore connection test params.
+        */
+       if (test_flag >= 2 &&
+          (test_user != NULL || test_host != NULL || test_addr != NULL)
+           && (test_user == NULL || test_host == NULL || test_addr == NULL))
+               fatal("user, host and addr are all required when testing "
+                  "Match configs");
+       if (test_flag < 2 && (test_user != NULL || test_host != NULL ||
+           test_addr != NULL))
+               fatal("Config test connection parameter (-C) provided without "
+                  "test mode (-T)");
+
+       /* Fetch our configuration */
+       buffer_init(&cfg);
+       if (rexeced_flag)
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
+       else
+               load_server_config(config_file_name, &cfg);
+
+       parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
+           &cfg, NULL, NULL, NULL);
+
+       seed_rng();
+
+       /* Fill in default values for those options not explicitly set. */
+       fill_default_server_options(&options);
+
+       /* challenge-response is implemented via keyboard interactive */
+       if (options.challenge_response_authentication)
+               options.kbd_interactive_authentication = 1;
+
+       /* set default channel AF */
+       channel_set_af(options.address_family);
+
+       /* Check that there are no remaining arguments. */
+       if (optind < ac) {
+               fprintf(stderr, "Extra argument %s.\n", av[optind]);
+               exit(1);
+       }
+
+       debug("sshd version %.100s", SSH_RELEASE);
+
+       /* Store privilege separation user for later use if required. */
+       if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
+               if (use_privsep || options.kerberos_authentication)
+                       fatal("Privilege separation user %s does not exist",
+                           SSH_PRIVSEP_USER);
+       } else {
+               memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd));
+               privsep_pw = pwcopy(privsep_pw);
+               xfree(privsep_pw->pw_passwd);
+               privsep_pw->pw_passwd = xstrdup("*");
+       }
+       endpwent();
+
+       /* load private host keys */
+       sensitive_data.host_keys = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_keys[i] = NULL;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = key_load_private(options.host_key_files[i], "", NULL);
+               sensitive_data.host_keys[i] = key;
+               if (key == NULL) {
+                       error("Could not load host key: %s",
+                           options.host_key_files[i]);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
+               switch (key->type) {
+               case KEY_RSA1:
+                       sensitive_data.ssh1_host_key = key;
+                       sensitive_data.have_ssh1_key = 1;
+                       break;
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       sensitive_data.have_ssh2_key = 1;
+                       break;
+               }
+               debug("private host key: #%d type %d %s", i, key->type,
+                   key_type(key));
+       }
+       if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
+               logit("Disabling protocol version 1. Could not load host key");
+               options.protocol &= ~SSH_PROTO_1;
+       }
+#ifndef GSSAPI
+       /* The GSSAPI key exchange can run without a host key */
+       if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
+               logit("Disabling protocol version 2. Could not load host key");
+               options.protocol &= ~SSH_PROTO_2;
+       }
+#endif
+       if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+               logit("sshd: no hostkeys available -- exiting.");
+               exit(1);
+       }
+
+       /*
+        * Load certificates. They are stored in an array at identical
+        * indices to the public keys that they relate to.
+        */
+       sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_certificates[i] = NULL;
+
+       for (i = 0; i < options.num_host_cert_files; i++) {
+               key = key_load_public(options.host_cert_files[i], NULL);
+               if (key == NULL) {
+                       error("Could not load host certificate: %s",
+                           options.host_cert_files[i]);
+                       continue;
+               }
+               if (!key_is_cert(key)) {
+                       error("Certificate file is not a certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               /* Find matching private key */
+               for (j = 0; j < options.num_host_key_files; j++) {
+                       if (key_equal_public(key,
+                           sensitive_data.host_keys[j])) {
+                               sensitive_data.host_certificates[j] = key;
+                               break;
+                       }
+               }
+               if (j >= options.num_host_key_files) {
+                       error("No matching private key for certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               sensitive_data.host_certificates[j] = key;
+               debug("host certificate: #%d type %d %s", j, key->type,
+                   key_type(key));
+       }
+       /* Check certain values for sanity. */
+       if (options.protocol & SSH_PROTO_1) {
+               if (options.server_key_bits < 512 ||
+                   options.server_key_bits > 32768) {
+                       fprintf(stderr, "Bad server key size.\n");
+                       exit(1);
+               }
+               /*
+                * Check that server and host key lengths differ sufficiently. This
+                * is necessary to make double encryption work with rsaref. Oh, I
+                * hate software patents. I dont know if this can go? Niels
+                */
+               if (options.server_key_bits >
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -
+                   SSH_KEY_BITS_RESERVED && options.server_key_bits <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       options.server_key_bits =
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                           SSH_KEY_BITS_RESERVED;
+                       debug("Forcing server key to %d bits to make it differ from host key.",
+                           options.server_key_bits);
+               }
+       }
+
+       if (use_privsep) {
+               struct stat st;
+
+               if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
+                   (S_ISDIR(st.st_mode) == 0))
+                       fatal("Missing privilege separation directory: %s",
+                           _PATH_PRIVSEP_CHROOT_DIR);
+
+#ifdef HAVE_CYGWIN
+               if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) &&
+                   (st.st_uid != getuid () ||
+                   (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
+#else
+               if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
+#endif
+                       fatal("%s must be owned by root and not group or "
+                           "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
+       }
+
+       if (test_flag > 1) {
+               if (test_user != NULL && test_addr != NULL && test_host != NULL)
+                       parse_server_match_config(&options, test_user,
+                           test_host, test_addr);
+               dump_config(&options);
+       }
+
+       /* Configuration looks good, so exit if in test mode. */
+       if (test_flag)
+               exit(0);
+
+       /*
+        * Clear out any supplemental groups we may have inherited.  This
+        * prevents inadvertent creation of files with bad modes (in the
+        * portable version at least, it's certainly possible for PAM
+        * to create a file, and we can't control the code in every
+        * module which might be used).
+        */
+       if (setgroups(0, NULL) < 0)
+               debug("setgroups() failed: %.200s", strerror(errno));
+
+       if (rexec_flag) {
+               rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *));
+               for (i = 0; i < rexec_argc; i++) {
+                       debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
+                       rexec_argv[i] = saved_argv[i];
+               }
+               rexec_argv[rexec_argc] = "-R";
+               rexec_argv[rexec_argc + 1] = NULL;
+       }
+
+       /* Ensure that umask disallows at least group and world write */
+       new_umask = umask(0077) | 0022;
+       (void) umask(new_umask);
+
+       /* Initialize the log (it is reinitialized below in case we forked). */
+       if (debug_flag && (!inetd_flag || rexeced_flag))
+               log_stderr = 1;
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /*
+        * If not in debugging mode, and not started from inetd, disconnect
+        * from the controlling terminal, and fork.  The original process
+        * exits.
+        */
+       if (!(debug_flag || inetd_flag || no_daemon_flag)) {
+#ifdef TIOCNOTTY
+               int fd;
+#endif /* TIOCNOTTY */
+               if (daemon(0, 0) < 0)
+                       fatal("daemon() failed: %.200s", strerror(errno));
+
+               /* Disconnect from the controlling tty. */
+#ifdef TIOCNOTTY
+               fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
+               if (fd >= 0) {
+                       (void) ioctl(fd, TIOCNOTTY, NULL);
+                       close(fd);
+               }
+#endif /* TIOCNOTTY */
+       }
+       /* Reinitialize the log (because of the fork above). */
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /* Initialize the random number generator. */
+       arc4random_stir();
+
+       /* Chdir to the root directory so that the current disk can be
+          unmounted if desired. */
+       chdir("/");
+
+       /* ignore SIGPIPE */
+       signal(SIGPIPE, SIG_IGN);
+
+       /* Get a connection, either from inetd or a listening TCP socket */
+       if (inetd_flag) {
+               server_accept_inetd(&sock_in, &sock_out);
+       } else {
+               platform_pre_listen();
+               server_listen();
+
+               if (options.protocol & SSH_PROTO_1)
+                       generate_ephemeral_server_key();
+
+               signal(SIGHUP, sighup_handler);
+               signal(SIGCHLD, main_sigchld_handler);
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+
+               /*
+                * Write out the pid file after the sigterm handler
+                * is setup and the listen sockets are bound
+                */
+               if (!debug_flag) {
+                       FILE *f = fopen(options.pid_file, "w");
+
+                       if (f == NULL) {
+                               error("Couldn't create pid file \"%s\": %s",
+                                   options.pid_file, strerror(errno));
+                       } else {
+                               fprintf(f, "%ld\n", (long) getpid());
+                               fclose(f);
+                       }
+               }
+
+               /* Accept a connection and return in a forked child */
+               server_accept_loop(&sock_in, &sock_out,
+                   &newsock, config_s);
+       }
+
+       /* This is the child processing a new connection. */
+       setproctitle("%s", "[accepted]");
+
+       /*
+        * Create a new session and process group since the 4.4BSD
+        * setlogin() affects the entire process group.  We don't
+        * want the child to be able to affect the parent.
+        */
+#if !defined(SSHD_ACQUIRES_CTTY)
+       /*
+        * If setsid is called, on some platforms sshd will later acquire a
+        * controlling terminal which will result in "could not set
+        * controlling tty" errors.
+        */
+       if (!debug_flag && !inetd_flag && setsid() < 0)
+               error("setsid: %.100s", strerror(errno));
+#endif
+
+       if (rexec_flag) {
+               int fd;
+
+               debug("rexec start in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+               dup2(newsock, STDIN_FILENO);
+               dup2(STDIN_FILENO, STDOUT_FILENO);
+               if (startup_pipe == -1)
+                       close(REEXEC_STARTUP_PIPE_FD);
+               else
+                       dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
+
+               dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
+               close(config_s[1]);
+               if (startup_pipe != -1)
+                       close(startup_pipe);
+
+               execv(rexec_argv[0], rexec_argv);
+
+               /* Reexec has failed, fall back and continue */
+               error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
+
+               /* Clean up fds */
+               startup_pipe = REEXEC_STARTUP_PIPE_FD;
+               close(config_s[1]);
+               close(REEXEC_CONFIG_PASS_FD);
+               newsock = sock_out = sock_in = dup(STDIN_FILENO);
+               if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       if (fd > STDERR_FILENO)
+                               close(fd);
+               }
+               debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+       }
+
+       /* Executed child processes don't need these. */
+       fcntl(sock_out, F_SETFD, FD_CLOEXEC);
+       fcntl(sock_in, F_SETFD, FD_CLOEXEC);
+
+       /*
+        * Disable the key regeneration alarm.  We will not regenerate the
+        * key since we are no longer in a position to give it to anyone. We
+        * will not restart on SIGHUP since it no longer makes sense.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGQUIT, SIG_DFL);
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGINT, SIG_DFL);
+
+       /*
+        * Register our connection.  This turns encryption off because we do
+        * not have a key.
+        */
+       packet_set_connection(sock_in, sock_out);
+       packet_set_server();
+
+       /* Set SO_KEEPALIVE if requested. */
+       if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
+           setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
+       if ((remote_port = get_remote_port()) < 0) {
+               debug("get_remote_port failed");
+               cleanup_exit(255);
+       }
+
+       /*
+        * We use get_canonical_hostname with usedns = 0 instead of
+        * get_remote_ipaddr here so IP options will be checked.
+        */
+       (void) get_canonical_hostname(0);
+       /*
+        * The rest of the code depends on the fact that
+        * get_remote_ipaddr() caches the remote ip, even if
+        * the socket goes away.
+        */
+       remote_ip = get_remote_ipaddr();
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_connection_from(remote_ip, remote_port);
+#endif
+#ifdef LIBWRAP
+       allow_severity = options.log_facility|LOG_INFO;
+       deny_severity = options.log_facility|LOG_WARNING;
+       /* Check whether logins are denied from this host. */
+       if (packet_connection_is_on_socket()) {
+               struct request_info req;
+
+               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
+               fromhost(&req);
+
+               if (!hosts_access(&req)) {
+                       debug("Connection refused by tcp wrapper");
+                       refuse(&req);
+                       /* NOTREACHED */
+                       fatal("libwrap refuse returns");
+               }
+       }
+#endif /* LIBWRAP */
+
+       /* Log the connection. */
+       verbose("Connection from %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_SECURITY_SESSION_API
+       /*
+        * Create a new security session for use by the new user login if
+        * the current session is the root session or we are not launched
+        * by inetd (eg: debugging mode or server mode).  We do not
+        * necessarily need to create a session if we are launched from
+        * inetd because Panther xinetd will create a session for us.
+        *
+        * The only case where this logic will fail is if there is an
+        * inetd running in a non-root session which is not creating
+        * new sessions for us.  Then all the users will end up in the
+        * same session (bad).
+        *
+        * When the client exits, the session will be destroyed for us
+        * automatically.
+        *
+        * We must create the session before any credentials are stored
+        * (including AFS pags, which happens a few lines below).
+        */
+       {
+               OSStatus err = 0;
+               SecuritySessionId sid = 0;
+               SessionAttributeBits sattrs = 0;
+
+               err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+               if (err)
+                       error("SessionGetInfo() failed with error %.8X",
+                           (unsigned) err);
+               else
+                       debug("Current Session ID is %.8X / Session Attributes are %.8X",
+                           (unsigned) sid, (unsigned) sattrs);
+
+               if (inetd_flag && !(sattrs & sessionIsRoot))
+                       debug("Running in inetd mode in a non-root session... "
+                           "assuming inetd created the session for us.");
+               else {
+                       debug("Creating new security session...");
+                       err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+                       if (err)
+                               error("SessionCreate() failed with error %.8X",
+                                   (unsigned) err);
+
+                       err = SessionGetInfo(callerSecuritySession, &sid, 
+                           &sattrs);
+                       if (err)
+                               error("SessionGetInfo() failed with error %.8X",
+                                   (unsigned) err);
+                       else
+                               debug("New Session ID is %.8X / Session Attributes are %.8X",
+                                   (unsigned) sid, (unsigned) sattrs);
+               }
+       }
+#endif
+
+       /*
+        * We don't want to listen forever unless the other side
+        * successfully authenticates itself.  So we set up an alarm which is
+        * cleared after successful authentication.  A limit of zero
+        * indicates no limit. Note that we don't set the alarm in debugging
+        * mode; it is just annoying to have the server exit just when you
+        * are about to discover the bug.
+        */
+       signal(SIGALRM, grace_alarm_handler);
+       if (!debug_flag)
+               alarm(options.login_grace_time);
+
+       sshd_exchange_identification(sock_in, sock_out);
+
+       /* In inetd mode, generate ephemeral key only for proto 1 connections */
+       if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
+               generate_ephemeral_server_key();
+
+       packet_set_nonblocking();
+
+       /* allocate authentication context */
+       authctxt = xcalloc(1, sizeof(*authctxt));
+
+       authctxt->loginmsg = &loginmsg;
+
+       /* XXX global for cleanup, access from other modules */
+       the_authctxt = authctxt;
+
+       /* prepare buffer to collect messages to display to user after login */
+       buffer_init(&loginmsg);
+       auth_debug_reset();
+
+       if (use_privsep)
+               if (privsep_preauth(authctxt) == 1)
+                       goto authenticated;
+
+       /* perform the key exchange */
+       /* authenticate user and start session */
+       if (compat20) {
+               do_ssh2_kex();
+               do_authentication2(authctxt);
+       } else {
+               do_ssh1_kex();
+               do_authentication(authctxt);
+       }
+       /*
+        * If we use privilege separation, the unprivileged child transfers
+        * the current keystate and exits
+        */
+       if (use_privsep) {
+               mm_send_keystate(pmonitor);
+               exit(0);
+       }
+
+ authenticated:
+       /*
+        * Cancel the alarm we set to limit the time taken for
+        * authentication.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       authctxt->authenticated = 1;
+       if (startup_pipe != -1) {
+               close(startup_pipe);
+               startup_pipe = -1;
+       }
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_event(SSH_AUTH_SUCCESS);
+#endif
+
+#ifdef GSSAPI
+       if (options.gss_authentication) {
+               temporarily_use_uid(authctxt->pw);
+               ssh_gssapi_storecreds();
+               restore_uid();
+       }
+#endif
+#ifdef USE_PAM
+       if (options.use_pam) {
+               do_pam_setcred(1);
+               do_pam_session();
+       }
+#endif
+
+       /*
+        * In privilege separation, we fork another child and prepare
+        * file descriptor passing.
+        */
+       if (use_privsep) {
+               privsep_postauth(authctxt);
+               /* the monitor process [priv] will not return */
+               if (!compat20)
+                       destroy_sensitive_data();
+       }
+
+       packet_set_timeout(options.client_alive_interval,
+           options.client_alive_count_max);
+
+       /* Start session. */
+       do_authenticated(authctxt);
+
+       /* The connection has been terminated. */
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes",
+           (unsigned long long)obytes, (unsigned long long)ibytes);
+
+       verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               finish_pam();
+#endif /* USE_PAM */
+
+#ifdef SSH_AUDIT_EVENTS
+       PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));
+#endif
+
+       packet_close();
+
+       if (use_privsep)
+               mm_terminate();
+
+       exit(0);
+}
+
+/*
+ * Decrypt session_key_int using our private server key and private host key
+ * (key with larger modulus first).
+ */
+int
+ssh1_session_key(BIGNUM *session_key_int)
+{
+       int rsafail = 0;
+
+       if (BN_cmp(sensitive_data.server_key->rsa->n,
+           sensitive_data.ssh1_host_key->rsa->n) > 0) {
+               /* Server key has bigger modulus. */
+               if (BN_num_bits(sensitive_data.server_key->rsa->n) <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) <= 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) <= 0)
+                       rsafail++;
+       } else {
+               /* Host key has bigger modulus (or they are equal). */
+               if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
+                   BN_num_bits(sensitive_data.server_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) < 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) < 0)
+                       rsafail++;
+       }
+       return (rsafail);
+}
+/*
+ * SSH1 key exchange
+ */
+static void
+do_ssh1_kex(void)
+{
+       int i, len;
+       int rsafail = 0;
+       BIGNUM *session_key_int;
+       u_char session_key[SSH_SESSION_KEY_LENGTH];
+       u_char cookie[8];
+       u_int cipher_type, auth_mask, protocol_flags;
+
+       /*
+        * Generate check bytes that the client must send back in the user
+        * packet in order for it to be accepted; this is used to defy ip
+        * spoofing attacks.  Note that this only works against somebody
+        * doing IP spoofing from a remote machine; any machine on the local
+        * network can still see outgoing packets and catch the random
+        * cookie.  This only affects rhosts authentication, and this is one
+        * of the reasons why it is inherently insecure.
+        */
+       arc4random_buf(cookie, sizeof(cookie));
+
+       /*
+        * Send our public key.  We include in the packet 64 bits of random
+        * data that must be matched in the reply in order to prevent IP
+        * spoofing.
+        */
+       packet_start(SSH_SMSG_PUBLIC_KEY);
+       for (i = 0; i < 8; i++)
+               packet_put_char(cookie[i]);
+
+       /* Store our public server RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
+       packet_put_bignum(sensitive_data.server_key->rsa->e);
+       packet_put_bignum(sensitive_data.server_key->rsa->n);
+
+       /* Store our public host RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
+
+       /* Put protocol flags. */
+       packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
+
+       /* Declare which ciphers we support. */
+       packet_put_int(cipher_mask_ssh1(0));
+
+       /* Declare supported authentication types. */
+       auth_mask = 0;
+       if (options.rhosts_rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
+       if (options.rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RSA;
+       if (options.challenge_response_authentication == 1)
+               auth_mask |= 1 << SSH_AUTH_TIS;
+       if (options.password_authentication)
+               auth_mask |= 1 << SSH_AUTH_PASSWORD;
+       packet_put_int(auth_mask);
+
+       /* Send the packet and wait for it to be sent. */
+       packet_send();
+       packet_write_wait();
+
+       debug("Sent %d bit server key and %d bit host key.",
+           BN_num_bits(sensitive_data.server_key->rsa->n),
+           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+
+       /* Read clients reply (cipher type and session key). */
+       packet_read_expect(SSH_CMSG_SESSION_KEY);
+
+       /* Get cipher type and check whether we accept this. */
+       cipher_type = packet_get_char();
+
+       if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
+               packet_disconnect("Warning: client selects unsupported cipher.");
+
+       /* Get check bytes from the packet.  These must match those we
+          sent earlier with the public key packet. */
+       for (i = 0; i < 8; i++)
+               if (cookie[i] != packet_get_char())
+                       packet_disconnect("IP Spoofing check bytes do not match.");
+
+       debug("Encryption type: %.200s", cipher_name(cipher_type));
+
+       /* Get the encrypted integer. */
+       if ((session_key_int = BN_new()) == NULL)
+               fatal("do_ssh1_kex: BN_new failed");
+       packet_get_bignum(session_key_int);
+
+       protocol_flags = packet_get_int();
+       packet_set_protocol_flags(protocol_flags);
+       packet_check_eom();
+
+       /* Decrypt session_key_int using host/server keys */
+       rsafail = PRIVSEP(ssh1_session_key(session_key_int));
+
+       /*
+        * Extract session key from the decrypted integer.  The key is in the
+        * least significant 256 bits of the integer; the first byte of the
+        * key is in the highest bits.
+        */
+       if (!rsafail) {
+               (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
+               len = BN_num_bytes(session_key_int);
+               if (len < 0 || (u_int)len > sizeof(session_key)) {
+                       error("do_ssh1_kex: bad session key len from %s: "
+                           "session_key_int %d > sizeof(session_key) %lu",
+                           get_remote_ipaddr(), len, (u_long)sizeof(session_key));
+                       rsafail++;
+               } else {
+                       memset(session_key, 0, sizeof(session_key));
+                       BN_bn2bin(session_key_int,
+                           session_key + sizeof(session_key) - len);
+
+                       derive_ssh1_session_id(
+                           sensitive_data.ssh1_host_key->rsa->n,
+                           sensitive_data.server_key->rsa->n,
+                           cookie, session_id);
+                       /*
+                        * Xor the first 16 bytes of the session key with the
+                        * session id.
+                        */
+                       for (i = 0; i < 16; i++)
+                               session_key[i] ^= session_id[i];
+               }
+       }
+       if (rsafail) {
+               int bytes = BN_num_bytes(session_key_int);
+               u_char *buf = xmalloc(bytes);
+               MD5_CTX md;
+
+               logit("do_connection: generating a fake encryption key");
+               BN_bn2bin(session_key_int, buf);
+               MD5_Init(&md);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key, &md);
+               MD5_Init(&md);
+               MD5_Update(&md, session_key, 16);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key + 16, &md);
+               memset(buf, 0, bytes);
+               xfree(buf);
+               for (i = 0; i < 16; i++)
+                       session_id[i] = session_key[i] ^ session_key[i + 16];
+       }
+       /* Destroy the private and public keys. No longer. */
+       destroy_sensitive_data();
+
+       if (use_privsep)
+               mm_ssh1_session_id(session_id);
+
+       /* Destroy the decrypted integer.  It is no longer needed. */
+       BN_clear_free(session_key_int);
+
+       /* Set the session key.  From this on all communications will be encrypted. */
+       packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);
+
+       /* Destroy our copy of the session key.  It is no longer needed. */
+       memset(session_key, 0, sizeof(session_key));
+
+       debug("Received session key; encryption turned on.");
+
+       /* Send an acknowledgment packet.  Note that this packet is sent encrypted. */
+       packet_start(SSH_SMSG_SUCCESS);
+       packet_send();
+       packet_write_wait();
+}
+
+/*
+ * SSH2 key exchange: diffie-hellman-group1-sha1
+ */
+static void
+do_ssh2_kex(void)
+{
+       Kex *kex;
+
+       if (options.ciphers != NULL) {
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       myproposal[PROPOSAL_ENC_ALGS_STOC] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
+
+       if (options.macs != NULL) {
+               myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+               myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+       }
+       if (options.compression == COMP_NONE) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
+       } else if (options.compression == COMP_DELAYED) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";
+       }
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+
+       myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
+
+#ifdef GSSAPI
+       {
+       char *orig;
+       char *gss = NULL;
+       char *newstr = NULL;
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+
+       /* 
+        * If we don't have a host key, then there's no point advertising
+        * the other key exchange algorithms
+        */
+
+       if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+               orig = NULL;
+
+       if (options.gss_keyex)
+               gss = ssh_gssapi_server_mechanisms();
+       else
+               gss = NULL;
+
+       if (gss && orig)
+               xasprintf(&newstr, "%s,%s", gss, orig);
+       else if (gss)
+               newstr = gss;
+       else if (orig)
+               newstr = orig;
+
+       /* 
+        * If we've got GSSAPI mechanisms, then we've got the 'null' host
+        * key alg, but we can't tell people about it unless its the only
+        * host key algorithm we support
+        */
+       if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+       if (newstr)
+               myproposal[PROPOSAL_KEX_ALGS] = newstr;
+       else
+               fatal("No supported key exchange algorithms");
+       }
+#endif
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
+#endif
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->load_host_public_key=&get_hostkey_public_by_type;
+       kex->load_host_private_key=&get_hostkey_private_by_type;
+       kex->host_key_index=&get_hostkey_index;
+
+       xxx_kex = kex;
+
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
+
+#ifdef DEBUG_KEXDH
+       /* send 1st encrypted/maced/compressed message */
+       packet_start(SSH2_MSG_IGNORE);
+       packet_put_cstring("markus");
+       packet_send();
+       packet_write_wait();
+#endif
+       debug("KEX done");
+}
+
+/* server specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       if (the_authctxt)
+               do_cleanup(the_authctxt);
+#ifdef SSH_AUDIT_EVENTS
+       /* done after do_cleanup so it can cancel the PAM auth 'thread' */
+       if (!use_privsep || mm_is_monitor())
+               audit_event(SSH_CONNECTION_ABANDON);
+#endif
+       _exit(i);
+}
diff --git a/.pc/selinux-role.patch/sshpty.c b/.pc/selinux-role.patch/sshpty.c
new file mode 100644 (file)
index 0000000..bbbc0fe
--- /dev/null
@@ -0,0 +1,258 @@
+/* $OpenBSD: sshpty.c,v 1.28 2007/09/11 23:49:09 stevesk Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Allocating a pseudo-terminal, and making it the controlling tty.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+#include <pwd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <termios.h>
+#ifdef HAVE_UTIL_H
+# include <util.h>
+#endif
+#include <unistd.h>
+
+#include "sshpty.h"
+#include "log.h"
+#include "misc.h"
+
+#ifdef HAVE_PTY_H
+# include <pty.h>
+#endif
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
+#ifdef __APPLE__
+# include <AvailabilityMacros.h>
+# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+#  define __APPLE_PRIVPTY__
+# endif
+#endif
+
+/*
+ * Allocates and opens a pty.  Returns 0 if no pty could be allocated, or
+ * nonzero if a pty was successfully allocated.  On success, open file
+ * descriptors for the pty and tty sides and the name of the tty side are
+ * returned (the buffer must be able to hold at least 64 characters).
+ */
+
+int
+pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
+{
+       /* openpty(3) exists in OSF/1 and some other os'es */
+       char *name;
+       int i;
+
+       i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
+       if (i < 0) {
+               error("openpty: %.100s", strerror(errno));
+               return 0;
+       }
+       name = ttyname(*ttyfd);
+       if (!name)
+               fatal("openpty returns device for which ttyname fails.");
+
+       strlcpy(namebuf, name, namebuflen);     /* possible truncation */
+       return 1;
+}
+
+/* Releases the tty.  Its ownership is returned to root, and permissions to 0666. */
+
+void
+pty_release(const char *tty)
+{
+#ifndef __APPLE_PRIVPTY__
+       if (chown(tty, (uid_t) 0, (gid_t) 0) < 0)
+               error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno));
+       if (chmod(tty, (mode_t) 0666) < 0)
+               error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno));
+#endif /* __APPLE_PRIVPTY__ */
+}
+
+/* Makes the tty the process's controlling tty and sets it to sane modes. */
+
+void
+pty_make_controlling_tty(int *ttyfd, const char *tty)
+{
+       int fd;
+#ifdef USE_VHANGUP
+       void *old;
+#endif /* USE_VHANGUP */
+
+#ifdef _UNICOS
+       if (setsid() < 0)
+               error("setsid: %.100s", strerror(errno));
+
+       fd = open(tty, O_RDWR|O_NOCTTY);
+       if (fd != -1) {
+               signal(SIGHUP, SIG_IGN);
+               ioctl(fd, TCVHUP, (char *)NULL);
+               signal(SIGHUP, SIG_DFL);
+               setpgid(0, 0);
+               close(fd);
+       } else {
+               error("Failed to disconnect from controlling tty.");
+       }
+
+       debug("Setting controlling tty using TCSETCTTY.");
+       ioctl(*ttyfd, TCSETCTTY, NULL);
+       fd = open("/dev/tty", O_RDWR);
+       if (fd < 0)
+               error("%.100s: %.100s", tty, strerror(errno));
+       close(*ttyfd);
+       *ttyfd = fd;
+#else /* _UNICOS */
+
+       /* First disconnect from the old controlling tty. */
+#ifdef TIOCNOTTY
+       fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
+       if (fd >= 0) {
+               (void) ioctl(fd, TIOCNOTTY, NULL);
+               close(fd);
+       }
+#endif /* TIOCNOTTY */
+       if (setsid() < 0)
+               error("setsid: %.100s", strerror(errno));
+
+       /*
+        * Verify that we are successfully disconnected from the controlling
+        * tty.
+        */
+       fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
+       if (fd >= 0) {
+               error("Failed to disconnect from controlling tty.");
+               close(fd);
+       }
+       /* Make it our controlling tty. */
+#ifdef TIOCSCTTY
+       debug("Setting controlling tty using TIOCSCTTY.");
+       if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0)
+               error("ioctl(TIOCSCTTY): %.100s", strerror(errno));
+#endif /* TIOCSCTTY */
+#ifdef NEED_SETPGRP
+       if (setpgrp(0,0) < 0)
+               error("SETPGRP %s",strerror(errno));
+#endif /* NEED_SETPGRP */
+#ifdef USE_VHANGUP
+       old = signal(SIGHUP, SIG_IGN);
+       vhangup();
+       signal(SIGHUP, old);
+#endif /* USE_VHANGUP */
+       fd = open(tty, O_RDWR);
+       if (fd < 0) {
+               error("%.100s: %.100s", tty, strerror(errno));
+       } else {
+#ifdef USE_VHANGUP
+               close(*ttyfd);
+               *ttyfd = fd;
+#else /* USE_VHANGUP */
+               close(fd);
+#endif /* USE_VHANGUP */
+       }
+       /* Verify that we now have a controlling tty. */
+       fd = open(_PATH_TTY, O_WRONLY);
+       if (fd < 0)
+               error("open /dev/tty failed - could not set controlling tty: %.100s",
+                   strerror(errno));
+       else
+               close(fd);
+#endif /* _UNICOS */
+}
+
+/* Changes the window size associated with the pty. */
+
+void
+pty_change_window_size(int ptyfd, u_int row, u_int col,
+       u_int xpixel, u_int ypixel)
+{
+       struct winsize w;
+
+       /* may truncate u_int -> u_short */
+       w.ws_row = row;
+       w.ws_col = col;
+       w.ws_xpixel = xpixel;
+       w.ws_ypixel = ypixel;
+       (void) ioctl(ptyfd, TIOCSWINSZ, &w);
+}
+
+void
+pty_setowner(struct passwd *pw, const char *tty)
+{
+       struct group *grp;
+       gid_t gid;
+       mode_t mode;
+       struct stat st;
+
+       /* Determine the group to make the owner of the tty. */
+       grp = getgrnam("tty");
+       if (grp) {
+               gid = grp->gr_gid;
+               mode = S_IRUSR | S_IWUSR | S_IWGRP;
+       } else {
+               gid = pw->pw_gid;
+               mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
+       }
+
+       /*
+        * Change owner and mode of the tty as required.
+        * Warn but continue if filesystem is read-only and the uids match/
+        * tty is owned by root.
+        */
+       if (stat(tty, &st))
+               fatal("stat(%.100s) failed: %.100s", tty,
+                   strerror(errno));
+
+#ifdef WITH_SELINUX
+       ssh_selinux_setup_pty(pw->pw_name, tty);
+#endif
+
+       if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
+               if (chown(tty, pw->pw_uid, gid) < 0) {
+                       if (errno == EROFS &&
+                           (st.st_uid == pw->pw_uid || st.st_uid == 0))
+                               debug("chown(%.100s, %u, %u) failed: %.100s",
+                                   tty, (u_int)pw->pw_uid, (u_int)gid,
+                                   strerror(errno));
+                       else
+                               fatal("chown(%.100s, %u, %u) failed: %.100s",
+                                   tty, (u_int)pw->pw_uid, (u_int)gid,
+                                   strerror(errno));
+               }
+       }
+
+       if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
+               if (chmod(tty, mode) < 0) {
+                       if (errno == EROFS &&
+                           (st.st_mode & (S_IRGRP | S_IROTH)) == 0)
+                               debug("chmod(%.100s, 0%o) failed: %.100s",
+                                   tty, (u_int)mode, strerror(errno));
+                       else
+                               fatal("chmod(%.100s, 0%o) failed: %.100s",
+                                   tty, (u_int)mode, strerror(errno));
+               }
+       }
+}
diff --git a/.pc/selinux-role.patch/sshpty.h b/.pc/selinux-role.patch/sshpty.h
new file mode 100644 (file)
index 0000000..cfa3224
--- /dev/null
@@ -0,0 +1,27 @@
+/* $OpenBSD: sshpty.h,v 1.12 2010/01/09 05:04:24 djm Exp $ */
+
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for allocating a pseudo-terminal and making it the controlling
+ * tty.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include <termios.h>
+
+struct termios *get_saved_tio(void);
+void    leave_raw_mode(int);
+void    enter_raw_mode(int);
+
+int     pty_allocate(int *, int *, char *, size_t);
+void    pty_release(const char *);
+void    pty_make_controlling_tty(int *, const char *);
+void    pty_change_window_size(int, u_int, u_int, u_int, u_int);
+void    pty_setowner(struct passwd *, const char *);
diff --git a/.pc/shell-path.patch/sshconnect.c b/.pc/shell-path.patch/sshconnect.c
new file mode 100644 (file)
index 0000000..0ee7266
--- /dev/null
@@ -0,0 +1,1291 @@
+/* $OpenBSD: sshconnect.c,v 1.234 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Code to connect to a remote host, and to perform the client side of the
+ * login (authentication) dialog.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
+#include "ssh.h"
+#include "rsa.h"
+#include "buffer.h"
+#include "packet.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "key.h"
+#include "sshconnect.h"
+#include "hostfile.h"
+#include "log.h"
+#include "readconf.h"
+#include "atomicio.h"
+#include "misc.h"
+#include "dns.h"
+#include "roaming.h"
+#include "ssh2.h"
+#include "version.h"
+
+char *client_version_string = NULL;
+char *server_version_string = NULL;
+
+static int matching_host_key_dns = 0;
+
+static pid_t proxy_command_pid = 0;
+
+/* import */
+extern Options options;
+extern char *__progname;
+extern uid_t original_real_uid;
+extern uid_t original_effective_uid;
+
+static int show_other_keys(struct hostkeys *, Key *);
+static void warn_changed_key(Key *);
+
+/*
+ * Connect to the given ssh server using a proxy command.
+ */
+static int
+ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
+{
+       char *command_string, *tmp;
+       int pin[2], pout[2];
+       pid_t pid;
+       char *shell, strport[NI_MAXSERV];
+
+       if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
+               shell = _PATH_BSHELL;
+
+       /* Convert the port number into a string. */
+       snprintf(strport, sizeof strport, "%hu", port);
+
+       /*
+        * Build the final command string in the buffer by making the
+        * appropriate substitutions to the given proxy command.
+        *
+        * Use "exec" to avoid "sh -c" processes on some platforms
+        * (e.g. Solaris)
+        */
+       xasprintf(&tmp, "exec %s", proxy_command);
+       command_string = percent_expand(tmp, "h", host, "p", strport,
+           "r", options.user, (char *)NULL);
+       xfree(tmp);
+
+       /* Create pipes for communicating with the proxy. */
+       if (pipe(pin) < 0 || pipe(pout) < 0)
+               fatal("Could not create pipes to communicate with the proxy: %.100s",
+                   strerror(errno));
+
+       debug("Executing proxy command: %.500s", command_string);
+
+       /* Fork and execute the proxy command. */
+       if ((pid = fork()) == 0) {
+               char *argv[10];
+
+               /* Child.  Permanently give up superuser privileges. */
+               permanently_drop_suid(original_real_uid);
+
+               /* Redirect stdin and stdout. */
+               close(pin[1]);
+               if (pin[0] != 0) {
+                       if (dup2(pin[0], 0) < 0)
+                               perror("dup2 stdin");
+                       close(pin[0]);
+               }
+               close(pout[0]);
+               if (dup2(pout[1], 1) < 0)
+                       perror("dup2 stdout");
+               /* Cannot be 1 because pin allocated two descriptors. */
+               close(pout[1]);
+
+               /* Stderr is left as it is so that error messages get
+                  printed on the user's terminal. */
+               argv[0] = shell;
+               argv[1] = "-c";
+               argv[2] = command_string;
+               argv[3] = NULL;
+
+               /* Execute the proxy command.  Note that we gave up any
+                  extra privileges above. */
+               signal(SIGPIPE, SIG_DFL);
+               execv(argv[0], argv);
+               perror(argv[0]);
+               exit(1);
+       }
+       /* Parent. */
+       if (pid < 0)
+               fatal("fork failed: %.100s", strerror(errno));
+       else
+               proxy_command_pid = pid; /* save pid to clean up later */
+
+       /* Close child side of the descriptors. */
+       close(pin[0]);
+       close(pout[1]);
+
+       /* Free the command name. */
+       xfree(command_string);
+
+       /* Set the connection file descriptors. */
+       packet_set_connection(pout[0], pin[1]);
+       packet_set_timeout(options.server_alive_interval,
+           options.server_alive_count_max);
+
+       /* Indicate OK return */
+       return 0;
+}
+
+void
+ssh_kill_proxy_command(void)
+{
+       /*
+        * Send SIGHUP to proxy command if used. We don't wait() in
+        * case it hangs and instead rely on init to reap the child
+        */
+       if (proxy_command_pid > 1)
+               kill(proxy_command_pid, SIGHUP);
+}
+
+/*
+ * Creates a (possibly privileged) socket for use as the ssh connection.
+ */
+static int
+ssh_create_socket(int privileged, struct addrinfo *ai)
+{
+       int sock, gaierr;
+       struct addrinfo hints, *res;
+
+       /*
+        * If we are running as root and want to connect to a privileged
+        * port, bind our own socket to a privileged port.
+        */
+       if (privileged) {
+               int p = IPPORT_RESERVED - 1;
+               PRIV_START;
+               sock = rresvport_af(&p, ai->ai_family);
+               PRIV_END;
+               if (sock < 0)
+                       error("rresvport: af=%d %.100s", ai->ai_family,
+                           strerror(errno));
+               else
+                       debug("Allocated local port %d.", p);
+               return sock;
+       }
+       sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+       if (sock < 0) {
+               error("socket: %.100s", strerror(errno));
+               return -1;
+       }
+       fcntl(sock, F_SETFD, FD_CLOEXEC);
+
+       /* Bind the socket to an alternative local IP address */
+       if (options.bind_address == NULL)
+               return sock;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = ai->ai_family;
+       hints.ai_socktype = ai->ai_socktype;
+       hints.ai_protocol = ai->ai_protocol;
+       hints.ai_flags = AI_PASSIVE;
+       gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res);
+       if (gaierr) {
+               error("getaddrinfo: %s: %s", options.bind_address,
+                   ssh_gai_strerror(gaierr));
+               close(sock);
+               return -1;
+       }
+       if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
+               error("bind: %s: %s", options.bind_address, strerror(errno));
+               close(sock);
+               freeaddrinfo(res);
+               return -1;
+       }
+       freeaddrinfo(res);
+       return sock;
+}
+
+static int
+timeout_connect(int sockfd, const struct sockaddr *serv_addr,
+    socklen_t addrlen, int *timeoutp)
+{
+       fd_set *fdset;
+       struct timeval tv, t_start;
+       socklen_t optlen;
+       int optval, rc, result = -1;
+
+       gettimeofday(&t_start, NULL);
+
+       if (*timeoutp <= 0) {
+               result = connect(sockfd, serv_addr, addrlen);
+               goto done;
+       }
+
+       set_nonblock(sockfd);
+       rc = connect(sockfd, serv_addr, addrlen);
+       if (rc == 0) {
+               unset_nonblock(sockfd);
+               result = 0;
+               goto done;
+       }
+       if (errno != EINPROGRESS) {
+               result = -1;
+               goto done;
+       }
+
+       fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS),
+           sizeof(fd_mask));
+       FD_SET(sockfd, fdset);
+       ms_to_timeval(&tv, *timeoutp);
+
+       for (;;) {
+               rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
+               if (rc != -1 || errno != EINTR)
+                       break;
+       }
+
+       switch (rc) {
+       case 0:
+               /* Timed out */
+               errno = ETIMEDOUT;
+               break;
+       case -1:
+               /* Select error */
+               debug("select: %s", strerror(errno));
+               break;
+       case 1:
+               /* Completed or failed */
+               optval = 0;
+               optlen = sizeof(optval);
+               if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
+                   &optlen) == -1) {
+                       debug("getsockopt: %s", strerror(errno));
+                       break;
+               }
+               if (optval != 0) {
+                       errno = optval;
+                       break;
+               }
+               result = 0;
+               unset_nonblock(sockfd);
+               break;
+       default:
+               /* Should not occur */
+               fatal("Bogus return (%d) from select()", rc);
+       }
+
+       xfree(fdset);
+
+ done:
+       if (result == 0 && *timeoutp > 0) {
+               ms_subtract_diff(&t_start, timeoutp);
+               if (*timeoutp <= 0) {
+                       errno = ETIMEDOUT;
+                       result = -1;
+               }
+       }
+
+       return (result);
+}
+
+/*
+ * Opens a TCP/IP connection to the remote server on the given host.
+ * The address of the remote host will be returned in hostaddr.
+ * If port is 0, the default port will be used.  If needpriv is true,
+ * a privileged port will be allocated to make the connection.
+ * This requires super-user privileges if needpriv is true.
+ * Connection_attempts specifies the maximum number of tries (one per
+ * second).  If proxy_command is non-NULL, it specifies the command (with %h
+ * and %p substituted for host and port, respectively) to use to contact
+ * the daemon.
+ */
+int
+ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
+    u_short port, int family, int connection_attempts, int *timeout_ms,
+    int want_keepalive, int needpriv, const char *proxy_command)
+{
+       int gaierr;
+       int on = 1;
+       int sock = -1, attempt;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+       struct addrinfo hints, *ai, *aitop;
+
+       debug2("ssh_connect: needpriv %d", needpriv);
+
+       /* If a proxy command is given, connect using it. */
+       if (proxy_command != NULL)
+               return ssh_proxy_connect(host, port, proxy_command);
+
+       /* No proxy command. */
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = family;
+       hints.ai_socktype = SOCK_STREAM;
+       snprintf(strport, sizeof strport, "%u", port);
+       if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
+               fatal("%s: Could not resolve hostname %.100s: %s", __progname,
+                   host, ssh_gai_strerror(gaierr));
+
+       for (attempt = 0; attempt < connection_attempts; attempt++) {
+               if (attempt > 0) {
+                       /* Sleep a moment before retrying. */
+                       sleep(1);
+                       debug("Trying again...");
+               }
+               /*
+                * Loop through addresses for this host, and try each one in
+                * sequence until the connection succeeds.
+                */
+               for (ai = aitop; ai; ai = ai->ai_next) {
+                       if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                               continue;
+                       if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                           ntop, sizeof(ntop), strport, sizeof(strport),
+                           NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
+                               error("ssh_connect: getnameinfo failed");
+                               continue;
+                       }
+                       debug("Connecting to %.200s [%.100s] port %s.",
+                               host, ntop, strport);
+
+                       /* Create a socket for connecting. */
+                       sock = ssh_create_socket(needpriv, ai);
+                       if (sock < 0)
+                               /* Any error is already output */
+                               continue;
+
+                       if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
+                           timeout_ms) >= 0) {
+                               /* Successful connection. */
+                               memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
+                               break;
+                       } else {
+                               debug("connect to address %s port %s: %s",
+                                   ntop, strport, strerror(errno));
+                               close(sock);
+                               sock = -1;
+                       }
+               }
+               if (sock != -1)
+                       break;  /* Successful connection. */
+       }
+
+       freeaddrinfo(aitop);
+
+       /* Return failure if we didn't get a successful connection. */
+       if (sock == -1) {
+               error("ssh: connect to host %s port %s: %s",
+                   host, strport, strerror(errno));
+               return (-1);
+       }
+
+       debug("Connection established.");
+
+       /* Set SO_KEEPALIVE if requested. */
+       if (want_keepalive &&
+           setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
+           sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
+       /* Set the connection. */
+       packet_set_connection(sock, sock);
+       packet_set_timeout(options.server_alive_interval,
+           options.server_alive_count_max);
+
+       return 0;
+}
+
+/*
+ * Waits for the server identification string, and sends our own
+ * identification string.
+ */
+void
+ssh_exchange_identification(int timeout_ms)
+{
+       char buf[256], remote_version[256];     /* must be same size! */
+       int remote_major, remote_minor, mismatch;
+       int connection_in = packet_get_connection_in();
+       int connection_out = packet_get_connection_out();
+       int minor1 = PROTOCOL_MINOR_1;
+       u_int i, n;
+       size_t len;
+       int fdsetsz, remaining, rc;
+       struct timeval t_start, t_remaining;
+       fd_set *fdset;
+
+       fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
+       fdset = xcalloc(1, fdsetsz);
+
+       /* Read other side's version identification. */
+       remaining = timeout_ms;
+       for (n = 0;;) {
+               for (i = 0; i < sizeof(buf) - 1; i++) {
+                       if (timeout_ms > 0) {
+                               gettimeofday(&t_start, NULL);
+                               ms_to_timeval(&t_remaining, remaining);
+                               FD_SET(connection_in, fdset);
+                               rc = select(connection_in + 1, fdset, NULL,
+                                   fdset, &t_remaining);
+                               ms_subtract_diff(&t_start, &remaining);
+                               if (rc == 0 || remaining <= 0)
+                                       fatal("Connection timed out during "
+                                           "banner exchange");
+                               if (rc == -1) {
+                                       if (errno == EINTR)
+                                               continue;
+                                       fatal("ssh_exchange_identification: "
+                                           "select: %s", strerror(errno));
+                               }
+                       }
+
+                       len = roaming_atomicio(read, connection_in, &buf[i], 1);
+
+                       if (len != 1 && errno == EPIPE)
+                               fatal("ssh_exchange_identification: "
+                                   "Connection closed by remote host");
+                       else if (len != 1)
+                               fatal("ssh_exchange_identification: "
+                                   "read: %.100s", strerror(errno));
+                       if (buf[i] == '\r') {
+                               buf[i] = '\n';
+                               buf[i + 1] = 0;
+                               continue;               /**XXX wait for \n */
+                       }
+                       if (buf[i] == '\n') {
+                               buf[i + 1] = 0;
+                               break;
+                       }
+                       if (++n > 65536)
+                               fatal("ssh_exchange_identification: "
+                                   "No banner received");
+               }
+               buf[sizeof(buf) - 1] = 0;
+               if (strncmp(buf, "SSH-", 4) == 0)
+                       break;
+               debug("ssh_exchange_identification: %s", buf);
+       }
+       server_version_string = xstrdup(buf);
+       xfree(fdset);
+
+       /*
+        * Check that the versions match.  In future this might accept
+        * several versions and set appropriate flags to handle them.
+        */
+       if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
+           &remote_major, &remote_minor, remote_version) != 3)
+               fatal("Bad remote protocol version identification: '%.100s'", buf);
+       debug("Remote protocol version %d.%d, remote software version %.100s",
+           remote_major, remote_minor, remote_version);
+
+       compat_datafellows(remote_version);
+       mismatch = 0;
+
+       switch (remote_major) {
+       case 1:
+               if (remote_minor == 99 &&
+                   (options.protocol & SSH_PROTO_2) &&
+                   !(options.protocol & SSH_PROTO_1_PREFERRED)) {
+                       enable_compat20();
+                       break;
+               }
+               if (!(options.protocol & SSH_PROTO_1)) {
+                       mismatch = 1;
+                       break;
+               }
+               if (remote_minor < 3) {
+                       fatal("Remote machine has too old SSH software version.");
+               } else if (remote_minor == 3 || remote_minor == 4) {
+                       /* We speak 1.3, too. */
+                       enable_compat13();
+                       minor1 = 3;
+                       if (options.forward_agent) {
+                               logit("Agent forwarding disabled for protocol 1.3");
+                               options.forward_agent = 0;
+                       }
+               }
+               break;
+       case 2:
+               if (options.protocol & SSH_PROTO_2) {
+                       enable_compat20();
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               mismatch = 1;
+               break;
+       }
+       if (mismatch)
+               fatal("Protocol major versions differ: %d vs. %d",
+                   (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
+                   remote_major);
+       /* Send our own protocol version identification. */
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
+           compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
+           compat20 ? PROTOCOL_MINOR_2 : minor1,
+           SSH_VERSION, compat20 ? "\r\n" : "\n");
+       if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
+           != strlen(buf))
+               fatal("write: %.100s", strerror(errno));
+       client_version_string = xstrdup(buf);
+       chop(client_version_string);
+       chop(server_version_string);
+       debug("Local version string %.100s", client_version_string);
+}
+
+/* defaults to 'no' */
+static int
+confirm(const char *prompt)
+{
+       const char *msg, *again = "Please type 'yes' or 'no': ";
+       char *p;
+       int ret = -1;
+
+       if (options.batch_mode)
+               return 0;
+       for (msg = prompt;;msg = again) {
+               p = read_passphrase(msg, RP_ECHO);
+               if (p == NULL ||
+                   (p[0] == '\0') || (p[0] == '\n') ||
+                   strncasecmp(p, "no", 2) == 0)
+                       ret = 0;
+               if (p && strncasecmp(p, "yes", 3) == 0)
+                       ret = 1;
+               if (p)
+                       xfree(p);
+               if (ret != -1)
+                       return ret;
+       }
+}
+
+static int
+check_host_cert(const char *host, const Key *host_key)
+{
+       const char *reason;
+
+       if (key_cert_check_authority(host_key, 1, 0, host, &reason) != 0) {
+               error("%s", reason);
+               return 0;
+       }
+       if (buffer_len(&host_key->cert->critical) != 0) {
+               error("Certificate for %s contains unsupported "
+                   "critical options(s)", host);
+               return 0;
+       }
+       return 1;
+}
+
+static int
+sockaddr_is_local(struct sockaddr *hostaddr)
+{
+       switch (hostaddr->sa_family) {
+       case AF_INET:
+               return (ntohl(((struct sockaddr_in *)hostaddr)->
+                   sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
+       case AF_INET6:
+               return IN6_IS_ADDR_LOOPBACK(
+                   &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
+       default:
+               return 0;
+       }
+}
+
+/*
+ * Prepare the hostname and ip address strings that are used to lookup
+ * host keys in known_hosts files. These may have a port number appended.
+ */
+void
+get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
+    u_short port, char **hostfile_hostname, char **hostfile_ipaddr)
+{
+       char ntop[NI_MAXHOST];
+       socklen_t addrlen;
+
+       switch (hostaddr == NULL ? -1 : hostaddr->sa_family) {
+       case -1:
+               addrlen = 0;
+               break;
+       case AF_INET:
+               addrlen = sizeof(struct sockaddr_in);
+               break;
+       case AF_INET6:
+               addrlen = sizeof(struct sockaddr_in6);
+               break;
+       default:
+               addrlen = sizeof(struct sockaddr);
+               break;
+       }
+
+       /*
+        * We don't have the remote ip-address for connections
+        * using a proxy command
+        */
+       if (hostfile_ipaddr != NULL) {
+               if (options.proxy_command == NULL) {
+                       if (getnameinfo(hostaddr, addrlen,
+                           ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
+                       fatal("check_host_key: getnameinfo failed");
+                       *hostfile_ipaddr = put_host_port(ntop, port);
+               } else {
+                       *hostfile_ipaddr = xstrdup("<no hostip for proxy "
+                           "command>");
+               }
+       }
+
+       /*
+        * Allow the user to record the key under a different name or
+        * differentiate a non-standard port.  This is useful for ssh
+        * tunneling over forwarded connections or if you run multiple
+        * sshd's on different ports on the same machine.
+        */
+       if (hostfile_hostname != NULL) {
+               if (options.host_key_alias != NULL) {
+                       *hostfile_hostname = xstrdup(options.host_key_alias);
+                       debug("using hostkeyalias: %s", *hostfile_hostname);
+               } else {
+                       *hostfile_hostname = put_host_port(hostname, port);
+               }
+       }
+}
+
+/*
+ * check whether the supplied host key is valid, return -1 if the key
+ * is not valid. user_hostfile[0] will not be updated if 'readonly' is true.
+ */
+#define RDRW   0
+#define RDONLY 1
+#define ROQUIET        2
+static int
+check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
+    Key *host_key, int readonly,
+    char **user_hostfiles, u_int num_user_hostfiles,
+    char **system_hostfiles, u_int num_system_hostfiles)
+{
+       HostStatus host_status;
+       HostStatus ip_status;
+       Key *raw_key = NULL;
+       char *ip = NULL, *host = NULL;
+       char hostline[1000], *hostp, *fp, *ra;
+       char msg[1024];
+       const char *type;
+       const struct hostkey_entry *host_found, *ip_found;
+       int len, cancelled_forwarding = 0;
+       int local = sockaddr_is_local(hostaddr);
+       int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
+       struct hostkeys *host_hostkeys, *ip_hostkeys;
+       u_int i;
+
+       /*
+        * Force accepting of the host key for loopback/localhost. The
+        * problem is that if the home directory is NFS-mounted to multiple
+        * machines, localhost will refer to a different machine in each of
+        * them, and the user will get bogus HOST_CHANGED warnings.  This
+        * essentially disables host authentication for localhost; however,
+        * this is probably not a real problem.
+        */
+       if (options.no_host_authentication_for_localhost == 1 && local &&
+           options.host_key_alias == NULL) {
+               debug("Forcing accepting of host key for "
+                   "loopback/localhost.");
+               return 0;
+       }
+
+       /*
+        * Prepare the hostname and address strings used for hostkey lookup.
+        * In some cases, these will have a port number appended.
+        */
+       get_hostfile_hostname_ipaddr(hostname, hostaddr, port, &host, &ip);
+
+       /*
+        * Turn off check_host_ip if the connection is to localhost, via proxy
+        * command or if we don't have a hostname to compare with
+        */
+       if (options.check_host_ip && (local ||
+           strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
+               options.check_host_ip = 0;
+
+       host_hostkeys = init_hostkeys();
+       for (i = 0; i < num_user_hostfiles; i++)
+               load_hostkeys(host_hostkeys, host, user_hostfiles[i]);
+       for (i = 0; i < num_system_hostfiles; i++)
+               load_hostkeys(host_hostkeys, host, system_hostfiles[i]);
+
+       ip_hostkeys = NULL;
+       if (!want_cert && options.check_host_ip) {
+               ip_hostkeys = init_hostkeys();
+               for (i = 0; i < num_user_hostfiles; i++)
+                       load_hostkeys(ip_hostkeys, ip, user_hostfiles[i]);
+               for (i = 0; i < num_system_hostfiles; i++)
+                       load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]);
+       }
+
+ retry:
+       /* Reload these as they may have changed on cert->key downgrade */
+       want_cert = key_is_cert(host_key);
+       type = key_type(host_key);
+
+       /*
+        * Check if the host key is present in the user's list of known
+        * hosts or in the systemwide list.
+        */
+       host_status = check_key_in_hostkeys(host_hostkeys, host_key,
+           &host_found);
+
+       /*
+        * Also perform check for the ip address, skip the check if we are
+        * localhost, looking for a certificate, or the hostname was an ip
+        * address to begin with.
+        */
+       if (!want_cert && ip_hostkeys != NULL) {
+               ip_status = check_key_in_hostkeys(ip_hostkeys, host_key,
+                   &ip_found);
+               if (host_status == HOST_CHANGED &&
+                   (ip_status != HOST_CHANGED || 
+                   (ip_found != NULL &&
+                   !key_equal(ip_found->key, host_found->key))))
+                       host_ip_differ = 1;
+       } else
+               ip_status = host_status;
+
+       switch (host_status) {
+       case HOST_OK:
+               /* The host is known and the key matches. */
+               debug("Host '%.200s' is known and matches the %s host %s.",
+                   host, type, want_cert ? "certificate" : "key");
+               debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
+                   host_found->file, host_found->line);
+               if (want_cert && !check_host_cert(hostname, host_key))
+                       goto fail;
+               if (options.check_host_ip && ip_status == HOST_NEW) {
+                       if (readonly || want_cert)
+                               logit("%s host key for IP address "
+                                   "'%.128s' not in list of known hosts.",
+                                   type, ip);
+                       else if (!add_host_to_hostfile(user_hostfiles[0], ip,
+                           host_key, options.hash_known_hosts))
+                               logit("Failed to add the %s host key for IP "
+                                   "address '%.128s' to the list of known "
+                                   "hosts (%.30s).", type, ip,
+                                   user_hostfiles[0]);
+                       else
+                               logit("Warning: Permanently added the %s host "
+                                   "key for IP address '%.128s' to the list "
+                                   "of known hosts.", type, ip);
+               } else if (options.visual_host_key) {
+                       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+                       ra = key_fingerprint(host_key, SSH_FP_MD5,
+                           SSH_FP_RANDOMART);
+                       logit("Host key fingerprint is %s\n%s\n", fp, ra);
+                       xfree(ra);
+                       xfree(fp);
+               }
+               break;
+       case HOST_NEW:
+               if (options.host_key_alias == NULL && port != 0 &&
+                   port != SSH_DEFAULT_PORT) {
+                       debug("checking without port identifier");
+                       if (check_host_key(hostname, hostaddr, 0, host_key,
+                           ROQUIET, user_hostfiles, num_user_hostfiles,
+                           system_hostfiles, num_system_hostfiles) == 0) {
+                               debug("found matching key w/out port");
+                               break;
+                       }
+               }
+               if (readonly || want_cert)
+                       goto fail;
+               /* The host is new. */
+               if (options.strict_host_key_checking == 1) {
+                       /*
+                        * User has requested strict host key checking.  We
+                        * will not add the host key automatically.  The only
+                        * alternative left is to abort.
+                        */
+                       error("No %s host key is known for %.200s and you "
+                           "have requested strict checking.", type, host);
+                       goto fail;
+               } else if (options.strict_host_key_checking == 2) {
+                       char msg1[1024], msg2[1024];
+
+                       if (show_other_keys(host_hostkeys, host_key))
+                               snprintf(msg1, sizeof(msg1),
+                                   "\nbut keys of different type are already"
+                                   " known for this host.");
+                       else
+                               snprintf(msg1, sizeof(msg1), ".");
+                       /* The default */
+                       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+                       ra = key_fingerprint(host_key, SSH_FP_MD5,
+                           SSH_FP_RANDOMART);
+                       msg2[0] = '\0';
+                       if (options.verify_host_key_dns) {
+                               if (matching_host_key_dns)
+                                       snprintf(msg2, sizeof(msg2),
+                                           "Matching host key fingerprint"
+                                           " found in DNS.\n");
+                               else
+                                       snprintf(msg2, sizeof(msg2),
+                                           "No matching host key fingerprint"
+                                           " found in DNS.\n");
+                       }
+                       snprintf(msg, sizeof(msg),
+                           "The authenticity of host '%.200s (%s)' can't be "
+                           "established%s\n"
+                           "%s key fingerprint is %s.%s%s\n%s"
+                           "Are you sure you want to continue connecting "
+                           "(yes/no)? ",
+                           host, ip, msg1, type, fp,
+                           options.visual_host_key ? "\n" : "",
+                           options.visual_host_key ? ra : "",
+                           msg2);
+                       xfree(ra);
+                       xfree(fp);
+                       if (!confirm(msg))
+                               goto fail;
+               }
+               /*
+                * If not in strict mode, add the key automatically to the
+                * local known_hosts file.
+                */
+               if (options.check_host_ip && ip_status == HOST_NEW) {
+                       snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
+                       hostp = hostline;
+                       if (options.hash_known_hosts) {
+                               /* Add hash of host and IP separately */
+                               r = add_host_to_hostfile(user_hostfiles[0],
+                                   host, host_key, options.hash_known_hosts) &&
+                                   add_host_to_hostfile(user_hostfiles[0], ip,
+                                   host_key, options.hash_known_hosts);
+                       } else {
+                               /* Add unhashed "host,ip" */
+                               r = add_host_to_hostfile(user_hostfiles[0],
+                                   hostline, host_key,
+                                   options.hash_known_hosts);
+                       }
+               } else {
+                       r = add_host_to_hostfile(user_hostfiles[0], host,
+                           host_key, options.hash_known_hosts);
+                       hostp = host;
+               }
+
+               if (!r)
+                       logit("Failed to add the host to the list of known "
+                           "hosts (%.500s).", user_hostfiles[0]);
+               else
+                       logit("Warning: Permanently added '%.200s' (%s) to the "
+                           "list of known hosts.", hostp, type);
+               break;
+       case HOST_REVOKED:
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("@       WARNING: REVOKED HOST KEY DETECTED!               @");
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("The %s host key for %s is marked as revoked.", type, host);
+               error("This could mean that a stolen key is being used to");
+               error("impersonate this host.");
+
+               /*
+                * If strict host key checking is in use, the user will have
+                * to edit the key manually and we can only abort.
+                */
+               if (options.strict_host_key_checking) {
+                       error("%s host key for %.200s was revoked and you have "
+                           "requested strict checking.", type, host);
+                       goto fail;
+               }
+               goto continue_unsafe;
+
+       case HOST_CHANGED:
+               if (want_cert) {
+                       /*
+                        * This is only a debug() since it is valid to have
+                        * CAs with wildcard DNS matches that don't match
+                        * all hosts that one might visit.
+                        */
+                       debug("Host certificate authority does not "
+                           "match %s in %s:%lu", CA_MARKER,
+                           host_found->file, host_found->line);
+                       goto fail;
+               }
+               if (readonly == ROQUIET)
+                       goto fail;
+               if (options.check_host_ip && host_ip_differ) {
+                       char *key_msg;
+                       if (ip_status == HOST_NEW)
+                               key_msg = "is unknown";
+                       else if (ip_status == HOST_OK)
+                               key_msg = "is unchanged";
+                       else
+                               key_msg = "has a different value";
+                       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+                       error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
+                       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+                       error("The %s host key for %s has changed,", type, host);
+                       error("and the key for the corresponding IP address %s", ip);
+                       error("%s. This could either mean that", key_msg);
+                       error("DNS SPOOFING is happening or the IP address for the host");
+                       error("and its host key have changed at the same time.");
+                       if (ip_status != HOST_NEW)
+                               error("Offending key for IP in %s:%lu",
+                                   ip_found->file, ip_found->line);
+               }
+               /* The host key has changed. */
+               warn_changed_key(host_key);
+               error("Add correct host key in %.100s to get rid of this message.",
+                   user_hostfiles[0]);
+               error("Offending %s key in %s:%lu", key_type(host_found->key),
+                   host_found->file, host_found->line);
+
+               /*
+                * If strict host key checking is in use, the user will have
+                * to edit the key manually and we can only abort.
+                */
+               if (options.strict_host_key_checking) {
+                       error("%s host key for %.200s has changed and you have "
+                           "requested strict checking.", type, host);
+                       goto fail;
+               }
+
+ continue_unsafe:
+               /*
+                * If strict host key checking has not been requested, allow
+                * the connection but without MITM-able authentication or
+                * forwarding.
+                */
+               if (options.password_authentication) {
+                       error("Password authentication is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.password_authentication = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.kbd_interactive_authentication) {
+                       error("Keyboard-interactive authentication is disabled"
+                           " to avoid man-in-the-middle attacks.");
+                       options.kbd_interactive_authentication = 0;
+                       options.challenge_response_authentication = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.challenge_response_authentication) {
+                       error("Challenge/response authentication is disabled"
+                           " to avoid man-in-the-middle attacks.");
+                       options.challenge_response_authentication = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.forward_agent) {
+                       error("Agent forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.forward_agent = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.forward_x11) {
+                       error("X11 forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.forward_x11 = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.num_local_forwards > 0 ||
+                   options.num_remote_forwards > 0) {
+                       error("Port forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.num_local_forwards =
+                           options.num_remote_forwards = 0;
+                       cancelled_forwarding = 1;
+               }
+               if (options.tun_open != SSH_TUNMODE_NO) {
+                       error("Tunnel forwarding is disabled to avoid "
+                           "man-in-the-middle attacks.");
+                       options.tun_open = SSH_TUNMODE_NO;
+                       cancelled_forwarding = 1;
+               }
+               if (options.exit_on_forward_failure && cancelled_forwarding)
+                       fatal("Error: forwarding disabled due to host key "
+                           "check failure");
+               
+               /*
+                * XXX Should permit the user to change to use the new id.
+                * This could be done by converting the host key to an
+                * identifying sentence, tell that the host identifies itself
+                * by that sentence, and ask the user if he/she wishes to
+                * accept the authentication.
+                */
+               break;
+       case HOST_FOUND:
+               fatal("internal error");
+               break;
+       }
+
+       if (options.check_host_ip && host_status != HOST_CHANGED &&
+           ip_status == HOST_CHANGED) {
+               snprintf(msg, sizeof(msg),
+                   "Warning: the %s host key for '%.200s' "
+                   "differs from the key for the IP address '%.128s'"
+                   "\nOffending key for IP in %s:%lu",
+                   type, host, ip, ip_found->file, ip_found->line);
+               if (host_status == HOST_OK) {
+                       len = strlen(msg);
+                       snprintf(msg + len, sizeof(msg) - len,
+                           "\nMatching host key in %s:%lu",
+                           host_found->file, host_found->line);
+               }
+               if (options.strict_host_key_checking == 1) {
+                       logit("%s", msg);
+                       error("Exiting, you have requested strict checking.");
+                       goto fail;
+               } else if (options.strict_host_key_checking == 2) {
+                       strlcat(msg, "\nAre you sure you want "
+                           "to continue connecting (yes/no)? ", sizeof(msg));
+                       if (!confirm(msg))
+                               goto fail;
+               } else {
+                       logit("%s", msg);
+               }
+       }
+
+       xfree(ip);
+       xfree(host);
+       if (host_hostkeys != NULL)
+               free_hostkeys(host_hostkeys);
+       if (ip_hostkeys != NULL)
+               free_hostkeys(ip_hostkeys);
+       return 0;
+
+fail:
+       if (want_cert && host_status != HOST_REVOKED) {
+               /*
+                * No matching certificate. Downgrade cert to raw key and
+                * search normally.
+                */
+               debug("No matching CA found. Retry with plain key");
+               raw_key = key_from_private(host_key);
+               if (key_drop_cert(raw_key) != 0)
+                       fatal("Couldn't drop certificate");
+               host_key = raw_key;
+               goto retry;
+       }
+       if (raw_key != NULL)
+               key_free(raw_key);
+       xfree(ip);
+       xfree(host);
+       if (host_hostkeys != NULL)
+               free_hostkeys(host_hostkeys);
+       if (ip_hostkeys != NULL)
+               free_hostkeys(ip_hostkeys);
+       return -1;
+}
+
+/* returns 0 if key verifies or -1 if key does NOT verify */
+int
+verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
+{
+       int flags = 0;
+       char *fp;
+
+       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+       debug("Server host key: %s %s", key_type(host_key), fp);
+       xfree(fp);
+
+       /* XXX certs are not yet supported for DNS */
+       if (!key_is_cert(host_key) && options.verify_host_key_dns &&
+           verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
+               if (flags & DNS_VERIFY_FOUND) {
+
+                       if (options.verify_host_key_dns == 1 &&
+                           flags & DNS_VERIFY_MATCH &&
+                           flags & DNS_VERIFY_SECURE)
+                               return 0;
+
+                       if (flags & DNS_VERIFY_MATCH) {
+                               matching_host_key_dns = 1;
+                       } else {
+                               warn_changed_key(host_key);
+                               error("Update the SSHFP RR in DNS with the new "
+                                   "host key to get rid of this message.");
+                       }
+               }
+       }
+
+       return check_host_key(host, hostaddr, options.port, host_key, RDRW,
+           options.user_hostfiles, options.num_user_hostfiles,
+           options.system_hostfiles, options.num_system_hostfiles);
+}
+
+/*
+ * Starts a dialog with the server, and authenticates the current user on the
+ * server.  This does not need any extra privileges.  The basic connection
+ * to the server must already have been established before this is called.
+ * If login fails, this function prints an error and never returns.
+ * This function does not require super-user privileges.
+ */
+void
+ssh_login(Sensitive *sensitive, const char *orighost,
+    struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
+{
+       char *host, *cp;
+       char *server_user, *local_user;
+
+       local_user = xstrdup(pw->pw_name);
+       server_user = options.user ? options.user : local_user;
+
+       /* Convert the user-supplied hostname into all lowercase. */
+       host = xstrdup(orighost);
+       for (cp = host; *cp; cp++)
+               if (isupper(*cp))
+                       *cp = (char)tolower(*cp);
+
+       /* Exchange protocol version identification strings with the server. */
+       ssh_exchange_identification(timeout_ms);
+
+       /* Put the connection into non-blocking mode. */
+       packet_set_nonblocking();
+
+       /* key exchange */
+       /* authenticate user */
+       if (compat20) {
+               ssh_kex2(host, hostaddr, port);
+               ssh_userauth2(local_user, server_user, host, sensitive);
+       } else {
+               ssh_kex(host, hostaddr);
+               ssh_userauth1(local_user, server_user, host, sensitive);
+       }
+       xfree(local_user);
+}
+
+void
+ssh_put_password(char *password)
+{
+       int size;
+       char *padded;
+
+       if (datafellows & SSH_BUG_PASSWORDPAD) {
+               packet_put_cstring(password);
+               return;
+       }
+       size = roundup(strlen(password) + 1, 32);
+       padded = xcalloc(1, size);
+       strlcpy(padded, password, size);
+       packet_put_string(padded, size);
+       memset(padded, 0, size);
+       xfree(padded);
+}
+
+/* print all known host keys for a given host, but skip keys of given type */
+static int
+show_other_keys(struct hostkeys *hostkeys, Key *key)
+{
+       int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1};
+       int i, ret = 0;
+       char *fp, *ra;
+       const struct hostkey_entry *found;
+
+       for (i = 0; type[i] != -1; i++) {
+               if (type[i] == key->type)
+                       continue;
+               if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
+                       continue;
+               fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
+               ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
+               logit("WARNING: %s key found for host %s\n"
+                   "in %s:%lu\n"
+                   "%s key fingerprint %s.",
+                   key_type(found->key),
+                   found->host, found->file, found->line,
+                   key_type(found->key), fp);
+               if (options.visual_host_key)
+                       logit("%s", ra);
+               xfree(ra);
+               xfree(fp);
+               ret = 1;
+       }
+       return ret;
+}
+
+static void
+warn_changed_key(Key *host_key)
+{
+       char *fp;
+
+       fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+
+       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+       error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
+       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+       error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
+       error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
+       error("It is also possible that a host key has just been changed.");
+       error("The fingerprint for the %s key sent by the remote host is\n%s.",
+           key_type(host_key), fp);
+       error("Please contact your system administrator.");
+
+       xfree(fp);
+}
+
+/*
+ * Execute a local command
+ */
+int
+ssh_local_cmd(const char *args)
+{
+       char *shell;
+       pid_t pid;
+       int status;
+       void (*osighand)(int);
+
+       if (!options.permit_local_command ||
+           args == NULL || !*args)
+               return (1);
+
+       if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
+               shell = _PATH_BSHELL;
+
+       osighand = signal(SIGCHLD, SIG_DFL);
+       pid = fork();
+       if (pid == 0) {
+               signal(SIGPIPE, SIG_DFL);
+               debug3("Executing %s -c \"%s\"", shell, args);
+               execl(shell, shell, "-c", args, (char *)NULL);
+               error("Couldn't execute %s -c \"%s\": %s",
+                   shell, args, strerror(errno));
+               _exit(1);
+       } else if (pid == -1)
+               fatal("fork failed: %.100s", strerror(errno));
+       while (waitpid(pid, &status, 0) == -1)
+               if (errno != EINTR)
+                       fatal("Couldn't wait for child: %s", strerror(errno));
+       signal(SIGCHLD, osighand);
+
+       if (!WIFEXITED(status))
+               return (1);
+
+       return (WEXITSTATUS(status));
+}
diff --git a/.pc/ssh-argv0.patch/ssh.1 b/.pc/ssh-argv0.patch/ssh.1
new file mode 100644 (file)
index 0000000..ac3f0b4
--- /dev/null
@@ -0,0 +1,1502 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh.1,v 1.320 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH 1
+.Os
+.Sh NAME
+.Nm ssh
+.Nd OpenSSH SSH client (remote login program)
+.Sh SYNOPSIS
+.Nm ssh
+.Bk -words
+.Op Fl 1246AaCfgKkMNnqsTtVvXxYy
+.Op Fl b Ar bind_address
+.Op Fl c Ar cipher_spec
+.Op Fl D Oo Ar bind_address : Oc Ns Ar port
+.Op Fl e Ar escape_char
+.Op Fl F Ar configfile
+.Op Fl I Ar pkcs11
+.Op Fl i Ar identity_file
+.Op Fl L Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl l Ar login_name
+.Op Fl m Ar mac_spec
+.Op Fl O Ar ctl_cmd
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Op Fl R Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl S Ar ctl_path
+.Op Fl W Ar host : Ns Ar port
+.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
+.Oo Ar user Ns @ Oc Ns Ar hostname
+.Op Ar command
+.Ek
+.Sh DESCRIPTION
+.Nm
+(SSH client) is a program for logging into a remote machine and for
+executing commands on a remote machine.
+It is intended to replace rlogin and rsh,
+and provide secure encrypted communications between
+two untrusted hosts over an insecure network.
+X11 connections and arbitrary TCP ports
+can also be forwarded over the secure channel.
+.Pp
+.Nm
+connects and logs into the specified
+.Ar hostname
+(with optional
+.Ar user
+name).
+The user must prove
+his/her identity to the remote machine using one of several methods
+depending on the protocol version used (see below).
+.Pp
+If
+.Ar command
+is specified,
+it is executed on the remote host instead of a login shell.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 1
+Forces
+.Nm
+to try protocol version 1 only.
+.It Fl 2
+Forces
+.Nm
+to try protocol version 2 only.
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl A
+Enables forwarding of the authentication agent connection.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's
+.Ux Ns -domain
+socket) can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Fl a
+Disables forwarding of the authentication agent connection.
+.It Fl b Ar bind_address
+Use
+.Ar bind_address
+on the local machine as the source address
+of the connection.
+Only useful on systems with more than one address.
+.It Fl C
+Requests compression of all data (including stdin, stdout, stderr, and
+data for forwarded X11 and TCP connections).
+The compression algorithm is the same used by
+.Xr gzip 1 ,
+and the
+.Dq level
+can be controlled by the
+.Cm CompressionLevel
+option for protocol version 1.
+Compression is desirable on modem lines and other
+slow connections, but will only slow down things on fast networks.
+The default value can be set on a host-by-host basis in the
+configuration files; see the
+.Cm Compression
+option.
+.It Fl c Ar cipher_spec
+Selects the cipher specification for encrypting the session.
+.Pp
+Protocol version 1 allows specification of a single cipher.
+The supported values are
+.Dq 3des ,
+.Dq blowfish ,
+and
+.Dq des .
+.Ar 3des
+(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
+It is believed to be secure.
+.Ar blowfish
+is a fast block cipher; it appears very secure and is much faster than
+.Ar 3des .
+.Ar des
+is only supported in the
+.Nm
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.Pp
+For protocol version 2,
+.Ar cipher_spec
+is a comma-separated list of ciphers
+listed in order of preference.
+See the
+.Cm Ciphers
+keyword in
+.Xr ssh_config 5
+for more information.
+.It Fl D Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port
+.Sm on
+.Xc
+Specifies a local
+.Dq dynamic
+application-level port forwarding.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Nm
+will act as a SOCKS server.
+Only root can forward privileged ports.
+Dynamic port forwardings can also be specified in the configuration file.
+.Pp
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl e Ar escape_char
+Sets the escape character for sessions with a pty (default:
+.Ql ~ ) .
+The escape character is only recognized at the beginning of a line.
+The escape character followed by a dot
+.Pq Ql \&.
+closes the connection;
+followed by control-Z suspends the connection;
+and followed by itself sends the escape character once.
+Setting the character to
+.Dq none
+disables any escapes and makes the session fully transparent.
+.It Fl F Ar configfile
+Specifies an alternative per-user configuration file.
+If a configuration file is given on the command line,
+the system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+will be ignored.
+The default for the per-user configuration file is
+.Pa ~/.ssh/config .
+.It Fl f
+Requests
+.Nm
+to go to background just before command execution.
+This is useful if
+.Nm
+is going to ask for passwords or passphrases, but the user
+wants it in the background.
+This implies
+.Fl n .
+The recommended way to start X11 programs at a remote site is with
+something like
+.Ic ssh -f host xterm .
+.Pp
+If the
+.Cm ExitOnForwardFailure
+configuration option is set to
+.Dq yes ,
+then a client started with
+.Fl f
+will wait for all remote port forwards to be successfully established
+before placing itself in the background.
+.It Fl g
+Allows remote hosts to connect to local forwarded ports.
+.It Fl I Ar pkcs11
+Specify the PKCS#11 shared library
+.Nm
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Fl i Ar identity_file
+Selects a file from which the identity (private key) for
+public key authentication is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Identity files may also be specified on
+a per-host basis in the configuration file.
+It is possible to have multiple
+.Fl i
+options (and multiple identities specified in
+configuration files).
+.Nm
+will also try to load certificate information from the filename obtained
+by appending
+.Pa -cert.pub
+to identity filenames.
+.It Fl K
+Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI
+credentials to the server.
+.It Fl k
+Disables forwarding (delegation) of GSSAPI credentials to the server.
+.It Fl L Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the local (client) host is to be
+forwarded to the given host and port on the remote side.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the remote machine.
+Port forwardings can also be specified in the configuration file.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl l Ar login_name
+Specifies the user to log in as on the remote machine.
+This also may be specified on a per-host basis in the configuration file.
+.It Fl M
+Places the
+.Nm
+client into
+.Dq master
+mode for connection sharing.
+Multiple
+.Fl M
+options places
+.Nm
+into
+.Dq master
+mode with confirmation required before slave connections are accepted.
+Refer to the description of
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl m Ar mac_spec
+Additionally, for protocol version 2 a comma-separated list of MAC
+(message authentication code) algorithms can
+be specified in order of preference.
+See the
+.Cm MACs
+keyword for more information.
+.It Fl N
+Do not execute a remote command.
+This is useful for just forwarding ports
+(protocol version 2 only).
+.It Fl n
+Redirects stdin from
+.Pa /dev/null
+(actually, prevents reading from stdin).
+This must be used when
+.Nm
+is run in the background.
+A common trick is to use this to run X11 programs on a remote machine.
+For example,
+.Ic ssh -n shadows.cs.hut.fi emacs &
+will start an emacs on shadows.cs.hut.fi, and the X11
+connection will be automatically forwarded over an encrypted channel.
+The
+.Nm
+program will be put in the background.
+(This does not work if
+.Nm
+needs to ask for a password or passphrase; see also the
+.Fl f
+option.)
+.It Fl O Ar ctl_cmd
+Control an active connection multiplexing master process.
+When the
+.Fl O
+option is specified, the
+.Ar ctl_cmd
+argument is interpreted and passed to the master process.
+Valid commands are:
+.Dq check
+(check that the master process is running),
+.Dq forward
+(request forwardings without command execution),
+.Dq exit
+(request the master to exit), and
+.Dq stop
+(request the master to stop accepting further multiplexing requests).
+.It Fl o Ar option
+Can be used to give options in the format used in the configuration file.
+This is useful for specifying options for which there is no separate
+command-line flag.
+For full details of the options listed below, and their possible values, see
+.Xr ssh_config 5 .
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It AddressFamily
+.It BatchMode
+.It BindAddress
+.It ChallengeResponseAuthentication
+.It CheckHostIP
+.It Cipher
+.It Ciphers
+.It ClearAllForwardings
+.It Compression
+.It CompressionLevel
+.It ConnectionAttempts
+.It ConnectTimeout
+.It ControlMaster
+.It ControlPath
+.It DynamicForward
+.It EscapeChar
+.It ExitOnForwardFailure
+.It ForwardAgent
+.It ForwardX11
+.It ForwardX11Trusted
+.It GatewayPorts
+.It GlobalKnownHostsFile
+.It GSSAPIAuthentication
+.It GSSAPIDelegateCredentials
+.It HashKnownHosts
+.It Host
+.It HostbasedAuthentication
+.It HostKeyAlgorithms
+.It HostKeyAlias
+.It HostName
+.It IdentityFile
+.It IdentitiesOnly
+.It IPQoS
+.It KbdInteractiveDevices
+.It KexAlgorithms
+.It LocalCommand
+.It LocalForward
+.It LogLevel
+.It MACs
+.It NoHostAuthenticationForLocalhost
+.It NumberOfPasswordPrompts
+.It PasswordAuthentication
+.It PermitLocalCommand
+.It PKCS11Provider
+.It Port
+.It PreferredAuthentications
+.It Protocol
+.It ProxyCommand
+.It PubkeyAuthentication
+.It RekeyLimit
+.It RemoteForward
+.It RequestTTY
+.It RhostsRSAAuthentication
+.It RSAAuthentication
+.It SendEnv
+.It ServerAliveInterval
+.It ServerAliveCountMax
+.It StrictHostKeyChecking
+.It TCPKeepAlive
+.It Tunnel
+.It TunnelDevice
+.It UsePrivilegedPort
+.It User
+.It UserKnownHostsFile
+.It VerifyHostKeyDNS
+.It VisualHostKey
+.It XAuthLocation
+.El
+.It Fl p Ar port
+Port to connect to on the remote host.
+This can be specified on a
+per-host basis in the configuration file.
+.It Fl q
+Quiet mode.
+Causes most warning and diagnostic messages to be suppressed.
+.It Fl R Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the remote (server) host is to be
+forwarded to the given host and port on the local side.
+This works by allocating a socket to listen to
+.Ar port
+on the remote side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the local machine.
+.Pp
+Port forwardings can also be specified in the configuration file.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+IPv6 addresses can be specified by enclosing the address in square braces.
+.Pp
+By default, the listening socket on the server will be bound to the loopback
+interface only.
+This may be overridden by specifying a
+.Ar bind_address .
+An empty
+.Ar bind_address ,
+or the address
+.Ql * ,
+indicates that the remote socket should listen on all interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+When used together with
+.Ic -O forward
+the allocated port will be printed to the standard output.
+.It Fl S Ar ctl_path
+Specifies the location of a control socket for connection sharing,
+or the string
+.Dq none
+to disable connection sharing.
+Refer to the description of
+.Cm ControlPath
+and
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl s
+May be used to request invocation of a subsystem on the remote system.
+Subsystems are a feature of the SSH2 protocol which facilitate the use
+of SSH as a secure transport for other applications (eg.\&
+.Xr sftp 1 ) .
+The subsystem is specified as the remote command.
+.It Fl T
+Disable pseudo-tty allocation.
+.It Fl t
+Force pseudo-tty allocation.
+This can be used to execute arbitrary
+screen-based programs on a remote machine, which can be very useful,
+e.g. when implementing menu services.
+Multiple
+.Fl t
+options force tty allocation, even if
+.Nm
+has no local tty.
+.It Fl V
+Display the version number and exit.
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in
+debugging connection, authentication, and configuration problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.It Fl W Ar host : Ns Ar port
+Requests that standard input and output on the client be forwarded to
+.Ar host
+on
+.Ar port
+over the secure channel.
+Implies
+.Fl N ,
+.Fl T ,
+.Cm ExitOnForwardFailure
+and
+.Cm ClearAllForwardings
+and works with Protocol version 2 only.
+.It Fl w Xo
+.Ar local_tun Ns Op : Ns Ar remote_tun
+.Xc
+Requests
+tunnel
+device forwarding with the specified
+.Xr tun 4
+devices between the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+See also the
+.Cm Tunnel
+and
+.Cm TunnelDevice
+directives in
+.Xr ssh_config 5 .
+If the
+.Cm Tunnel
+directive is unset, it is set to the default tunnel mode, which is
+.Dq point-to-point .
+.It Fl X
+Enables X11 forwarding.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring.
+.Pp
+For this reason, X11 forwarding is subjected to X11 SECURITY extension
+restrictions by default.
+Please refer to the
+.Nm
+.Fl Y
+option and the
+.Cm ForwardX11Trusted
+directive in
+.Xr ssh_config 5
+for more information.
+.It Fl x
+Disables X11 forwarding.
+.It Fl Y
+Enables trusted X11 forwarding.
+Trusted X11 forwardings are not subjected to the X11 SECURITY extension
+controls.
+.It Fl y
+Send log information using the
+.Xr syslog 3
+system module.
+By default this information is sent to stderr.
+.El
+.Pp
+.Nm
+may additionally obtain configuration data from
+a per-user configuration file and a system-wide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Sh AUTHENTICATION
+The OpenSSH SSH client supports SSH protocols 1 and 2.
+The default is to use protocol 2 only,
+though this can be changed via the
+.Cm Protocol
+option in
+.Xr ssh_config 5
+or the
+.Fl 1
+and
+.Fl 2
+options (see above).
+Both protocols support similar authentication methods,
+but protocol 2 is the default since
+it provides additional mechanisms for confidentiality
+(the traffic is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour)
+and integrity (hmac-md5, hmac-sha1,
+hmac-sha2-256, hmac-sha2-512,
+umac-64, hmac-ripemd160).
+Protocol 1 lacks a strong mechanism for ensuring the
+integrity of the connection.
+.Pp
+The methods available for authentication are:
+GSSAPI-based authentication,
+host-based authentication,
+public key authentication,
+challenge-response authentication,
+and password authentication.
+Authentication methods are tried in the order specified above,
+though protocol 2 has a configuration option to change the default order:
+.Cm PreferredAuthentications .
+.Pp
+Host-based authentication works as follows:
+If the machine the user logs in from is listed in
+.Pa /etc/hosts.equiv
+or
+.Pa /etc/shosts.equiv
+on the remote machine, and the user names are
+the same on both sides, or if the files
+.Pa ~/.rhosts
+or
+.Pa ~/.shosts
+exist in the user's home directory on the
+remote machine and contain a line containing the name of the client
+machine and the name of the user on that machine, the user is
+considered for login.
+Additionally, the server
+.Em must
+be able to verify the client's
+host key (see the description of
+.Pa /etc/ssh/ssh_known_hosts
+and
+.Pa ~/.ssh/known_hosts ,
+below)
+for login to be permitted.
+This authentication method closes security holes due to IP
+spoofing, DNS spoofing, and routing spoofing.
+[Note to the administrator:
+.Pa /etc/hosts.equiv ,
+.Pa ~/.rhosts ,
+and the rlogin/rsh protocol in general, are inherently insecure and should be
+disabled if security is desired.]
+.Pp
+Public key authentication works as follows:
+The scheme is based on public-key cryptography,
+using cryptosystems
+where encryption and decryption are done using separate keys,
+and it is unfeasible to derive the decryption key from the encryption key.
+The idea is that each user creates a public/private
+key pair for authentication purposes.
+The server knows the public key, and only the user knows the private key.
+.Nm
+implements public key authentication protocol automatically,
+using one of the DSA, ECDSA or RSA algorithms.
+Protocol 1 is restricted to using only RSA keys,
+but protocol 2 may use any.
+The
+.Sx HISTORY
+section of
+.Xr ssl 8
+(on non-OpenBSD systems, see
+.nh
+http://www.openbsd.org/cgi\-bin/man.cgi?query=ssl&sektion=8#HISTORY)
+.hy
+contains a brief discussion of the DSA and RSA algorithms.
+.Pp
+The file
+.Pa ~/.ssh/authorized_keys
+lists the public keys that are permitted for logging in.
+When the user logs in, the
+.Nm
+program tells the server which key pair it would like to use for
+authentication.
+The client proves that it has access to the private key
+and the server checks that the corresponding public key
+is authorized to accept the account.
+.Pp
+The user creates his/her key pair by running
+.Xr ssh-keygen 1 .
+This stores the private key in
+.Pa ~/.ssh/identity
+(protocol 1),
+.Pa ~/.ssh/id_dsa
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa
+(protocol 2 RSA)
+and stores the public key in
+.Pa ~/.ssh/identity.pub
+(protocol 1),
+.Pa ~/.ssh/id_dsa.pub
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa.pub
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa.pub
+(protocol 2 RSA)
+in the user's home directory.
+The user should then copy the public key
+to
+.Pa ~/.ssh/authorized_keys
+in his/her home directory on the remote machine.
+The
+.Pa authorized_keys
+file corresponds to the conventional
+.Pa ~/.rhosts
+file, and has one key
+per line, though the lines can be very long.
+After this, the user can log in without giving the password.
+.Pp
+A variation on public key authentication
+is available in the form of certificate authentication:
+instead of a set of public/private keys,
+signed certificates are used.
+This has the advantage that a single trusted certification authority
+can be used in place of many public/private keys.
+See the
+.Sx CERTIFICATES
+section of
+.Xr ssh-keygen 1
+for more information.
+.Pp
+The most convenient way to use public key or certificate authentication
+may be with an authentication agent.
+See
+.Xr ssh-agent 1
+for more information.
+.Pp
+Challenge-response authentication works as follows:
+The server sends an arbitrary
+.Qq challenge
+text, and prompts for a response.
+Protocol 2 allows multiple challenges and responses;
+protocol 1 is restricted to just one challenge/response.
+Examples of challenge-response authentication include
+BSD Authentication (see
+.Xr login.conf 5 )
+and PAM (some non-OpenBSD systems).
+.Pp
+Finally, if other authentication methods fail,
+.Nm
+prompts the user for a password.
+The password is sent to the remote
+host for checking; however, since all communications are encrypted,
+the password cannot be seen by someone listening on the network.
+.Pp
+.Nm
+automatically maintains and checks a database containing
+identification for all hosts it has ever been used with.
+Host keys are stored in
+.Pa ~/.ssh/known_hosts
+in the user's home directory.
+Additionally, the file
+.Pa /etc/ssh/ssh_known_hosts
+is automatically checked for known hosts.
+Any new hosts are automatically added to the user's file.
+If a host's identification ever changes,
+.Nm
+warns about this and disables password authentication to prevent
+server spoofing or man-in-the-middle attacks,
+which could otherwise be used to circumvent the encryption.
+The
+.Cm StrictHostKeyChecking
+option can be used to control logins to machines whose
+host key is not known or has changed.
+.Pp
+When the user's identity has been accepted by the server, the server
+either executes the given command, or logs into the machine and gives
+the user a normal shell on the remote machine.
+All communication with
+the remote command or shell will be automatically encrypted.
+.Pp
+If a pseudo-terminal has been allocated (normal login session), the
+user may use the escape characters noted below.
+.Pp
+If no pseudo-tty has been allocated,
+the session is transparent and can be used to reliably transfer binary data.
+On most systems, setting the escape character to
+.Dq none
+will also make the session transparent even if a tty is used.
+.Pp
+The session terminates when the command or shell on the remote
+machine exits and all X11 and TCP connections have been closed.
+.Sh ESCAPE CHARACTERS
+When a pseudo-terminal has been requested,
+.Nm
+supports a number of functions through the use of an escape character.
+.Pp
+A single tilde character can be sent as
+.Ic ~~
+or by following the tilde by a character other than those described below.
+The escape character must always follow a newline to be interpreted as
+special.
+The escape character can be changed in configuration files using the
+.Cm EscapeChar
+configuration directive or on the command line by the
+.Fl e
+option.
+.Pp
+The supported escapes (assuming the default
+.Ql ~ )
+are:
+.Bl -tag -width Ds
+.It Cm ~.
+Disconnect.
+.It Cm ~^Z
+Background
+.Nm .
+.It Cm ~#
+List forwarded connections.
+.It Cm ~&
+Background
+.Nm
+at logout when waiting for forwarded connection / X11 sessions to terminate.
+.It Cm ~?
+Display a list of escape characters.
+.It Cm ~B
+Send a BREAK to the remote system
+(only useful for SSH protocol version 2 and if the peer supports it).
+.It Cm ~C
+Open command line.
+Currently this allows the addition of port forwardings using the
+.Fl L ,
+.Fl R
+and
+.Fl D
+options (see above).
+It also allows the cancellation of existing remote port-forwardings
+using
+.Sm off
+.Fl KR Oo Ar bind_address : Oc Ar port .
+.Sm on
+.Ic !\& Ns Ar command
+allows the user to execute a local command if the
+.Ic PermitLocalCommand
+option is enabled in
+.Xr ssh_config 5 .
+Basic help is available, using the
+.Fl h
+option.
+.It Cm ~R
+Request rekeying of the connection
+(only useful for SSH protocol version 2 and if the peer supports it).
+.El
+.Sh TCP FORWARDING
+Forwarding of arbitrary TCP connections over the secure channel can
+be specified either on the command line or in a configuration file.
+One possible application of TCP forwarding is a secure connection to a
+mail server; another is going through firewalls.
+.Pp
+In the example below, we look at encrypting communication between
+an IRC client and server, even though the IRC server does not directly
+support encrypted communications.
+This works as follows:
+the user connects to the remote host using
+.Nm ,
+specifying a port to be used to forward connections
+to the remote server.
+After that it is possible to start the service which is to be encrypted
+on the client machine,
+connecting to the same local port,
+and
+.Nm
+will encrypt and forward the connection.
+.Pp
+The following example tunnels an IRC session from client machine
+.Dq 127.0.0.1
+(localhost)
+to remote server
+.Dq server.example.com :
+.Bd -literal -offset 4n
+$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
+$ irc -c '#users' -p 1234 pinky 127.0.0.1
+.Ed
+.Pp
+This tunnels a connection to IRC server
+.Dq server.example.com ,
+joining channel
+.Dq #users ,
+nickname
+.Dq pinky ,
+using port 1234.
+It doesn't matter which port is used,
+as long as it's greater than 1023
+(remember, only root can open sockets on privileged ports)
+and doesn't conflict with any ports already in use.
+The connection is forwarded to port 6667 on the remote server,
+since that's the standard port for IRC services.
+.Pp
+The
+.Fl f
+option backgrounds
+.Nm
+and the remote command
+.Dq sleep 10
+is specified to allow an amount of time
+(10 seconds, in the example)
+to start the service which is to be tunnelled.
+If no connections are made within the time specified,
+.Nm
+will exit.
+.Sh X11 FORWARDING
+If the
+.Cm ForwardX11
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl X ,
+.Fl x ,
+and
+.Fl Y
+options above)
+and the user is using X11 (the
+.Ev DISPLAY
+environment variable is set), the connection to the X11 display is
+automatically forwarded to the remote side in such a way that any X11
+programs started from the shell (or command) will go through the
+encrypted channel, and the connection to the real X server will be made
+from the local machine.
+The user should not manually set
+.Ev DISPLAY .
+Forwarding of X11 connections can be
+configured on the command line or in configuration files.
+.Pp
+The
+.Ev DISPLAY
+value set by
+.Nm
+will point to the server machine, but with a display number greater than zero.
+This is normal, and happens because
+.Nm
+creates a
+.Dq proxy
+X server on the server machine for forwarding the
+connections over the encrypted channel.
+.Pp
+.Nm
+will also automatically set up Xauthority data on the server machine.
+For this purpose, it will generate a random authorization cookie,
+store it in Xauthority on the server, and verify that any forwarded
+connections carry this cookie and replace it by the real cookie when
+the connection is opened.
+The real authentication cookie is never
+sent to the server machine (and no cookies are sent in the plain).
+.Pp
+If the
+.Cm ForwardAgent
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl A
+and
+.Fl a
+options above) and
+the user is using an authentication agent, the connection to the agent
+is automatically forwarded to the remote side.
+.Sh VERIFYING HOST KEYS
+When connecting to a server for the first time,
+a fingerprint of the server's public key is presented to the user
+(unless the option
+.Cm StrictHostKeyChecking
+has been disabled).
+Fingerprints can be determined using
+.Xr ssh-keygen 1 :
+.Pp
+.Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
+.Pp
+If the fingerprint is already known, it can be matched
+and the key can be accepted or rejected.
+Because of the difficulty of comparing host keys
+just by looking at hex strings,
+there is also support to compare host keys visually,
+using
+.Em random art .
+By setting the
+.Cm VisualHostKey
+option to
+.Dq yes ,
+a small ASCII graphic gets displayed on every login to a server, no matter
+if the session itself is interactive or not.
+By learning the pattern a known server produces, a user can easily
+find out that the host key has changed when a completely different pattern
+is displayed.
+Because these patterns are not unambiguous however, a pattern that looks
+similar to the pattern remembered only gives a good probability that the
+host key is the same, not guaranteed proof.
+.Pp
+To get a listing of the fingerprints along with their random art for
+all known hosts, the following command line can be used:
+.Pp
+.Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts
+.Pp
+If the fingerprint is unknown,
+an alternative method of verification is available:
+SSH fingerprints verified by DNS.
+An additional resource record (RR),
+SSHFP,
+is added to a zonefile
+and the connecting client is able to match the fingerprint
+with that of the key presented.
+.Pp
+In this example, we are connecting a client to a server,
+.Dq host.example.com .
+The SSHFP resource records should first be added to the zonefile for
+host.example.com:
+.Bd -literal -offset indent
+$ ssh-keygen -r host.example.com.
+.Ed
+.Pp
+The output lines will have to be added to the zonefile.
+To check that the zone is answering fingerprint queries:
+.Pp
+.Dl $ dig -t SSHFP host.example.com
+.Pp
+Finally the client connects:
+.Bd -literal -offset indent
+$ ssh -o "VerifyHostKeyDNS ask" host.example.com
+[...]
+Matching host key fingerprint found in DNS.
+Are you sure you want to continue connecting (yes/no)?
+.Ed
+.Pp
+See the
+.Cm VerifyHostKeyDNS
+option in
+.Xr ssh_config 5
+for more information.
+.Sh SSH-BASED VIRTUAL PRIVATE NETWORKS
+.Nm
+contains support for Virtual Private Network (VPN) tunnelling
+using the
+.Xr tun 4
+network pseudo-device,
+allowing two networks to be joined securely.
+The
+.Xr sshd_config 5
+configuration option
+.Cm PermitTunnel
+controls whether the server supports this,
+and at what level (layer 2 or 3 traffic).
+.Pp
+The following example would connect client network 10.0.50.0/24
+with remote network 10.0.99.0/24 using a point-to-point connection
+from 10.1.1.1 to 10.1.1.2,
+provided that the SSH server running on the gateway to the remote network,
+at 192.168.1.15, allows it.
+.Pp
+On the client:
+.Bd -literal -offset indent
+# ssh -f -w 0:1 192.168.1.15 true
+# ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
+# route add 10.0.99.0/24 10.1.1.2
+.Ed
+.Pp
+On the server:
+.Bd -literal -offset indent
+# ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
+# route add 10.0.50.0/24 10.1.1.1
+.Ed
+.Pp
+Client access may be more finely tuned via the
+.Pa /root/.ssh/authorized_keys
+file (see below) and the
+.Cm PermitRootLogin
+server option.
+The following entry would permit connections on
+.Xr tun 4
+device 1 from user
+.Dq jane
+and on tun device 2 from user
+.Dq john ,
+if
+.Cm PermitRootLogin
+is set to
+.Dq forced-commands-only :
+.Bd -literal -offset 2n
+tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane
+tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john
+.Ed
+.Pp
+Since an SSH-based setup entails a fair amount of overhead,
+it may be more suited to temporary setups,
+such as for wireless VPNs.
+More permanent VPNs are better provided by tools such as
+.Xr ipsecctl 8
+and
+.Xr isakmpd 8 .
+.Sh ENVIRONMENT
+.Nm
+will normally set the following environment variables:
+.Bl -tag -width "SSH_ORIGINAL_COMMAND"
+.It Ev DISPLAY
+The
+.Ev DISPLAY
+variable indicates the location of the X11 server.
+It is automatically set by
+.Nm
+to point to a value of the form
+.Dq hostname:n ,
+where
+.Dq hostname
+indicates the host where the shell runs, and
+.Sq n
+is an integer \*(Ge 1.
+.Nm
+uses this special value to forward X11 connections over the secure
+channel.
+The user should normally not set
+.Ev DISPLAY
+explicitly, as that
+will render the X11 connection insecure (and will require the user to
+manually copy any required authorization cookies).
+.It Ev HOME
+Set to the path of the user's home directory.
+.It Ev LOGNAME
+Synonym for
+.Ev USER ;
+set for compatibility with systems that use this variable.
+.It Ev MAIL
+Set to the path of the user's mailbox.
+.It Ev PATH
+Set to the default
+.Ev PATH ,
+as specified when compiling
+.Nm .
+.It Ev SSH_ASKPASS
+If
+.Nm
+needs a passphrase, it will read the passphrase from the current
+terminal if it was run from a terminal.
+If
+.Nm
+does not have a terminal associated with it but
+.Ev DISPLAY
+and
+.Ev SSH_ASKPASS
+are set, it will execute the program specified by
+.Ev SSH_ASKPASS
+and open an X11 window to read the passphrase.
+This is particularly useful when calling
+.Nm
+from a
+.Pa .xsession
+or related script.
+(Note that on some machines it
+may be necessary to redirect the input from
+.Pa /dev/null
+to make this work.)
+.It Ev SSH_AUTH_SOCK
+Identifies the path of a
+.Ux Ns -domain
+socket used to communicate with the agent.
+.It Ev SSH_CONNECTION
+Identifies the client and server ends of the connection.
+The variable contains
+four space-separated values: client IP address, client port number,
+server IP address, and server port number.
+.It Ev SSH_ORIGINAL_COMMAND
+This variable contains the original command line if a forced command
+is executed.
+It can be used to extract the original arguments.
+.It Ev SSH_TTY
+This is set to the name of the tty (path to the device) associated
+with the current shell or command.
+If the current session has no tty,
+this variable is not set.
+.It Ev TZ
+This variable is set to indicate the present time zone if it
+was set when the daemon was started (i.e. the daemon passes the value
+on to new connections).
+.It Ev USER
+Set to the name of the user logging in.
+.El
+.Pp
+Additionally,
+.Nm
+reads
+.Pa ~/.ssh/environment ,
+and adds lines of the format
+.Dq VARNAME=value
+to the environment if the file exists and users are allowed to
+change their environment.
+For more information, see the
+.Cm PermitUserEnvironment
+option in
+.Xr sshd_config 5 .
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.rhosts
+This file is used for host-based authentication (see above).
+On some machines this file may need to be
+world-readable if the user's home directory is on an NFS partition,
+because
+.Xr sshd 8
+reads it as root.
+Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else.
+The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.Pp
+.It Pa ~/.shosts
+This file is used in exactly the same way as
+.Pa .rhosts ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa ~/.ssh/
+This directory is the default location for all user-specific configuration
+and authentication information.
+There is no general requirement to keep the entire contents of this directory
+secret, but the recommended permissions are read/write/execute for the user,
+and not accessible by others.
+.Pp
+.It Pa ~/.ssh/authorized_keys
+Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as
+this user.
+The format of this file is described in the
+.Xr sshd 8
+manual page.
+This file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.Pp
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+It may be group-writable provided that the group in question contains only
+the user.
+.Pp
+.It Pa ~/.ssh/environment
+Contains additional definitions for environment variables; see
+.Sx ENVIRONMENT ,
+above.
+.Pp
+.It Pa ~/.ssh/identity
+.It Pa ~/.ssh/id_dsa
+.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_rsa
+Contains the private key for authentication.
+These files
+contain sensitive data and should be readable by the user but not
+accessible by others (read/write/execute).
+.Nm
+will simply ignore a private key file if it is accessible by others.
+It is possible to specify a passphrase when
+generating the key which will be used to encrypt the
+sensitive part of this file using 3DES.
+.Pp
+.It Pa ~/.ssh/identity.pub
+.It Pa ~/.ssh/id_dsa.pub
+.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_rsa.pub
+Contains the public key for authentication.
+These files are not
+sensitive and can (but need not) be readable by anyone.
+.Pp
+.It Pa ~/.ssh/known_hosts
+Contains a list of host keys for all hosts the user has logged into
+that are not already in the systemwide list of known host keys.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa ~/.ssh/rc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is
+started.
+See the
+.Xr sshd 8
+manual page for more information.
+.Pp
+.It Pa /etc/hosts.equiv
+This file is for host-based authentication (see above).
+It should only be writable by root.
+.Pp
+.It Pa /etc/shosts.equiv
+This file is used in exactly the same way as
+.Pa hosts.equiv ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Pp
+.It Pa /etc/ssh/ssh_host_key
+.It Pa /etc/ssh/ssh_host_dsa_key
+.It Pa /etc/ssh/ssh_host_ecdsa_key
+.It Pa /etc/ssh/ssh_host_rsa_key
+These three files contain the private parts of the host keys
+and are used for host-based authentication.
+If protocol version 1 is used,
+.Nm
+must be setuid root, since the host key is readable only by root.
+For protocol version 2,
+.Nm
+uses
+.Xr ssh-keysign 8
+to access the host keys,
+eliminating the requirement that
+.Nm
+be setuid root when host-based authentication is used.
+By default
+.Nm
+is not setuid root.
+.Pp
+.It Pa /etc/ssh/ssh_known_hosts
+Systemwide list of known host keys.
+This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization.
+It should be world-readable.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa /etc/ssh/sshrc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is started.
+See the
+.Xr sshd 8
+manual page for more information.
+.El
+.Sh EXIT STATUS
+.Nm
+exits with the exit status of the remote command or with 255
+if an error occurred.
+.Sh SEE ALSO
+.Xr scp 1 ,
+.Xr sftp 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-keygen 1 ,
+.Xr ssh-keyscan 1 ,
+.Xr ssh-vulnkey 1 ,
+.Xr tun 4 ,
+.Xr hosts.equiv 5 ,
+.Xr ssh_config 5 ,
+.Xr ssh-keysign 8 ,
+.Xr sshd 8
+.Rs
+.%R RFC 4250
+.%T "The Secure Shell (SSH) Protocol Assigned Numbers"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4251
+.%T "The Secure Shell (SSH) Protocol Architecture"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4252
+.%T "The Secure Shell (SSH) Authentication Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4253
+.%T "The Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4254
+.%T "The Secure Shell (SSH) Connection Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4255
+.%T "Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4256
+.%T "Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4335
+.%T "The Secure Shell (SSH) Session Channel Break Extension"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4344
+.%T "The Secure Shell (SSH) Transport Layer Encryption Modes"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4345
+.%T "Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4419
+.%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4716
+.%T "The Secure Shell (SSH) Public Key File Format"
+.%D 2006
+.Re
+.Rs
+.%R RFC 5656
+.%T "Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer"
+.%D 2009
+.Re
+.Rs
+.%T "Hash Visualization: a New Technique to improve Real-World Security"
+.%A A. Perrig
+.%A D. Song
+.%D 1999
+.%O "International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)"
+.Re
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/ssh-vulnkey.patch/Makefile.in b/.pc/ssh-vulnkey.patch/Makefile.in
new file mode 100644 (file)
index 0000000..e479a44
--- /dev/null
@@ -0,0 +1,443 @@
+# $Id: Makefile.in,v 1.325 2011/08/05 20:15:18 djm Exp $
+
+# uncomment if you run a non bourne compatable shell. Ie. csh
+#SHELL = @SH@
+
+AUTORECONF=autoreconf
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+sbindir=@sbindir@
+libexecdir=@libexecdir@
+datadir=@datadir@
+datarootdir=@datarootdir@
+mandir=@mandir@
+mansubdir=@mansubdir@
+sysconfdir=@sysconfdir@
+piddir=@piddir@
+srcdir=@srcdir@
+top_srcdir=@top_srcdir@
+
+DESTDIR=
+VPATH=@srcdir@
+SSH_PROGRAM=@bindir@/ssh
+ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
+SFTP_SERVER=$(libexecdir)/sftp-server
+SSH_KEYSIGN=$(libexecdir)/ssh-keysign
+SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
+PRIVSEP_PATH=@PRIVSEP_PATH@
+SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
+STRIP_OPT=@STRIP_OPT@
+
+PATHS= -DSSHDIR=\"$(sysconfdir)\" \
+       -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
+       -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
+       -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
+       -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
+       -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
+       -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
+       -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
+
+CC=@CC@
+LD=@LD@
+CFLAGS=@CFLAGS@
+CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+LIBS=@LIBS@
+SSHLIBS=@SSHLIBS@
+SSHDLIBS=@SSHDLIBS@
+LIBEDIT=@LIBEDIT@
+AR=@AR@
+AWK=@AWK@
+RANLIB=@RANLIB@
+INSTALL=@INSTALL@
+PERL=@PERL@
+SED=@SED@
+ENT=@ENT@
+XAUTH_PATH=@XAUTH_PATH@
+LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
+EXEEXT=@EXEEXT@
+MANFMT=@MANFMT@
+
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
+
+LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
+       canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
+       cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
+       compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
+       log.o match.o md-sha256.o moduli.o nchan.o packet.o \
+       readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
+       atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
+       monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
+       kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
+       kexgssc.o \
+       msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
+       schnorr.o ssh-pkcs11.o
+
+SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
+       sshconnect.o sshconnect1.o sshconnect2.o mux.o \
+       roaming_common.o roaming_client.o
+
+SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
+       audit.o audit-bsm.o audit-linux.o platform.o \
+       sshpty.o sshlogin.o servconf.o serverloop.o \
+       auth.o auth1.o auth2.o auth-options.o session.o \
+       auth-chall.o auth2-chall.o groupaccess.o \
+       auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
+       auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
+       monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
+       auth-krb5.o \
+       auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
+       loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
+       sftp-server.o sftp-common.o \
+       roaming_common.o roaming_serv.o \
+       sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
+
+MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
+MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
+MANTYPE                = @MANTYPE@
+
+CONFIGFILES=sshd_config.out ssh_config.out moduli.out
+CONFIGFILES_IN=sshd_config ssh_config moduli
+
+PATHSUBS       = \
+       -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
+       -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
+       -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \
+       -e 's|/usr/libexec|$(libexecdir)|g' \
+       -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \
+       -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \
+       -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
+       -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
+       -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
+       -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \
+       -e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \
+       -e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \
+       -e 's|/var/empty|$(PRIVSEP_PATH)|g' \
+       -e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g'
+
+FIXPATHSCMD    = $(SED) $(PATHSUBS)
+
+all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+
+$(LIBSSH_OBJS): Makefile.in config.h
+$(SSHOBJS): Makefile.in config.h
+$(SSHDOBJS): Makefile.in config.h
+
+.c.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
+$(LIBCOMPAT): always
+       (cd openbsd-compat && $(MAKE))
+always:
+
+libssh.a: $(LIBSSH_OBJS)
+       $(AR) rv $@ $(LIBSSH_OBJS)
+       $(RANLIB) $@
+
+ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
+       $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
+
+sshd$(EXEEXT): libssh.a        $(LIBCOMPAT) $(SSHDOBJS)
+       $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
+
+scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
+       $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
+       $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
+       $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
+       $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o
+       $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
+       $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
+ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
+       $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+
+sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
+       $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
+sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
+       $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
+
+# test driver for the loginrec code - not built by default
+logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
+       $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
+
+$(MANPAGES): $(MANPAGES_IN)
+       if test "$(MANTYPE)" = "cat"; then \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \
+       else \
+               manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \
+       fi; \
+       if test "$(MANTYPE)" = "man"; then \
+               $(FIXPATHSCMD) $${manpage} | $(AWK) -f $(srcdir)/mdoc2man.awk > $@; \
+       else \
+               $(FIXPATHSCMD) $${manpage} > $@; \
+       fi
+
+$(CONFIGFILES): $(CONFIGFILES_IN)
+       conffile=`echo $@ | sed 's/.out$$//'`; \
+       $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@
+
+# fake rule to stop make trying to compile moduli.o into a binary "moduli.o"
+moduli:
+       echo
+
+clean: regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core survey
+       (cd openbsd-compat && $(MAKE) clean)
+
+distclean:     regressclean
+       rm -f *.o *.a $(TARGETS) logintest config.cache config.log
+       rm -f *.out core opensshd.init openssh.xml
+       rm -f Makefile buildpkg.sh config.h config.status
+       rm -f survey.sh openbsd-compat/regress/Makefile *~ 
+       rm -rf autom4te.cache
+       (cd openbsd-compat && $(MAKE) distclean)
+       if test -d pkg ; then \
+               rm -fr pkg ; \
+       fi
+
+veryclean: distclean
+       rm -f configure config.h.in *.0
+
+cleandir: veryclean
+
+mrproper: veryclean
+
+realclean: veryclean
+
+catman-do:
+       @for f in $(MANPAGES_IN) ; do \
+               base=`echo $$f | sed 's/\..*$$//'` ; \
+               echo "$$f -> $$base.0" ; \
+               $(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \
+                       >$$base.0 ; \
+       done
+
+distprep: catman-do
+       $(AUTORECONF)
+       -rm -rf autom4te.cache
+
+install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
+install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf
+install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files
+
+check-config:
+       -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
+
+install-files:
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)1
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)5
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8
+       $(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir)
+       (umask 022 ; $(srcdir)/mkinstalldirs $(DESTDIR)$(PRIVSEP_PATH))
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       $(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       $(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5
+       $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
+       $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
+       $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+       ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+install-sysconf:
+       if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
+               $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \
+               $(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \
+               $(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \
+       fi
+       @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \
+               if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \
+                       echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \
+                       mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \
+               else \
+                       $(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \
+               fi ; \
+       else \
+               echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \
+       fi
+
+host-key: ssh-keygen$(EXEEXT)
+       @if [ -z "$(DESTDIR)" ] ; then \
+               if [ -f "$(sysconfdir)/ssh_host_key" ] ; then \
+                       echo "$(sysconfdir)/ssh_host_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa1 -f $(sysconfdir)/ssh_host_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_dsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t dsa -f $(sysconfdir)/ssh_host_dsa_key -N "" ; \
+               fi ; \
+               if [ -f $(sysconfdir)/ssh_host_rsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
+               else \
+                       ./ssh-keygen -t rsa -f $(sysconfdir)/ssh_host_rsa_key -N "" ; \
+               fi ; \
+               if [ -z "@COMMENT_OUT_ECC@" ] ; then \
+                   if [ -f $(sysconfdir)/ssh_host_ecdsa_key ] ; then \
+                       echo "$(sysconfdir)/ssh_host_ecdsa_key already exists, skipping." ; \
+                   else \
+                       ./ssh-keygen -t ecdsa -f $(sysconfdir)/ssh_host_ecdsa_key -N "" ; \
+                   fi ; \
+               fi ; \
+       fi ;
+
+host-key-force: ssh-keygen$(EXEEXT)
+       ./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
+       ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
+       ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
+       test -z "@COMMENT_OUT_ECC@" && ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""
+
+uninstallall:  uninstall
+       -rm -f $(DESTDIR)$(sysconfdir)/ssh_config
+       -rm -f $(DESTDIR)$(sysconfdir)/sshd_config
+       -rmdir $(DESTDIR)$(sysconfdir)
+       -rmdir $(DESTDIR)$(bindir)
+       -rmdir $(DESTDIR)$(sbindir)
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)1
+       -rmdir $(DESTDIR)$(mandir)/$(mansubdir)8
+       -rmdir $(DESTDIR)$(mandir)
+       -rmdir $(DESTDIR)$(libexecdir)
+
+uninstall:
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
+       -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+
+tests interop-tests:   $(TARGETS)
+       BUILDDIR=`pwd`; \
+       [ -d `pwd`/regress ]  ||  mkdir -p `pwd`/regress; \
+       [ -f `pwd`/regress/Makefile ]  || \
+           ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile ; \
+       TEST_SHELL="@TEST_SHELL@"; \
+       TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
+       TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
+       TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
+       TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
+       TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
+       TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
+       TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
+       TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
+       TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
+       TEST_SSH_PLINK="plink"; \
+       TEST_SSH_PUTTYGEN="puttygen"; \
+       TEST_SSH_CONCH="conch"; \
+       TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
+       TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
+       TEST_SSH_SHA256="@TEST_SSH_SHA256@" ; \
+       cd $(srcdir)/regress || exit $$?; \
+       $(MAKE) \
+               .OBJDIR="$${BUILDDIR}/regress" \
+               .CURDIR="`pwd`" \
+               BUILDDIR="$${BUILDDIR}" \
+               OBJ="$${BUILDDIR}/regress/" \
+               PATH="$${BUILDDIR}:$${PATH}" \
+               TEST_SHELL="$${TEST_SHELL}" \
+               TEST_SSH_SSH="$${TEST_SSH_SSH}" \
+               TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
+               TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
+               TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
+               TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
+               TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
+               TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
+               TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
+               TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
+               TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
+               TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
+               TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
+               TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
+               TEST_SSH_ECC="$${TEST_SSH_ECC}" \
+               TEST_SSH_SHA256="$${TEST_SSH_SHA256}" \
+               EXEEXT="$(EXEEXT)" \
+               $@ && echo all tests passed
+
+compat-tests: $(LIBCOMPAT)
+       (cd openbsd-compat/regress && $(MAKE))
+
+regressclean:
+       if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \
+               (cd regress && $(MAKE) clean) \
+       fi
+
+survey: survey.sh ssh
+       @$(SHELL) ./survey.sh > survey
+       @echo 'The survey results have been placed in the file "survey" in the'
+       @echo 'current directory.  Please review the file then send with'
+       @echo '"make send-survey".'
+
+send-survey:   survey
+       mail portable-survey@mindrot.org <survey
+
+package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
+       if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
+               sh buildpkg.sh; \
+       fi
+
diff --git a/.pc/ssh-vulnkey.patch/auth-rh-rsa.c b/.pc/ssh-vulnkey.patch/auth-rh-rsa.c
new file mode 100644 (file)
index 0000000..b21a0f4
--- /dev/null
@@ -0,0 +1,103 @@
+/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Rhosts or /etc/hosts.equiv authentication combined with RSA host
+ * authentication.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <pwd.h>
+#include <stdarg.h>
+
+#include "packet.h"
+#include "uidswap.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "key.h"
+#include "hostfile.h"
+#include "pathnames.h"
+#include "auth.h"
+#include "canohost.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+
+int
+auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
+    Key *client_host_key)
+{
+       HostStatus host_status;
+
+       if (auth_key_is_revoked(client_host_key))
+               return 0;
+
+       /* Check if we would accept it using rhosts authentication. */
+       if (!auth_rhosts(pw, cuser))
+               return 0;
+
+       host_status = check_key_in_hostfiles(pw, client_host_key,
+           chost, _PATH_SSH_SYSTEM_HOSTFILE,
+           options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
+
+       return (host_status == HOST_OK);
+}
+
+/*
+ * Tries to authenticate the user using the .rhosts file and the host using
+ * its host key.  Returns true if authentication succeeds.
+ */
+int
+auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
+{
+       char *chost;
+       struct passwd *pw = authctxt->pw;
+
+       debug("Trying rhosts with RSA host authentication for client user %.100s",
+           cuser);
+
+       if (!authctxt->valid || client_host_key == NULL ||
+           client_host_key->rsa == NULL)
+               return 0;
+
+       chost = (char *)get_canonical_hostname(options.use_dns);
+       debug("Rhosts RSA authentication: canonical host %.900s", chost);
+
+       if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
+               debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
+               packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
+               return 0;
+       }
+       /* A matching host key was found and is known. */
+
+       /* Perform the challenge-response dialog with the client for the host key. */
+       if (!auth_rsa_challenge_dialog(client_host_key)) {
+               logit("Client on %.800s failed to respond correctly to host authentication.",
+                   chost);
+               return 0;
+       }
+       /*
+        * We have authenticated the user using .rhosts or /etc/hosts.equiv,
+        * and the host using RSA. We accept the authentication.
+        */
+
+       verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
+           pw->pw_name, cuser, chost);
+       packet_send_debug("Rhosts with RSA host authentication accepted.");
+       return 1;
+}
diff --git a/.pc/ssh-vulnkey.patch/auth-rsa.c b/.pc/ssh-vulnkey.patch/auth-rsa.c
new file mode 100644 (file)
index 0000000..4ab46cd
--- /dev/null
@@ -0,0 +1,337 @@
+/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * RSA-based authentication.  This code determines whether to admit a login
+ * based on RSA authentication.  This file also contains functions to check
+ * validity of the host key.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <openssl/rsa.h>
+#include <openssl/md5.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "xmalloc.h"
+#include "rsa.h"
+#include "packet.h"
+#include "ssh1.h"
+#include "uidswap.h"
+#include "match.h"
+#include "buffer.h"
+#include "pathnames.h"
+#include "log.h"
+#include "servconf.h"
+#include "key.h"
+#include "auth-options.h"
+#include "hostfile.h"
+#include "auth.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "ssh.h"
+#include "misc.h"
+
+/* import */
+extern ServerOptions options;
+
+/*
+ * Session identifier that is used to bind key exchange and authentication
+ * responses to a particular session.
+ */
+extern u_char session_id[16];
+
+/*
+ * The .ssh/authorized_keys file contains public keys, one per line, in the
+ * following format:
+ *   options bits e n comment
+ * where bits, e and n are decimal numbers,
+ * and comment is any string of characters up to newline.  The maximum
+ * length of a line is SSH_MAX_PUBKEY_BYTES characters.  See sshd(8) for a
+ * description of the options.
+ */
+
+BIGNUM *
+auth_rsa_generate_challenge(Key *key)
+{
+       BIGNUM *challenge;
+       BN_CTX *ctx;
+
+       if ((challenge = BN_new()) == NULL)
+               fatal("auth_rsa_generate_challenge: BN_new() failed");
+       /* Generate a random challenge. */
+       if (BN_rand(challenge, 256, 0, 0) == 0)
+               fatal("auth_rsa_generate_challenge: BN_rand failed");
+       if ((ctx = BN_CTX_new()) == NULL)
+               fatal("auth_rsa_generate_challenge: BN_CTX_new failed");
+       if (BN_mod(challenge, challenge, key->rsa->n, ctx) == 0)
+               fatal("auth_rsa_generate_challenge: BN_mod failed");
+       BN_CTX_free(ctx);
+
+       return challenge;
+}
+
+int
+auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
+{
+       u_char buf[32], mdbuf[16];
+       MD5_CTX md;
+       int len;
+
+       /* don't allow short keys */
+       if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+               error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
+                   BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
+               return (0);
+       }
+
+       /* The response is MD5 of decrypted challenge plus session id. */
+       len = BN_num_bytes(challenge);
+       if (len <= 0 || len > 32)
+               fatal("auth_rsa_verify_response: bad challenge length %d", len);
+       memset(buf, 0, 32);
+       BN_bn2bin(challenge, buf + 32 - len);
+       MD5_Init(&md);
+       MD5_Update(&md, buf, 32);
+       MD5_Update(&md, session_id, 16);
+       MD5_Final(mdbuf, &md);
+
+       /* Verify that the response is the original challenge. */
+       if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
+               /* Wrong answer. */
+               return (0);
+       }
+       /* Correct answer. */
+       return (1);
+}
+
+/*
+ * Performs the RSA authentication challenge-response dialog with the client,
+ * and returns true (non-zero) if the client gave the correct answer to
+ * our challenge; returns zero if the client gives a wrong answer.
+ */
+
+int
+auth_rsa_challenge_dialog(Key *key)
+{
+       BIGNUM *challenge, *encrypted_challenge;
+       u_char response[16];
+       int i, success;
+
+       if ((encrypted_challenge = BN_new()) == NULL)
+               fatal("auth_rsa_challenge_dialog: BN_new() failed");
+
+       challenge = PRIVSEP(auth_rsa_generate_challenge(key));
+
+       /* Encrypt the challenge with the public key. */
+       rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
+
+       /* Send the encrypted challenge to the client. */
+       packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
+       packet_put_bignum(encrypted_challenge);
+       packet_send();
+       BN_clear_free(encrypted_challenge);
+       packet_write_wait();
+
+       /* Wait for a response. */
+       packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE);
+       for (i = 0; i < 16; i++)
+               response[i] = (u_char)packet_get_char();
+       packet_check_eom();
+
+       success = PRIVSEP(auth_rsa_verify_response(key, challenge, response));
+       BN_clear_free(challenge);
+       return (success);
+}
+
+static int
+rsa_key_allowed_in_file(struct passwd *pw, char *file,
+    const BIGNUM *client_n, Key **rkey)
+{
+       char line[SSH_MAX_PUBKEY_BYTES];
+       int allowed = 0;
+       u_int bits;
+       FILE *f;
+       u_long linenum = 0;
+       Key *key;
+
+       debug("trying public RSA key file %s", file);
+       if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
+               return 0;
+
+       /*
+        * Go though the accepted keys, looking for the current key.  If
+        * found, perform a challenge-response dialog to verify that the
+        * user really has the corresponding private key.
+        */
+       key = key_new(KEY_RSA1);
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               char *cp;
+               char *key_options;
+               int keybits;
+
+               /* Skip leading whitespace, empty and comment lines. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               if (!*cp || *cp == '\n' || *cp == '#')
+                       continue;
+
+               /*
+                * Check if there are options for this key, and if so,
+                * save their starting address and skip the option part
+                * for now.  If there are no options, set the starting
+                * address to NULL.
+                */
+               if (*cp < '0' || *cp > '9') {
+                       int quoted = 0;
+                       key_options = cp;
+                       for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
+                               if (*cp == '\\' && cp[1] == '"')
+                                       cp++;   /* Skip both */
+                               else if (*cp == '"')
+                                       quoted = !quoted;
+                       }
+               } else
+                       key_options = NULL;
+
+               /* Parse the key from the line. */
+               if (hostfile_read_key(&cp, &bits, key) == 0) {
+                       debug("%.100s, line %lu: non ssh1 key syntax",
+                           file, linenum);
+                       continue;
+               }
+               /* cp now points to the comment part. */
+
+               /*
+                * Check if the we have found the desired key (identified
+                * by its modulus).
+                */
+               if (BN_cmp(key->rsa->n, client_n) != 0)
+                       continue;
+
+               /* check the real bits  */
+               keybits = BN_num_bits(key->rsa->n);
+               if (keybits < 0 || bits != (u_int)keybits)
+                       logit("Warning: %s, line %lu: keysize mismatch: "
+                           "actual %d vs. announced %d.",
+                           file, linenum, BN_num_bits(key->rsa->n), bits);
+
+               /* Never accept a revoked key */
+               if (auth_key_is_revoked(key))
+                       break;
+
+               /* We have found the desired key. */
+               /*
+                * If our options do not allow this key to be used,
+                * do not send challenge.
+                */
+               if (!auth_parse_options(pw, key_options, file, linenum))
+                       continue;
+               if (key_is_cert_authority)
+                       continue;
+               /* break out, this key is allowed */
+               allowed = 1;
+               break;
+       }
+
+       /* Close the file. */
+       fclose(f);
+
+       /* return key if allowed */
+       if (allowed && rkey != NULL)
+               *rkey = key;
+       else
+               key_free(key);
+
+       return allowed;
+}
+
+/*
+ * check if there's user key matching client_n,
+ * return key if login is allowed, NULL otherwise
+ */
+
+int
+auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+{
+       char *file;
+       u_int i, allowed = 0;
+
+       temporarily_use_uid(pw);
+
+       for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
+               file = expand_authorized_keys(
+                   options.authorized_keys_files[i], pw);
+               allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
+               xfree(file);
+       }
+
+       restore_uid();
+
+       return allowed;
+}
+
+/*
+ * Performs the RSA authentication dialog with the client.  This returns
+ * 0 if the client could not be authenticated, and 1 if authentication was
+ * successful.  This may exit if there is a serious protocol violation.
+ */
+int
+auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
+{
+       Key *key;
+       char *fp;
+       struct passwd *pw = authctxt->pw;
+
+       /* no user given */
+       if (!authctxt->valid)
+               return 0;
+
+       if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) {
+               auth_clear_options();
+               return (0);
+       }
+
+       /* Perform the challenge-response dialog for this key. */
+       if (!auth_rsa_challenge_dialog(key)) {
+               /* Wrong response. */
+               verbose("Wrong response to RSA authentication challenge.");
+               packet_send_debug("Wrong response to RSA authentication challenge.");
+               /*
+                * Break out of the loop. Otherwise we might send
+                * another challenge and break the protocol.
+                */
+               key_free(key);
+               return (0);
+       }
+       /*
+        * Correct response.  The client has been successfully
+        * authenticated. Note that we have not yet processed the
+        * options; this will be reset if the options cause the
+        * authentication to be rejected.
+        */
+       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+       verbose("Found matching %s key: %s",
+           key_type(key), fp);
+       xfree(fp);
+       key_free(key);
+
+       packet_send_debug("RSA authentication accepted.");
+       return (1);
+}
diff --git a/.pc/ssh-vulnkey.patch/auth.c b/.pc/ssh-vulnkey.patch/auth.c
new file mode 100644 (file)
index 0000000..cd95da9
--- /dev/null
@@ -0,0 +1,695 @@
+/* $OpenBSD: auth.c,v 1.94 2011/05/23 03:33:38 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+#include <pwd.h>
+#ifdef HAVE_LOGIN_H
+#include <login.h>
+#endif
+#ifdef USE_SHADOW
+#include <shadow.h>
+#endif
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "match.h"
+#include "groupaccess.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "auth-options.h"
+#include "canohost.h"
+#include "uidswap.h"
+#include "misc.h"
+#include "packet.h"
+#include "loginrec.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "authfile.h"
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+extern int use_privsep;
+extern Buffer loginmsg;
+extern struct passwd *privsep_pw;
+
+/* Debugging messages */
+Buffer auth_debug;
+int auth_debug_init;
+
+/*
+ * Check if the user is allowed to log in via ssh. If user is listed
+ * in DenyUsers or one of user's groups is listed in DenyGroups, false
+ * will be returned. If AllowUsers isn't empty and user isn't listed
+ * there, or if AllowGroups isn't empty and one of user's groups isn't
+ * listed there, false will be returned.
+ * If the user's shell is not executable, false will be returned.
+ * Otherwise true is returned.
+ */
+int
+allowed_user(struct passwd * pw)
+{
+       struct stat st;
+       const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
+       u_int i;
+#ifdef USE_SHADOW
+       struct spwd *spw = NULL;
+#endif
+
+       /* Shouldn't be called if pw is NULL, but better safe than sorry... */
+       if (!pw || !pw->pw_name)
+               return 0;
+
+#ifdef USE_SHADOW
+       if (!options.use_pam)
+               spw = getspnam(pw->pw_name);
+#ifdef HAS_SHADOW_EXPIRE
+       if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
+               return 0;
+#endif /* HAS_SHADOW_EXPIRE */
+#endif /* USE_SHADOW */
+
+       /* grab passwd field for locked account check */
+       passwd = pw->pw_passwd;
+#ifdef USE_SHADOW
+       if (spw != NULL)
+#ifdef USE_LIBIAF
+               passwd = get_iaf_password(pw);
+#else
+               passwd = spw->sp_pwdp;
+#endif /* USE_LIBIAF */
+#endif
+
+       /* check for locked account */
+       if (!options.use_pam && passwd && *passwd) {
+               int locked = 0;
+
+#ifdef LOCKED_PASSWD_STRING
+               if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
+                        locked = 1;
+#endif
+#ifdef LOCKED_PASSWD_PREFIX
+               if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
+                   strlen(LOCKED_PASSWD_PREFIX)) == 0)
+                        locked = 1;
+#endif
+#ifdef LOCKED_PASSWD_SUBSTR
+               if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
+                       locked = 1;
+#endif
+#ifdef USE_LIBIAF
+               free((void *) passwd);
+#endif /* USE_LIBIAF */
+               if (locked) {
+                       logit("User %.100s not allowed because account is locked",
+                           pw->pw_name);
+                       return 0;
+               }
+       }
+
+       /*
+        * Deny if shell does not exist or is not executable unless we
+        * are chrooting.
+        */
+       if (options.chroot_directory == NULL ||
+           strcasecmp(options.chroot_directory, "none") == 0) {
+               char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
+                   _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
+
+               if (stat(shell, &st) != 0) {
+                       logit("User %.100s not allowed because shell %.100s "
+                           "does not exist", pw->pw_name, shell);
+                       xfree(shell);
+                       return 0;
+               }
+               if (S_ISREG(st.st_mode) == 0 ||
+                   (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
+                       logit("User %.100s not allowed because shell %.100s "
+                           "is not executable", pw->pw_name, shell);
+                       xfree(shell);
+                       return 0;
+               }
+               xfree(shell);
+       }
+
+       if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
+           options.num_deny_groups > 0 || options.num_allow_groups > 0) {
+               hostname = get_canonical_hostname(options.use_dns);
+               ipaddr = get_remote_ipaddr();
+       }
+
+       /* Return false if user is listed in DenyUsers */
+       if (options.num_deny_users > 0) {
+               for (i = 0; i < options.num_deny_users; i++)
+                       if (match_user(pw->pw_name, hostname, ipaddr,
+                           options.deny_users[i])) {
+                               logit("User %.100s from %.100s not allowed "
+                                   "because listed in DenyUsers",
+                                   pw->pw_name, hostname);
+                               return 0;
+                       }
+       }
+       /* Return false if AllowUsers isn't empty and user isn't listed there */
+       if (options.num_allow_users > 0) {
+               for (i = 0; i < options.num_allow_users; i++)
+                       if (match_user(pw->pw_name, hostname, ipaddr,
+                           options.allow_users[i]))
+                               break;
+               /* i < options.num_allow_users iff we break for loop */
+               if (i >= options.num_allow_users) {
+                       logit("User %.100s from %.100s not allowed because "
+                           "not listed in AllowUsers", pw->pw_name, hostname);
+                       return 0;
+               }
+       }
+       if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
+               /* Get the user's group access list (primary and supplementary) */
+               if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+                       logit("User %.100s from %.100s not allowed because "
+                           "not in any group", pw->pw_name, hostname);
+                       return 0;
+               }
+
+               /* Return false if one of user's groups is listed in DenyGroups */
+               if (options.num_deny_groups > 0)
+                       if (ga_match(options.deny_groups,
+                           options.num_deny_groups)) {
+                               ga_free();
+                               logit("User %.100s from %.100s not allowed "
+                                   "because a group is listed in DenyGroups",
+                                   pw->pw_name, hostname);
+                               return 0;
+                       }
+               /*
+                * Return false if AllowGroups isn't empty and one of user's groups
+                * isn't listed there
+                */
+               if (options.num_allow_groups > 0)
+                       if (!ga_match(options.allow_groups,
+                           options.num_allow_groups)) {
+                               ga_free();
+                               logit("User %.100s from %.100s not allowed "
+                                   "because none of user's groups are listed "
+                                   "in AllowGroups", pw->pw_name, hostname);
+                               return 0;
+                       }
+               ga_free();
+       }
+
+#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER
+       if (!sys_auth_allowed_user(pw, &loginmsg))
+               return 0;
+#endif
+
+       /* We found no reason not to let this user try to log on... */
+       return 1;
+}
+
+void
+auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
+{
+       void (*authlog) (const char *fmt,...) = verbose;
+       char *authmsg;
+
+       if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
+               return;
+
+       /* Raise logging level */
+       if (authenticated == 1 ||
+           !authctxt->valid ||
+           authctxt->failures >= options.max_authtries / 2 ||
+           strcmp(method, "password") == 0)
+               authlog = logit;
+
+       if (authctxt->postponed)
+               authmsg = "Postponed";
+       else
+               authmsg = authenticated ? "Accepted" : "Failed";
+
+       authlog("%s %s for %s%.100s from %.200s port %d%s",
+           authmsg,
+           method,
+           authctxt->valid ? "" : "invalid user ",
+           authctxt->user,
+           get_remote_ipaddr(),
+           get_remote_port(),
+           info);
+
+#ifdef CUSTOM_FAILED_LOGIN
+       if (authenticated == 0 && !authctxt->postponed &&
+           (strcmp(method, "password") == 0 ||
+           strncmp(method, "keyboard-interactive", 20) == 0 ||
+           strcmp(method, "challenge-response") == 0))
+               record_failed_login(authctxt->user,
+                   get_canonical_hostname(options.use_dns), "ssh");
+# ifdef WITH_AIXAUTHENTICATE
+       if (authenticated)
+               sys_auth_record_login(authctxt->user,
+                   get_canonical_hostname(options.use_dns), "ssh", &loginmsg);
+# endif
+#endif
+#ifdef SSH_AUDIT_EVENTS
+       if (authenticated == 0 && !authctxt->postponed)
+               audit_event(audit_classify_auth(method));
+#endif
+}
+
+/*
+ * Check whether root logins are disallowed.
+ */
+int
+auth_root_allowed(char *method)
+{
+       switch (options.permit_root_login) {
+       case PERMIT_YES:
+               return 1;
+       case PERMIT_NO_PASSWD:
+               if (strcmp(method, "password") != 0)
+                       return 1;
+               break;
+       case PERMIT_FORCED_ONLY:
+               if (forced_command) {
+                       logit("Root login accepted for forced command.");
+                       return 1;
+               }
+               break;
+       }
+       logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
+       return 0;
+}
+
+
+/*
+ * Given a template and a passwd structure, build a filename
+ * by substituting % tokenised options. Currently, %% becomes '%',
+ * %h becomes the home directory and %u the username.
+ *
+ * This returns a buffer allocated by xmalloc.
+ */
+char *
+expand_authorized_keys(const char *filename, struct passwd *pw)
+{
+       char *file, ret[MAXPATHLEN];
+       int i;
+
+       file = percent_expand(filename, "h", pw->pw_dir,
+           "u", pw->pw_name, (char *)NULL);
+
+       /*
+        * Ensure that filename starts anchored. If not, be backward
+        * compatible and prepend the '%h/'
+        */
+       if (*file == '/')
+               return (file);
+
+       i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
+       if (i < 0 || (size_t)i >= sizeof(ret))
+               fatal("expand_authorized_keys: path too long");
+       xfree(file);
+       return (xstrdup(ret));
+}
+
+char *
+authorized_principals_file(struct passwd *pw)
+{
+       if (options.authorized_principals_file == NULL)
+               return NULL;
+       return expand_authorized_keys(options.authorized_principals_file, pw);
+}
+
+/* return ok if key exists in sysfile or userfile */
+HostStatus
+check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
+    const char *sysfile, const char *userfile)
+{
+       char *user_hostfile;
+       struct stat st;
+       HostStatus host_status;
+       struct hostkeys *hostkeys;
+       const struct hostkey_entry *found;
+
+       hostkeys = init_hostkeys();
+       load_hostkeys(hostkeys, host, sysfile);
+       if (userfile != NULL) {
+               user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
+               if (options.strict_modes &&
+                   (stat(user_hostfile, &st) == 0) &&
+                   ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+                   (st.st_mode & 022) != 0)) {
+                       logit("Authentication refused for %.100s: "
+                           "bad owner or modes for %.200s",
+                           pw->pw_name, user_hostfile);
+                       auth_debug_add("Ignored %.200s: bad ownership or modes",
+                           user_hostfile);
+               } else {
+                       temporarily_use_uid(pw);
+                       load_hostkeys(hostkeys, host, user_hostfile);
+                       restore_uid();
+               }
+               xfree(user_hostfile);
+       }
+       host_status = check_key_in_hostkeys(hostkeys, key, &found);
+       if (host_status == HOST_REVOKED)
+               error("WARNING: revoked key for %s attempted authentication",
+                   found->host);
+       else if (host_status == HOST_OK)
+               debug("%s: key for %s found at %s:%ld", __func__,
+                   found->host, found->file, found->line);
+       else
+               debug("%s: key for host %s not found", __func__, host);
+
+       free_hostkeys(hostkeys);
+
+       return host_status;
+}
+
+
+/*
+ * Check a given file for security. This is defined as all components
+ * of the path to the file must be owned by either the owner of
+ * of the file or root and no directories must be group or world writable.
+ *
+ * XXX Should any specific check be done for sym links ?
+ *
+ * Takes an open file descriptor, the file name, a uid and and
+ * error buffer plus max size as arguments.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+static int
+secure_filename(FILE *f, const char *file, struct passwd *pw,
+    char *err, size_t errlen)
+{
+       uid_t uid = pw->pw_uid;
+       char buf[MAXPATHLEN], homedir[MAXPATHLEN];
+       char *cp;
+       int comparehome = 0;
+       struct stat st;
+
+       if (realpath(file, buf) == NULL) {
+               snprintf(err, errlen, "realpath %s failed: %s", file,
+                   strerror(errno));
+               return -1;
+       }
+       if (realpath(pw->pw_dir, homedir) != NULL)
+               comparehome = 1;
+
+       /* check the open file to avoid races */
+       if (fstat(fileno(f), &st) < 0 ||
+           (st.st_uid != 0 && st.st_uid != uid) ||
+           (st.st_mode & 022) != 0) {
+               snprintf(err, errlen, "bad ownership or modes for file %s",
+                   buf);
+               return -1;
+       }
+
+       /* for each component of the canonical path, walking upwards */
+       for (;;) {
+               if ((cp = dirname(buf)) == NULL) {
+                       snprintf(err, errlen, "dirname() failed");
+                       return -1;
+               }
+               strlcpy(buf, cp, sizeof(buf));
+
+               if (stat(buf, &st) < 0 ||
+                   (st.st_uid != 0 && st.st_uid != uid) ||
+                   (st.st_mode & 022) != 0) {
+                       snprintf(err, errlen,
+                           "bad ownership or modes for directory %s", buf);
+                       return -1;
+               }
+
+               /* If are past the homedir then we can stop */
+               if (comparehome && strcmp(homedir, buf) == 0)
+                       break;
+
+               /*
+                * dirname should always complete with a "/" path,
+                * but we can be paranoid and check for "." too
+                */
+               if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
+                       break;
+       }
+       return 0;
+}
+
+static FILE *
+auth_openfile(const char *file, struct passwd *pw, int strict_modes,
+    int log_missing, char *file_type)
+{
+       char line[1024];
+       struct stat st;
+       int fd;
+       FILE *f;
+
+       if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
+               if (log_missing || errno != ENOENT)
+                       debug("Could not open %s '%s': %s", file_type, file,
+                          strerror(errno));
+               return NULL;
+       }
+
+       if (fstat(fd, &st) < 0) {
+               close(fd);
+               return NULL;
+       }
+       if (!S_ISREG(st.st_mode)) {
+               logit("User %s %s %s is not a regular file",
+                   pw->pw_name, file_type, file);
+               close(fd);
+               return NULL;
+       }
+       unset_nonblock(fd);
+       if ((f = fdopen(fd, "r")) == NULL) {
+               close(fd);
+               return NULL;
+       }
+       if (strict_modes &&
+           secure_filename(f, file, pw, line, sizeof(line)) != 0) {
+               fclose(f);
+               logit("Authentication refused: %s", line);
+               auth_debug_add("Ignored %s: %s", file_type, line);
+               return NULL;
+       }
+
+       return f;
+}
+
+
+FILE *
+auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
+{
+       return auth_openfile(file, pw, strict_modes, 1, "authorized keys");
+}
+
+FILE *
+auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
+{
+       return auth_openfile(file, pw, strict_modes, 0,
+           "authorized principals");
+}
+
+struct passwd *
+getpwnamallow(const char *user)
+{
+#ifdef HAVE_LOGIN_CAP
+       extern login_cap_t *lc;
+#ifdef BSD_AUTH
+       auth_session_t *as;
+#endif
+#endif
+       struct passwd *pw;
+
+       parse_server_match_config(&options, user,
+           get_canonical_hostname(options.use_dns), get_remote_ipaddr());
+
+#if defined(_AIX) && defined(HAVE_SETAUTHDB)
+       aix_setauthdb(user);
+#endif
+
+       pw = getpwnam(user);
+
+#if defined(_AIX) && defined(HAVE_SETAUTHDB)
+       aix_restoreauthdb();
+#endif
+#ifdef HAVE_CYGWIN
+       /*
+        * Windows usernames are case-insensitive.  To avoid later problems
+        * when trying to match the username, the user is only allowed to
+        * login if the username is given in the same case as stored in the
+        * user database.
+        */
+       if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
+               logit("Login name %.100s does not match stored username %.100s",
+                   user, pw->pw_name);
+               pw = NULL;
+       }
+#endif
+       if (pw == NULL) {
+               logit("Invalid user %.100s from %.100s",
+                   user, get_remote_ipaddr());
+#ifdef CUSTOM_FAILED_LOGIN
+               record_failed_login(user,
+                   get_canonical_hostname(options.use_dns), "ssh");
+#endif
+#ifdef SSH_AUDIT_EVENTS
+               audit_event(SSH_INVALID_USER);
+#endif /* SSH_AUDIT_EVENTS */
+               return (NULL);
+       }
+       if (!allowed_user(pw))
+               return (NULL);
+#ifdef HAVE_LOGIN_CAP
+       if ((lc = login_getclass(pw->pw_class)) == NULL) {
+               debug("unable to get login class: %s", user);
+               return (NULL);
+       }
+#ifdef BSD_AUTH
+       if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
+           auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
+               debug("Approval failure for %s", user);
+               pw = NULL;
+       }
+       if (as != NULL)
+               auth_close(as);
+#endif
+#endif
+       if (pw != NULL)
+               return (pwcopy(pw));
+       return (NULL);
+}
+
+/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
+int
+auth_key_is_revoked(Key *key)
+{
+       char *key_fp;
+
+       if (options.revoked_keys_file == NULL)
+               return 0;
+
+       switch (key_in_file(key, options.revoked_keys_file, 0)) {
+       case 0:
+               /* key not revoked */
+               return 0;
+       case -1:
+               /* Error opening revoked_keys_file: refuse all keys */
+               error("Revoked keys file is unreadable: refusing public key "
+                   "authentication");
+               return 1;
+       case 1:
+               /* Key revoked */
+               key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+               error("WARNING: authentication attempt with a revoked "
+                   "%s key %s ", key_type(key), key_fp);
+               xfree(key_fp);
+               return 1;
+       }
+       fatal("key_in_file returned junk");
+}
+
+void
+auth_debug_add(const char *fmt,...)
+{
+       char buf[1024];
+       va_list args;
+
+       if (!auth_debug_init)
+               return;
+
+       va_start(args, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, args);
+       va_end(args);
+       buffer_put_cstring(&auth_debug, buf);
+}
+
+void
+auth_debug_send(void)
+{
+       char *msg;
+
+       if (!auth_debug_init)
+               return;
+       while (buffer_len(&auth_debug)) {
+               msg = buffer_get_string(&auth_debug, NULL);
+               packet_send_debug("%s", msg);
+               xfree(msg);
+       }
+}
+
+void
+auth_debug_reset(void)
+{
+       if (auth_debug_init)
+               buffer_clear(&auth_debug);
+       else {
+               buffer_init(&auth_debug);
+               auth_debug_init = 1;
+       }
+}
+
+struct passwd *
+fakepw(void)
+{
+       static struct passwd fake;
+
+       memset(&fake, 0, sizeof(fake));
+       fake.pw_name = "NOUSER";
+       fake.pw_passwd =
+           "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
+       fake.pw_gecos = "NOUSER";
+       fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
+       fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+       fake.pw_class = "";
+#endif
+       fake.pw_dir = "/nonexist";
+       fake.pw_shell = "/nonexist";
+
+       return (&fake);
+}
diff --git a/.pc/ssh-vulnkey.patch/auth.h b/.pc/ssh-vulnkey.patch/auth.h
new file mode 100644 (file)
index 0000000..fc1dff4
--- /dev/null
@@ -0,0 +1,207 @@
+/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */
+
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef AUTH_H
+#define AUTH_H
+
+#include <signal.h>
+
+#include <openssl/rsa.h>
+
+#ifdef HAVE_LOGIN_CAP
+#include <login_cap.h>
+#endif
+#ifdef BSD_AUTH
+#include <bsd_auth.h>
+#endif
+#ifdef KRB5
+#include <krb5.h>
+#endif
+
+typedef struct Authctxt Authctxt;
+typedef struct Authmethod Authmethod;
+typedef struct KbdintDevice KbdintDevice;
+
+struct Authctxt {
+       sig_atomic_t     success;
+       int              authenticated; /* authenticated and alarms cancelled */
+       int              postponed;     /* authentication needs another step */
+       int              valid;         /* user exists and is allowed to login */
+       int              attempt;
+       int              failures;
+       int              server_caused_failure; 
+       int              force_pwchange;
+       char            *user;          /* username sent by the client */
+       char            *service;
+       struct passwd   *pw;            /* set if 'valid' */
+       char            *style;
+       char            *role;
+       void            *kbdintctxt;
+       void            *jpake_ctx;
+#ifdef BSD_AUTH
+       auth_session_t  *as;
+#endif
+#ifdef KRB5
+       krb5_context     krb5_ctx;
+       krb5_ccache      krb5_fwd_ccache;
+       krb5_principal   krb5_user;
+       char            *krb5_ticket_file;
+       char            *krb5_ccname;
+#endif
+       Buffer          *loginmsg;
+       void            *methoddata;
+};
+/*
+ * Every authentication method has to handle authentication requests for
+ * non-existing users, or for users that are not allowed to login. In this
+ * case 'valid' is set to 0, but 'user' points to the username requested by
+ * the client.
+ */
+
+struct Authmethod {
+       char    *name;
+       int     (*userauth)(Authctxt *authctxt);
+       int     *enabled;
+};
+
+/*
+ * Keyboard interactive device:
+ * init_ctx    returns: non NULL upon success
+ * query       returns: 0 - success, otherwise failure
+ * respond     returns: 0 - success, 1 - need further interaction,
+ *             otherwise - failure
+ */
+struct KbdintDevice
+{
+       const char *name;
+       void*   (*init_ctx)(Authctxt*);
+       int     (*query)(void *ctx, char **name, char **infotxt,
+                   u_int *numprompts, char ***prompts, u_int **echo_on);
+       int     (*respond)(void *ctx, u_int numresp, char **responses);
+       void    (*free_ctx)(void *ctx);
+};
+
+int      auth_rhosts(struct passwd *, const char *);
+int
+auth_rhosts2(struct passwd *, const char *, const char *, const char *);
+
+int     auth_rhosts_rsa(Authctxt *, char *, Key *);
+int      auth_password(Authctxt *, const char *);
+int      auth_rsa(Authctxt *, BIGNUM *);
+int      auth_rsa_challenge_dialog(Key *);
+BIGNUM *auth_rsa_generate_challenge(Key *);
+int     auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
+int     auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
+
+int     auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
+int     hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
+int     user_key_allowed(struct passwd *, Key *);
+
+#ifdef KRB5
+int    auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
+int    auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
+int    auth_krb5_password(Authctxt *authctxt, const char *password);
+void   krb5_cleanup_proc(Authctxt *authctxt);
+#endif /* KRB5 */
+
+#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
+#include <shadow.h>
+int auth_shadow_acctexpired(struct spwd *);
+int auth_shadow_pwexpired(Authctxt *);
+#endif
+
+#include "auth-pam.h"
+#include "audit.h"
+void remove_kbdint_device(const char *);
+
+void disable_forwarding(void);
+
+void   do_authentication(Authctxt *);
+void   do_authentication2(Authctxt *);
+
+void   auth_log(Authctxt *, int, char *, char *);
+void   userauth_finish(Authctxt *, int, char *);
+void   userauth_send_banner(const char *);
+int    auth_root_allowed(char *);
+
+char   *auth2_read_banner(void);
+
+void   privsep_challenge_enable(void);
+
+int    auth2_challenge(Authctxt *, char *);
+void   auth2_challenge_stop(Authctxt *);
+int    bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
+int    bsdauth_respond(void *, u_int, char **);
+int    skey_query(void *, char **, char **, u_int *, char ***, u_int **);
+int    skey_respond(void *, u_int, char **);
+
+void   auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **);
+void   auth2_jpake_stop(Authctxt *);
+
+int    allowed_user(struct passwd *);
+struct passwd * getpwnamallow(const char *user);
+
+char   *get_challenge(Authctxt *);
+int    verify_response(Authctxt *, const char *);
+void   abandon_challenge_response(Authctxt *);
+
+char   *expand_authorized_keys(const char *, struct passwd *pw);
+char   *authorized_principals_file(struct passwd *);
+
+FILE   *auth_openkeyfile(const char *, struct passwd *, int);
+FILE   *auth_openprincipals(const char *, struct passwd *, int);
+int     auth_key_is_revoked(Key *);
+
+HostStatus
+check_key_in_hostfiles(struct passwd *, Key *, const char *,
+    const char *, const char *);
+
+/* hostkey handling */
+Key    *get_hostkey_by_index(int);
+Key    *get_hostkey_public_by_type(int);
+Key    *get_hostkey_private_by_type(int);
+int     get_hostkey_index(Key *);
+int     ssh1_session_key(BIGNUM *);
+
+/* debug messages during authentication */
+void    auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
+void    auth_debug_send(void);
+void    auth_debug_reset(void);
+
+struct passwd *fakepw(void);
+
+int     sys_auth_passwd(Authctxt *, const char *);
+
+#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
+
+#define SKEY_PROMPT "\nS/Key Password: "
+
+#if defined(KRB5) && !defined(HEIMDAL)
+#include <krb5.h>
+krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
+#endif
+#endif
diff --git a/.pc/ssh-vulnkey.patch/auth2-hostbased.c b/.pc/ssh-vulnkey.patch/auth2-hostbased.c
new file mode 100644 (file)
index 0000000..cdf442f
--- /dev/null
@@ -0,0 +1,220 @@
+/* $OpenBSD: auth2-hostbased.c,v 1.14 2010/08/04 05:42:47 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <pwd.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "xmalloc.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "canohost.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "pathnames.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern u_int session_id2_len;
+
+static int
+userauth_hostbased(Authctxt *authctxt)
+{
+       Buffer b;
+       Key *key = NULL;
+       char *pkalg, *cuser, *chost, *service;
+       u_char *pkblob, *sig;
+       u_int alen, blen, slen;
+       int pktype;
+       int authenticated = 0;
+
+       if (!authctxt->valid) {
+               debug2("userauth_hostbased: disabled because of invalid user");
+               return 0;
+       }
+       pkalg = packet_get_string(&alen);
+       pkblob = packet_get_string(&blen);
+       chost = packet_get_string(NULL);
+       cuser = packet_get_string(NULL);
+       sig = packet_get_string(&slen);
+
+       debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
+           cuser, chost, pkalg, slen);
+#ifdef DEBUG_PK
+       debug("signature:");
+       buffer_init(&b);
+       buffer_append(&b, sig, slen);
+       buffer_dump(&b);
+       buffer_free(&b);
+#endif
+       pktype = key_type_from_name(pkalg);
+       if (pktype == KEY_UNSPEC) {
+               /* this is perfectly legal */
+               logit("userauth_hostbased: unsupported "
+                   "public key algorithm: %s", pkalg);
+               goto done;
+       }
+       key = key_from_blob(pkblob, blen);
+       if (key == NULL) {
+               error("userauth_hostbased: cannot decode key: %s", pkalg);
+               goto done;
+       }
+       if (key->type != pktype) {
+               error("userauth_hostbased: type mismatch for decoded key "
+                   "(received %d, expected %d)", key->type, pktype);
+               goto done;
+       }
+       service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
+           authctxt->service;
+       buffer_init(&b);
+       buffer_put_string(&b, session_id2, session_id2_len);
+       /* reconstruct packet */
+       buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+       buffer_put_cstring(&b, authctxt->user);
+       buffer_put_cstring(&b, service);
+       buffer_put_cstring(&b, "hostbased");
+       buffer_put_string(&b, pkalg, alen);
+       buffer_put_string(&b, pkblob, blen);
+       buffer_put_cstring(&b, chost);
+       buffer_put_cstring(&b, cuser);
+#ifdef DEBUG_PK
+       buffer_dump(&b);
+#endif
+       /* test for allowed key and correct signature */
+       authenticated = 0;
+       if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
+           PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+                       buffer_len(&b))) == 1)
+               authenticated = 1;
+
+       buffer_free(&b);
+done:
+       debug2("userauth_hostbased: authenticated %d", authenticated);
+       if (key != NULL)
+               key_free(key);
+       xfree(pkalg);
+       xfree(pkblob);
+       xfree(cuser);
+       xfree(chost);
+       xfree(sig);
+       return authenticated;
+}
+
+/* return 1 if given hostkey is allowed */
+int
+hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
+    Key *key)
+{
+       const char *resolvedname, *ipaddr, *lookup, *reason;
+       HostStatus host_status;
+       int len;
+       char *fp;
+
+       if (auth_key_is_revoked(key))
+               return 0;
+
+       resolvedname = get_canonical_hostname(options.use_dns);
+       ipaddr = get_remote_ipaddr();
+
+       debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
+           chost, resolvedname, ipaddr);
+
+       if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
+               debug2("stripping trailing dot from chost %s", chost);
+               chost[len - 1] = '\0';
+       }
+
+       if (options.hostbased_uses_name_from_packet_only) {
+               if (auth_rhosts2(pw, cuser, chost, chost) == 0)
+                       return 0;
+               lookup = chost;
+       } else {
+               if (strcasecmp(resolvedname, chost) != 0)
+                       logit("userauth_hostbased mismatch: "
+                           "client sends %s, but we resolve %s to %s",
+                           chost, ipaddr, resolvedname);
+               if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
+                       return 0;
+               lookup = resolvedname;
+       }
+       debug2("userauth_hostbased: access allowed by auth_rhosts2");
+
+       if (key_is_cert(key) && 
+           key_cert_check_authority(key, 1, 0, lookup, &reason)) {
+               error("%s", reason);
+               auth_debug_add("%s", reason);
+               return 0;
+       }
+
+       host_status = check_key_in_hostfiles(pw, key, lookup,
+           _PATH_SSH_SYSTEM_HOSTFILE,
+           options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
+
+       /* backward compat if no key has been found. */
+       if (host_status == HOST_NEW) {
+               host_status = check_key_in_hostfiles(pw, key, lookup,
+                   _PATH_SSH_SYSTEM_HOSTFILE2,
+                   options.ignore_user_known_hosts ? NULL :
+                   _PATH_SSH_USER_HOSTFILE2);
+       }
+
+       if (host_status == HOST_OK) {
+               if (key_is_cert(key)) {
+                       fp = key_fingerprint(key->cert->signature_key,
+                           SSH_FP_MD5, SSH_FP_HEX);
+                       verbose("Accepted certificate ID \"%s\" signed by "
+                           "%s CA %s from %s@%s", key->cert->key_id,
+                           key_type(key->cert->signature_key), fp,
+                           cuser, lookup);
+               } else {
+                       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+                       verbose("Accepted %s public key %s from %s@%s",
+                           key_type(key), fp, cuser, lookup);
+               }
+               xfree(fp);
+       }
+
+       return (host_status == HOST_OK);
+}
+
+Authmethod method_hostbased = {
+       "hostbased",
+       userauth_hostbased,
+       &options.hostbased_authentication
+};
diff --git a/.pc/ssh-vulnkey.patch/auth2-pubkey.c b/.pc/ssh-vulnkey.patch/auth2-pubkey.c
new file mode 100644 (file)
index 0000000..137887e
--- /dev/null
@@ -0,0 +1,465 @@
+/* $OpenBSD: auth2-pubkey.c,v 1.29 2011/05/23 03:30:07 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "pathnames.h"
+#include "uidswap.h"
+#include "auth-options.h"
+#include "canohost.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "misc.h"
+#include "authfile.h"
+#include "match.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern u_int session_id2_len;
+
+static int
+userauth_pubkey(Authctxt *authctxt)
+{
+       Buffer b;
+       Key *key = NULL;
+       char *pkalg;
+       u_char *pkblob, *sig;
+       u_int alen, blen, slen;
+       int have_sig, pktype;
+       int authenticated = 0;
+
+       if (!authctxt->valid) {
+               debug2("userauth_pubkey: disabled because of invalid user");
+               return 0;
+       }
+       have_sig = packet_get_char();
+       if (datafellows & SSH_BUG_PKAUTH) {
+               debug2("userauth_pubkey: SSH_BUG_PKAUTH");
+               /* no explicit pkalg given */
+               pkblob = packet_get_string(&blen);
+               buffer_init(&b);
+               buffer_append(&b, pkblob, blen);
+               /* so we have to extract the pkalg from the pkblob */
+               pkalg = buffer_get_string(&b, &alen);
+               buffer_free(&b);
+       } else {
+               pkalg = packet_get_string(&alen);
+               pkblob = packet_get_string(&blen);
+       }
+       pktype = key_type_from_name(pkalg);
+       if (pktype == KEY_UNSPEC) {
+               /* this is perfectly legal */
+               logit("userauth_pubkey: unsupported public key algorithm: %s",
+                   pkalg);
+               goto done;
+       }
+       key = key_from_blob(pkblob, blen);
+       if (key == NULL) {
+               error("userauth_pubkey: cannot decode key: %s", pkalg);
+               goto done;
+       }
+       if (key->type != pktype) {
+               error("userauth_pubkey: type mismatch for decoded key "
+                   "(received %d, expected %d)", key->type, pktype);
+               goto done;
+       }
+       if (have_sig) {
+               sig = packet_get_string(&slen);
+               packet_check_eom();
+               buffer_init(&b);
+               if (datafellows & SSH_OLD_SESSIONID) {
+                       buffer_append(&b, session_id2, session_id2_len);
+               } else {
+                       buffer_put_string(&b, session_id2, session_id2_len);
+               }
+               /* reconstruct packet */
+               buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+               buffer_put_cstring(&b, authctxt->user);
+               buffer_put_cstring(&b,
+                   datafellows & SSH_BUG_PKSERVICE ?
+                   "ssh-userauth" :
+                   authctxt->service);
+               if (datafellows & SSH_BUG_PKAUTH) {
+                       buffer_put_char(&b, have_sig);
+               } else {
+                       buffer_put_cstring(&b, "publickey");
+                       buffer_put_char(&b, have_sig);
+                       buffer_put_cstring(&b, pkalg);
+               }
+               buffer_put_string(&b, pkblob, blen);
+#ifdef DEBUG_PK
+               buffer_dump(&b);
+#endif
+               /* test for correct signature */
+               authenticated = 0;
+               if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
+                   PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+                   buffer_len(&b))) == 1)
+                       authenticated = 1;
+               buffer_free(&b);
+               xfree(sig);
+       } else {
+               debug("test whether pkalg/pkblob are acceptable");
+               packet_check_eom();
+
+               /* XXX fake reply and always send PK_OK ? */
+               /*
+                * XXX this allows testing whether a user is allowed
+                * to login: if you happen to have a valid pubkey this
+                * message is sent. the message is NEVER sent at all
+                * if a user is not allowed to login. is this an
+                * issue? -markus
+                */
+               if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
+                       packet_start(SSH2_MSG_USERAUTH_PK_OK);
+                       packet_put_string(pkalg, alen);
+                       packet_put_string(pkblob, blen);
+                       packet_send();
+                       packet_write_wait();
+                       authctxt->postponed = 1;
+               }
+       }
+       if (authenticated != 1)
+               auth_clear_options();
+done:
+       debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
+       if (key != NULL)
+               key_free(key);
+       xfree(pkalg);
+       xfree(pkblob);
+       return authenticated;
+}
+
+static int
+match_principals_option(const char *principal_list, struct KeyCert *cert)
+{
+       char *result;
+       u_int i;
+
+       /* XXX percent_expand() sequences for authorized_principals? */
+
+       for (i = 0; i < cert->nprincipals; i++) {
+               if ((result = match_list(cert->principals[i],
+                   principal_list, NULL)) != NULL) {
+                       debug3("matched principal from key options \"%.100s\"",
+                           result);
+                       xfree(result);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int
+match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
+{
+       FILE *f;
+       char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
+       u_long linenum = 0;
+       u_int i;
+
+       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;
+       }
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               /* Skip leading whitespace. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               /* Skip blank and comment lines. */
+               if ((ep = strchr(cp, '#')) != NULL)
+                       *ep = '\0';
+               if (!*cp || *cp == '\n')
+                       continue;
+               /* Trim trailing whitespace. */
+               ep = cp + strlen(cp) - 1;
+               while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
+                       *ep-- = '\0';
+               /*
+                * If the line has internal whitespace then assume it has
+                * key options.
+                */
+               line_opts = NULL;
+               if ((ep = strrchr(cp, ' ')) != NULL ||
+                   (ep = strrchr(cp, '\t')) != NULL) {
+                       for (; *ep == ' ' || *ep == '\t'; ep++)
+                               ;
+                       line_opts = cp;
+                       cp = ep;
+               }
+               for (i = 0; i < cert->nprincipals; i++) {
+                       if (strcmp(cp, cert->principals[i]) == 0) {
+                               debug3("matched principal from file \"%.100s\"",
+                                   cert->principals[i]);
+                               if (auth_parse_options(pw, line_opts,
+                                   file, linenum) != 1)
+                                       continue;
+                               fclose(f);
+                               restore_uid();
+                               return 1;
+                       }
+               }
+       }
+       fclose(f);
+       restore_uid();
+       return 0;
+}      
+
+/* return 1 if user allows given key */
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
+{
+       char line[SSH_MAX_PUBKEY_BYTES];
+       const char *reason;
+       int found_key = 0;
+       FILE *f;
+       u_long linenum = 0;
+       Key *found;
+       char *fp;
+
+       /* Temporarily use the user's uid. */
+       temporarily_use_uid(pw);
+
+       debug("trying public key file %s", file);
+       f = auth_openkeyfile(file, pw, options.strict_modes);
+
+       if (!f) {
+               restore_uid();
+               return 0;
+       }
+
+       found_key = 0;
+       found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
+
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               char *cp, *key_options = NULL;
+
+               auth_clear_options();
+
+               /* Skip leading whitespace, empty and comment lines. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               if (!*cp || *cp == '\n' || *cp == '#')
+                       continue;
+
+               if (key_read(found, &cp) != 1) {
+                       /* no key?  check if there are options for this key */
+                       int quoted = 0;
+                       debug2("user_key_allowed: check options: '%s'", cp);
+                       key_options = cp;
+                       for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
+                               if (*cp == '\\' && cp[1] == '"')
+                                       cp++;   /* Skip both */
+                               else if (*cp == '"')
+                                       quoted = !quoted;
+                       }
+                       /* Skip remaining whitespace. */
+                       for (; *cp == ' ' || *cp == '\t'; cp++)
+                               ;
+                       if (key_read(found, &cp) != 1) {
+                               debug2("user_key_allowed: advance: '%s'", cp);
+                               /* still no key?  advance to next line*/
+                               continue;
+                       }
+               }
+               if (key_is_cert(key)) {
+                       if (!key_equal(found, key->cert->signature_key))
+                               continue;
+                       if (auth_parse_options(pw, key_options, file,
+                           linenum) != 1)
+                               continue;
+                       if (!key_is_cert_authority)
+                               continue;
+                       fp = key_fingerprint(found, SSH_FP_MD5,
+                           SSH_FP_HEX);
+                       debug("matching CA found: file %s, line %lu, %s %s",
+                           file, linenum, key_type(found), fp);
+                       /*
+                        * If the user has specified a list of principals as
+                        * a key option, then prefer that list to matching
+                        * their username in the certificate principals list.
+                        */
+                       if (authorized_principals != NULL &&
+                           !match_principals_option(authorized_principals,
+                           key->cert)) {
+                               reason = "Certificate does not contain an "
+                                   "authorized principal";
+ fail_reason:
+                               xfree(fp);
+                               error("%s", reason);
+                               auth_debug_add("%s", reason);
+                               continue;
+                       }
+                       if (key_cert_check_authority(key, 0, 0,
+                           authorized_principals == NULL ? pw->pw_name : NULL,
+                           &reason) != 0)
+                               goto fail_reason;
+                       if (auth_cert_options(key, pw) != 0) {
+                               xfree(fp);
+                               continue;
+                       }
+                       verbose("Accepted certificate ID \"%s\" "
+                           "signed by %s CA %s via %s", key->cert->key_id,
+                           key_type(found), fp, file);
+                       xfree(fp);
+                       found_key = 1;
+                       break;
+               } else if (key_equal(found, key)) {
+                       if (auth_parse_options(pw, key_options, file,
+                           linenum) != 1)
+                               continue;
+                       if (key_is_cert_authority)
+                               continue;
+                       found_key = 1;
+                       debug("matching key found: file %s, line %lu",
+                           file, linenum);
+                       fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+                       verbose("Found matching %s key: %s",
+                           key_type(found), fp);
+                       xfree(fp);
+                       break;
+               }
+       }
+       restore_uid();
+       fclose(f);
+       key_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, Key *key)
+{
+       char *ca_fp, *principals_file = NULL;
+       const char *reason;
+       int ret = 0;
+
+       if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
+               return 0;
+
+       ca_fp = key_fingerprint(key->cert->signature_key,
+           SSH_FP_MD5, SSH_FP_HEX);
+
+       if (key_in_file(key->cert->signature_key,
+           options.trusted_user_ca_keys, 1) != 1) {
+               debug2("%s: CA %s %s is not listed in %s", __func__,
+                   key_type(key->cert->signature_key), ca_fp,
+                   options.trusted_user_ca_keys);
+               goto out;
+       }
+       /*
+        * If AuthorizedPrincipals is in use, then compare the certificate
+        * principals against the names in that file rather than matching
+        * against the username.
+        */
+       if ((principals_file = authorized_principals_file(pw)) != NULL) {
+               if (!match_principals_file(principals_file, pw, key->cert)) {
+                       reason = "Certificate does not contain an "
+                           "authorized principal";
+ fail_reason:
+                       error("%s", reason);
+                       auth_debug_add("%s", reason);
+                       goto out;
+               }
+       }
+       if (key_cert_check_authority(key, 0, 1,
+           principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
+               goto fail_reason;
+       if (auth_cert_options(key, pw) != 0)
+               goto out;
+
+       verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
+           key->cert->key_id, key_type(key->cert->signature_key), ca_fp,
+           options.trusted_user_ca_keys);
+       ret = 1;
+
+ out:
+       if (principals_file != NULL)
+               xfree(principals_file);
+       if (ca_fp != NULL)
+               xfree(ca_fp);
+       return ret;
+}
+
+/* check whether given key is in .ssh/authorized_keys* */
+int
+user_key_allowed(struct passwd *pw, Key *key)
+{
+       u_int success, i;
+       char *file;
+
+       if (auth_key_is_revoked(key))
+               return 0;
+       if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+               return 0;
+
+       success = user_cert_trusted_ca(pw, key);
+       if (success)
+               return success;
+
+       for (i = 0; !success && i < options.num_authkeys_files; i++) {
+               file = expand_authorized_keys(
+                   options.authorized_keys_files[i], pw);
+               success = user_key_allowed2(pw, key, file);
+               xfree(file);
+       }
+
+       return success;
+}
+
+Authmethod method_pubkey = {
+       "publickey",
+       userauth_pubkey,
+       &options.pubkey_authentication
+};
diff --git a/.pc/ssh-vulnkey.patch/authfile.c b/.pc/ssh-vulnkey.patch/authfile.c
new file mode 100644 (file)
index 0000000..1d7e53c
--- /dev/null
@@ -0,0 +1,946 @@
+/* $OpenBSD: authfile.c,v 1.92 2011/06/14 22:49:18 markus Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * This file contains functions for reading and writing identity files, and
+ * for reading the passphrase from the user.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ *
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+
+/* compatibility with old or broken OpenSSL versions */
+#include "openbsd-compat/openssl-compat.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "cipher.h"
+#include "buffer.h"
+#include "key.h"
+#include "ssh.h"
+#include "log.h"
+#include "authfile.h"
+#include "rsa.h"
+#include "misc.h"
+#include "atomicio.h"
+
+#define MAX_KEY_FILE_SIZE      (1024 * 1024)
+
+/* Version identification string for SSH v1 identity files. */
+static const char authfile_id_string[] =
+    "SSH PRIVATE KEY FILE FORMAT 1.1\n";
+
+/*
+ * Serialises the authentication (private) key to a blob, encrypting it with
+ * passphrase.  The identification of the blob (lowest 64 bits of n) will
+ * precede the key to provide identification of the key without needing a
+ * passphrase.
+ */
+static int
+key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
+    const char *comment)
+{
+       Buffer buffer, encrypted;
+       u_char buf[100], *cp;
+       int i, cipher_num;
+       CipherContext ciphercontext;
+       Cipher *cipher;
+       u_int32_t rnd;
+
+       /*
+        * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
+        * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
+        */
+       cipher_num = (strcmp(passphrase, "") == 0) ?
+           SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER;
+       if ((cipher = cipher_by_number(cipher_num)) == NULL)
+               fatal("save_private_key_rsa: bad cipher");
+
+       /* This buffer is used to built the secret part of the private key. */
+       buffer_init(&buffer);
+
+       /* Put checkbytes for checking passphrase validity. */
+       rnd = arc4random();
+       buf[0] = rnd & 0xff;
+       buf[1] = (rnd >> 8) & 0xff;
+       buf[2] = buf[0];
+       buf[3] = buf[1];
+       buffer_append(&buffer, buf, 4);
+
+       /*
+        * Store the private key (n and e will not be stored because they
+        * will be stored in plain text, and storing them also in encrypted
+        * format would just give known plaintext).
+        */
+       buffer_put_bignum(&buffer, key->rsa->d);
+       buffer_put_bignum(&buffer, key->rsa->iqmp);
+       buffer_put_bignum(&buffer, key->rsa->q);        /* reverse from SSL p */
+       buffer_put_bignum(&buffer, key->rsa->p);        /* reverse from SSL q */
+
+       /* Pad the part to be encrypted until its size is a multiple of 8. */
+       while (buffer_len(&buffer) % 8 != 0)
+               buffer_put_char(&buffer, 0);
+
+       /* This buffer will be used to contain the data in the file. */
+       buffer_init(&encrypted);
+
+       /* First store keyfile id string. */
+       for (i = 0; authfile_id_string[i]; i++)
+               buffer_put_char(&encrypted, authfile_id_string[i]);
+       buffer_put_char(&encrypted, 0);
+
+       /* Store cipher type. */
+       buffer_put_char(&encrypted, cipher_num);
+       buffer_put_int(&encrypted, 0);  /* For future extension */
+
+       /* Store public key.  This will be in plain text. */
+       buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
+       buffer_put_bignum(&encrypted, key->rsa->n);
+       buffer_put_bignum(&encrypted, key->rsa->e);
+       buffer_put_cstring(&encrypted, comment);
+
+       /* Allocate space for the private part of the key in the buffer. */
+       cp = buffer_append_space(&encrypted, buffer_len(&buffer));
+
+       cipher_set_key_string(&ciphercontext, cipher, passphrase,
+           CIPHER_ENCRYPT);
+       cipher_crypt(&ciphercontext, cp,
+           buffer_ptr(&buffer), buffer_len(&buffer));
+       cipher_cleanup(&ciphercontext);
+       memset(&ciphercontext, 0, sizeof(ciphercontext));
+
+       /* Destroy temporary data. */
+       memset(buf, 0, sizeof(buf));
+       buffer_free(&buffer);
+
+       buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted));
+       buffer_free(&encrypted);
+
+       return 1;
+}
+
+/* convert SSH v2 key in OpenSSL PEM format */
+static int
+key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase,
+    const char *comment)
+{
+       int success = 0;
+       int blen, len = strlen(_passphrase);
+       u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
+#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
+       const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
+#else
+       const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
+#endif
+       const u_char *bptr;
+       BIO *bio;
+
+       if (len > 0 && len <= 4) {
+               error("passphrase too short: have %d bytes, need > 4", len);
+               return 0;
+       }
+       if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+               error("%s: BIO_new failed", __func__);
+               return 0;
+       }
+       switch (key->type) {
+       case KEY_DSA:
+               success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
+                   cipher, passphrase, len, NULL, NULL);
+               break;
+#ifdef OPENSSL_HAS_ECC
+       case KEY_ECDSA:
+               success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
+                   cipher, passphrase, len, NULL, NULL);
+               break;
+#endif
+       case KEY_RSA:
+               success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
+                   cipher, passphrase, len, NULL, NULL);
+               break;
+       }
+       if (success) {
+               if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
+                       success = 0;
+               else
+                       buffer_append(blob, bptr, blen);
+       }
+       BIO_free(bio);
+       return success;
+}
+
+/* Save a key blob to a file */
+static int
+key_save_private_blob(Buffer *keybuf, const char *filename)
+{
+       int fd;
+
+       if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
+               error("open %s failed: %s.", filename, strerror(errno));
+               return 0;
+       }
+       if (atomicio(vwrite, fd, buffer_ptr(keybuf),
+           buffer_len(keybuf)) != buffer_len(keybuf)) {
+               error("write to key file %s failed: %s", filename,
+                   strerror(errno));
+               close(fd);
+               unlink(filename);
+               return 0;
+       }
+       close(fd);
+       return 1;
+}
+
+/* Serialise "key" to buffer "blob" */
+static int
+key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
+    const char *comment)
+{
+       switch (key->type) {
+       case KEY_RSA1:
+               return key_private_rsa1_to_blob(key, blob, passphrase, comment);
+       case KEY_DSA:
+       case KEY_ECDSA:
+       case KEY_RSA:
+               return key_private_pem_to_blob(key, blob, passphrase, comment);
+       default:
+               error("%s: cannot save key type %d", __func__, key->type);
+               return 0;
+       }
+}
+
+int
+key_save_private(Key *key, const char *filename, const char *passphrase,
+    const char *comment)
+{
+       Buffer keyblob;
+       int success = 0;
+
+       buffer_init(&keyblob);
+       if (!key_private_to_blob(key, &keyblob, passphrase, comment))
+               goto out;
+       if (!key_save_private_blob(&keyblob, filename))
+               goto out;
+       success = 1;
+ out:
+       buffer_free(&keyblob);
+       return success;
+}
+
+/*
+ * Parse the public, unencrypted portion of a RSA1 key.
+ */
+static Key *
+key_parse_public_rsa1(Buffer *blob, char **commentp)
+{
+       Key *pub;
+       Buffer copy;
+
+       /* Check that it is at least big enough to contain the ID string. */
+       if (buffer_len(blob) < sizeof(authfile_id_string)) {
+               debug3("Truncated RSA1 identifier");
+               return NULL;
+       }
+
+       /*
+        * Make sure it begins with the id string.  Consume the id string
+        * from the buffer.
+        */
+       if (memcmp(buffer_ptr(blob), authfile_id_string,
+           sizeof(authfile_id_string)) != 0) {
+               debug3("Incorrect RSA1 identifier");
+               return NULL;
+       }
+       buffer_init(&copy);
+       buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
+       buffer_consume(&copy, sizeof(authfile_id_string));
+
+       /* Skip cipher type and reserved data. */
+       (void) buffer_get_char(&copy);          /* cipher type */
+       (void) buffer_get_int(&copy);           /* reserved */
+
+       /* Read the public key from the buffer. */
+       (void) buffer_get_int(&copy);
+       pub = key_new(KEY_RSA1);
+       buffer_get_bignum(&copy, pub->rsa->n);
+       buffer_get_bignum(&copy, pub->rsa->e);
+       if (commentp)
+               *commentp = buffer_get_string(&copy, NULL);
+       /* The encrypted private part is not parsed by this function. */
+       buffer_free(&copy);
+
+       return pub;
+}
+
+/* Load a key from a fd into a buffer */
+int
+key_load_file(int fd, const char *filename, Buffer *blob)
+{
+       u_char buf[1024];
+       size_t len;
+       struct stat st;
+
+       if (fstat(fd, &st) < 0) {
+               error("%s: fstat of key file %.200s%sfailed: %.100s", __func__,
+                   filename == NULL ? "" : filename,
+                   filename == NULL ? "" : " ",
+                   strerror(errno));
+               return 0;
+       }
+       if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+           st.st_size > MAX_KEY_FILE_SIZE) {
+ toobig:
+               error("%s: key file %.200s%stoo large", __func__,
+                   filename == NULL ? "" : filename,
+                   filename == NULL ? "" : " ");
+               return 0;
+       }
+       buffer_init(blob);
+       for (;;) {
+               if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
+                       if (errno == EPIPE)
+                               break;
+                       debug("%s: read from key file %.200s%sfailed: %.100s",
+                           __func__, filename == NULL ? "" : filename,
+                           filename == NULL ? "" : " ", strerror(errno));
+                       buffer_clear(blob);
+                       bzero(buf, sizeof(buf));
+                       return 0;
+               }
+               buffer_append(blob, buf, len);
+               if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
+                       buffer_clear(blob);
+                       bzero(buf, sizeof(buf));
+                       goto toobig;
+               }
+       }
+       bzero(buf, sizeof(buf));
+       if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+           st.st_size != buffer_len(blob)) {
+               debug("%s: key file %.200s%schanged size while reading",
+                   __func__, filename == NULL ? "" : filename,
+                   filename == NULL ? "" : " ");
+               buffer_clear(blob);
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
+ * encountered (the file does not exist or is not readable), and the key
+ * otherwise.
+ */
+static Key *
+key_load_public_rsa1(int fd, const char *filename, char **commentp)
+{
+       Buffer buffer;
+       Key *pub;
+
+       buffer_init(&buffer);
+       if (!key_load_file(fd, filename, &buffer)) {
+               buffer_free(&buffer);
+               return NULL;
+       }
+
+       pub = key_parse_public_rsa1(&buffer, commentp);
+       if (pub == NULL)
+               debug3("Could not load \"%s\" as a RSA1 public key", filename);
+       buffer_free(&buffer);
+       return pub;
+}
+
+/* load public key from private-key file, works only for SSH v1 */
+Key *
+key_load_public_type(int type, const char *filename, char **commentp)
+{
+       Key *pub;
+       int fd;
+
+       if (type == KEY_RSA1) {
+               fd = open(filename, O_RDONLY);
+               if (fd < 0)
+                       return NULL;
+               pub = key_load_public_rsa1(fd, filename, commentp);
+               close(fd);
+               return pub;
+       }
+       return NULL;
+}
+
+static Key *
+key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
+{
+       int check1, check2, cipher_type;
+       Buffer decrypted;
+       u_char *cp;
+       CipherContext ciphercontext;
+       Cipher *cipher;
+       Key *prv = NULL;
+       Buffer copy;
+
+       /* Check that it is at least big enough to contain the ID string. */
+       if (buffer_len(blob) < sizeof(authfile_id_string)) {
+               debug3("Truncated RSA1 identifier");
+               return NULL;
+       }
+
+       /*
+        * Make sure it begins with the id string.  Consume the id string
+        * from the buffer.
+        */
+       if (memcmp(buffer_ptr(blob), authfile_id_string,
+           sizeof(authfile_id_string)) != 0) {
+               debug3("Incorrect RSA1 identifier");
+               return NULL;
+       }
+       buffer_init(&copy);
+       buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
+       buffer_consume(&copy, sizeof(authfile_id_string));
+
+       /* Read cipher type. */
+       cipher_type = buffer_get_char(&copy);
+       (void) buffer_get_int(&copy);   /* Reserved data. */
+
+       /* Read the public key from the buffer. */
+       (void) buffer_get_int(&copy);
+       prv = key_new_private(KEY_RSA1);
+
+       buffer_get_bignum(&copy, prv->rsa->n);
+       buffer_get_bignum(&copy, prv->rsa->e);
+       if (commentp)
+               *commentp = buffer_get_string(&copy, NULL);
+       else
+               (void)buffer_get_string_ptr(&copy, NULL);
+
+       /* Check that it is a supported cipher. */
+       cipher = cipher_by_number(cipher_type);
+       if (cipher == NULL) {
+               debug("Unsupported RSA1 cipher %d", cipher_type);
+               buffer_free(&copy);
+               goto fail;
+       }
+       /* Initialize space for decrypted data. */
+       buffer_init(&decrypted);
+       cp = buffer_append_space(&decrypted, buffer_len(&copy));
+
+       /* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
+       cipher_set_key_string(&ciphercontext, cipher, passphrase,
+           CIPHER_DECRYPT);
+       cipher_crypt(&ciphercontext, cp,
+           buffer_ptr(&copy), buffer_len(&copy));
+       cipher_cleanup(&ciphercontext);
+       memset(&ciphercontext, 0, sizeof(ciphercontext));
+       buffer_free(&copy);
+
+       check1 = buffer_get_char(&decrypted);
+       check2 = buffer_get_char(&decrypted);
+       if (check1 != buffer_get_char(&decrypted) ||
+           check2 != buffer_get_char(&decrypted)) {
+               if (strcmp(passphrase, "") != 0)
+                       debug("Bad passphrase supplied for RSA1 key");
+               /* Bad passphrase. */
+               buffer_free(&decrypted);
+               goto fail;
+       }
+       /* Read the rest of the private key. */
+       buffer_get_bignum(&decrypted, prv->rsa->d);
+       buffer_get_bignum(&decrypted, prv->rsa->iqmp);          /* u */
+       /* in SSL and SSH v1 p and q are exchanged */
+       buffer_get_bignum(&decrypted, prv->rsa->q);             /* p */
+       buffer_get_bignum(&decrypted, prv->rsa->p);             /* q */
+
+       /* calculate p-1 and q-1 */
+       rsa_generate_additional_parameters(prv->rsa);
+
+       buffer_free(&decrypted);
+
+       /* enable blinding */
+       if (RSA_blinding_on(prv->rsa, NULL) != 1) {
+               error("%s: RSA_blinding_on failed", __func__);
+               goto fail;
+       }
+       return prv;
+
+fail:
+       if (commentp)
+               xfree(*commentp);
+       key_free(prv);
+       return NULL;
+}
+
+static Key *
+key_parse_private_pem(Buffer *blob, int type, const char *passphrase,
+    char **commentp)
+{
+       EVP_PKEY *pk = NULL;
+       Key *prv = NULL;
+       char *name = "<no key>";
+       BIO *bio;
+
+       if ((bio = BIO_new_mem_buf(buffer_ptr(blob),
+           buffer_len(blob))) == NULL) {
+               error("%s: BIO_new_mem_buf failed", __func__);
+               return NULL;
+       }
+       
+       pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase);
+       BIO_free(bio);
+       if (pk == NULL) {
+               debug("%s: PEM_read_PrivateKey failed", __func__);
+               (void)ERR_get_error();
+       } else if (pk->type == EVP_PKEY_RSA &&
+           (type == KEY_UNSPEC||type==KEY_RSA)) {
+               prv = key_new(KEY_UNSPEC);
+               prv->rsa = EVP_PKEY_get1_RSA(pk);
+               prv->type = KEY_RSA;
+               name = "rsa w/o comment";
+#ifdef DEBUG_PK
+               RSA_print_fp(stderr, prv->rsa, 8);
+#endif
+               if (RSA_blinding_on(prv->rsa, NULL) != 1) {
+                       error("%s: RSA_blinding_on failed", __func__);
+                       key_free(prv);
+                       prv = NULL;
+               }
+       } else if (pk->type == EVP_PKEY_DSA &&
+           (type == KEY_UNSPEC||type==KEY_DSA)) {
+               prv = key_new(KEY_UNSPEC);
+               prv->dsa = EVP_PKEY_get1_DSA(pk);
+               prv->type = KEY_DSA;
+               name = "dsa w/o comment";
+#ifdef DEBUG_PK
+               DSA_print_fp(stderr, prv->dsa, 8);
+#endif
+#ifdef OPENSSL_HAS_ECC
+       } else if (pk->type == EVP_PKEY_EC &&
+           (type == KEY_UNSPEC||type==KEY_ECDSA)) {
+               prv = key_new(KEY_UNSPEC);
+               prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
+               prv->type = KEY_ECDSA;
+               if ((prv->ecdsa_nid = key_ecdsa_key_to_nid(prv->ecdsa)) == -1 ||
+                   key_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
+                   key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
+                   EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
+                   key_ec_validate_private(prv->ecdsa) != 0) {
+                       error("%s: bad ECDSA key", __func__);
+                       key_free(prv);
+                       prv = NULL;
+               }
+               name = "ecdsa w/o comment";
+#ifdef DEBUG_PK
+               if (prv != NULL && prv->ecdsa != NULL)
+                       key_dump_ec_key(prv->ecdsa);
+#endif
+#endif /* OPENSSL_HAS_ECC */
+       } else {
+               error("%s: PEM_read_PrivateKey: mismatch or "
+                   "unknown EVP_PKEY save_type %d", __func__, pk->save_type);
+       }
+       if (pk != NULL)
+               EVP_PKEY_free(pk);
+       if (prv != NULL && commentp)
+               *commentp = xstrdup(name);
+       debug("read PEM private key done: type %s",
+           prv ? key_type(prv) : "<unknown>");
+       return prv;
+}
+
+Key *
+key_load_private_pem(int fd, int type, const char *passphrase,
+    char **commentp)
+{
+       Buffer buffer;
+       Key *prv;
+
+       buffer_init(&buffer);
+       if (!key_load_file(fd, NULL, &buffer)) {
+               buffer_free(&buffer);
+               return NULL;
+       }
+       prv = key_parse_private_pem(&buffer, type, passphrase, commentp);
+       buffer_free(&buffer);
+       return prv;
+}
+
+int
+key_perm_ok(int fd, const char *filename)
+{
+       struct stat st;
+
+       if (fstat(fd, &st) < 0)
+               return 0;
+       /*
+        * if a key owned by the user is accessed, then we check the
+        * permissions of the file. if the key owned by a different user,
+        * then we don't care.
+        */
+#ifdef HAVE_CYGWIN
+       if (check_ntsec(filename))
+#endif
+       if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
+               error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+               error("Permissions 0%3.3o for '%s' are too open.",
+                   (u_int)st.st_mode & 0777, filename);
+               error("It is required that your private key files are NOT accessible by others.");
+               error("This private key will be ignored.");
+               return 0;
+       }
+       return 1;
+}
+
+static Key *
+key_parse_private_type(Buffer *blob, int type, const char *passphrase,
+    char **commentp)
+{
+       switch (type) {
+       case KEY_RSA1:
+               return key_parse_private_rsa1(blob, passphrase, commentp);
+       case KEY_DSA:
+       case KEY_ECDSA:
+       case KEY_RSA:
+       case KEY_UNSPEC:
+               return key_parse_private_pem(blob, type, passphrase, commentp);
+       default:
+               error("%s: cannot parse key type %d", __func__, type);
+               break;
+       }
+       return NULL;
+}
+
+Key *
+key_load_private_type(int type, const char *filename, const char *passphrase,
+    char **commentp, int *perm_ok)
+{
+       int fd;
+       Key *ret;
+       Buffer buffer;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
+               debug("could not open key file '%s': %s", filename,
+                   strerror(errno));
+               if (perm_ok != NULL)
+                       *perm_ok = 0;
+               return NULL;
+       }
+       if (!key_perm_ok(fd, filename)) {
+               if (perm_ok != NULL)
+                       *perm_ok = 0;
+               error("bad permissions: ignore key: %s", filename);
+               close(fd);
+               return NULL;
+       }
+       if (perm_ok != NULL)
+               *perm_ok = 1;
+
+       buffer_init(&buffer);
+       if (!key_load_file(fd, filename, &buffer)) {
+               buffer_free(&buffer);
+               close(fd);
+               return NULL;
+       }
+       close(fd);
+       ret = key_parse_private_type(&buffer, type, passphrase, commentp);
+       buffer_free(&buffer);
+       return ret;
+}
+
+Key *
+key_parse_private(Buffer *buffer, const char *filename,
+    const char *passphrase, char **commentp)
+{
+       Key *pub, *prv;
+
+       /* it's a SSH v1 key if the public key part is readable */
+       pub = key_parse_public_rsa1(buffer, commentp);
+       if (pub == NULL) {
+               prv = key_parse_private_type(buffer, KEY_UNSPEC,
+                   passphrase, NULL);
+               /* use the filename as a comment for PEM */
+               if (commentp && prv)
+                       *commentp = xstrdup(filename);
+       } else {
+               key_free(pub);
+               /* key_parse_public_rsa1() has already loaded the comment */
+               prv = key_parse_private_type(buffer, KEY_RSA1, passphrase,
+                   NULL);
+       }
+       return prv;
+}
+
+Key *
+key_load_private(const char *filename, const char *passphrase,
+    char **commentp)
+{
+       Key *prv;
+       Buffer buffer;
+       int fd;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
+               debug("could not open key file '%s': %s", filename,
+                   strerror(errno));
+               return NULL;
+       }
+       if (!key_perm_ok(fd, filename)) {
+               error("bad permissions: ignore key: %s", filename);
+               close(fd);
+               return NULL;
+       }
+
+       buffer_init(&buffer);
+       if (!key_load_file(fd, filename, &buffer)) {
+               buffer_free(&buffer);
+               close(fd);
+               return NULL;
+       }
+       close(fd);
+
+       prv = key_parse_private(&buffer, filename, passphrase, commentp);
+       buffer_free(&buffer);
+       return prv;
+}
+
+static int
+key_try_load_public(Key *k, const char *filename, char **commentp)
+{
+       FILE *f;
+       char line[SSH_MAX_PUBKEY_BYTES];
+       char *cp;
+       u_long linenum = 0;
+
+       f = fopen(filename, "r");
+       if (f != NULL) {
+               while (read_keyfile_line(f, filename, line, sizeof(line),
+                           &linenum) != -1) {
+                       cp = line;
+                       switch (*cp) {
+                       case '#':
+                       case '\n':
+                       case '\0':
+                               continue;
+                       }
+                       /* Abort loading if this looks like a private key */
+                       if (strncmp(cp, "-----BEGIN", 10) == 0)
+                               break;
+                       /* Skip leading whitespace. */
+                       for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
+                               ;
+                       if (*cp) {
+                               if (key_read(k, &cp) == 1) {
+                                       cp[strcspn(cp, "\r\n")] = '\0';
+                                       if (commentp) {
+                                               *commentp = xstrdup(*cp ?
+                                                   cp : filename);
+                                       }
+                                       fclose(f);
+                                       return 1;
+                               }
+                       }
+               }
+               fclose(f);
+       }
+       return 0;
+}
+
+/* load public key from ssh v1 private or any pubkey file */
+Key *
+key_load_public(const char *filename, char **commentp)
+{
+       Key *pub;
+       char file[MAXPATHLEN];
+
+       /* try rsa1 private key */
+       pub = key_load_public_type(KEY_RSA1, filename, commentp);
+       if (pub != NULL)
+               return pub;
+
+       /* try rsa1 public key */
+       pub = key_new(KEY_RSA1);
+       if (key_try_load_public(pub, filename, commentp) == 1)
+               return pub;
+       key_free(pub);
+
+       /* try ssh2 public key */
+       pub = key_new(KEY_UNSPEC);
+       if (key_try_load_public(pub, filename, commentp) == 1)
+               return pub;
+       if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
+           (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
+           (key_try_load_public(pub, file, commentp) == 1))
+               return pub;
+       key_free(pub);
+       return NULL;
+}
+
+/* Load the certificate associated with the named private key */
+Key *
+key_load_cert(const char *filename)
+{
+       Key *pub;
+       char *file;
+
+       pub = key_new(KEY_UNSPEC);
+       xasprintf(&file, "%s-cert.pub", filename);
+       if (key_try_load_public(pub, file, NULL) == 1) {
+               xfree(file);
+               return pub;
+       }
+       xfree(file);
+       key_free(pub);
+       return NULL;
+}
+
+/* Load private key and certificate */
+Key *
+key_load_private_cert(int type, const char *filename, const char *passphrase,
+    int *perm_ok)
+{
+       Key *key, *pub;
+
+       switch (type) {
+       case KEY_RSA:
+       case KEY_DSA:
+       case KEY_ECDSA:
+               break;
+       default:
+               error("%s: unsupported key type", __func__);
+               return NULL;
+       }
+
+       if ((key = key_load_private_type(type, filename, 
+           passphrase, NULL, perm_ok)) == NULL)
+               return NULL;
+
+       if ((pub = key_load_cert(filename)) == NULL) {
+               key_free(key);
+               return NULL;
+       }
+
+       /* Make sure the private key matches the certificate */
+       if (key_equal_public(key, pub) == 0) {
+               error("%s: certificate does not match private key %s",
+                   __func__, filename);
+       } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) {
+               error("%s: key_to_certified failed", __func__);
+       } else {
+               key_cert_copy(pub, key);
+               key_free(pub);
+               return key;
+       }
+
+       key_free(key);
+       key_free(pub);
+       return NULL;
+}
+
+/*
+ * Returns 1 if the specified "key" is listed in the file "filename",
+ * 0 if the key is not listed or -1 on error.
+ * If strict_type is set then the key type must match exactly,
+ * otherwise a comparison that ignores certficiate data is performed.
+ */
+int
+key_in_file(Key *key, const char *filename, int strict_type)
+{
+       FILE *f;
+       char line[SSH_MAX_PUBKEY_BYTES];
+       char *cp;
+       u_long linenum = 0;
+       int ret = 0;
+       Key *pub;
+       int (*key_compare)(const Key *, const Key *) = strict_type ?
+           key_equal : key_equal_public;
+
+       if ((f = fopen(filename, "r")) == NULL) {
+               if (errno == ENOENT) {
+                       debug("%s: keyfile \"%s\" missing", __func__, filename);
+                       return 0;
+               } else {
+                       error("%s: could not open keyfile \"%s\": %s", __func__,
+                           filename, strerror(errno));
+                       return -1;
+               }
+       }
+
+       while (read_keyfile_line(f, filename, line, sizeof(line),
+                   &linenum) != -1) {
+               cp = line;
+
+               /* Skip leading whitespace. */
+               for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
+                       ;
+
+               /* Skip comments and empty lines */
+               switch (*cp) {
+               case '#':
+               case '\n':
+               case '\0':
+                       continue;
+               }
+
+               pub = key_new(KEY_UNSPEC);
+               if (key_read(pub, &cp) != 1) {
+                       key_free(pub);
+                       continue;
+               }
+               if (key_compare(key, pub)) {
+                       ret = 1;
+                       key_free(pub);
+                       break;
+               }
+               key_free(pub);
+       }
+       fclose(f);
+       return ret;
+}
+
diff --git a/.pc/ssh-vulnkey.patch/authfile.h b/.pc/ssh-vulnkey.patch/authfile.h
new file mode 100644 (file)
index 0000000..78349be
--- /dev/null
@@ -0,0 +1,31 @@
+/* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 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".
+ */
+
+#ifndef AUTHFILE_H
+#define AUTHFILE_H
+
+int     key_save_private(Key *, const char *, const char *, const char *);
+int     key_load_file(int, const char *, Buffer *);
+Key    *key_load_cert(const char *);
+Key    *key_load_public(const char *, char **);
+Key    *key_load_public_type(int, const char *, char **);
+Key    *key_parse_private(Buffer *, const char *, const char *, char **);
+Key    *key_load_private(const char *, const char *, char **);
+Key    *key_load_private_cert(int, const char *, const char *, int *);
+Key    *key_load_private_type(int, const char *, const char *, char **, int *);
+Key    *key_load_private_pem(int, int, const char *, char **);
+int     key_perm_ok(int, const char *);
+int     key_in_file(Key *, const char *, int);
+
+#endif
diff --git a/.pc/ssh-vulnkey.patch/pathnames.h b/.pc/ssh-vulnkey.patch/pathnames.h
new file mode 100644 (file)
index 0000000..c3d9abf
--- /dev/null
@@ -0,0 +1,181 @@
+/* $OpenBSD: pathnames.h,v 1.22 2011/05/23 03:30:07 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".
+ */
+
+#define ETCDIR                         "/etc"
+
+#ifndef SSHDIR
+#define SSHDIR                         ETCDIR "/ssh"
+#endif
+
+#ifndef _PATH_SSH_PIDDIR
+#define _PATH_SSH_PIDDIR               "/var/run"
+#endif
+
+/*
+ * System-wide file containing host keys of known hosts.  This file should be
+ * world-readable.
+ */
+#define _PATH_SSH_SYSTEM_HOSTFILE      SSHDIR "/ssh_known_hosts"
+/* backward compat for protocol 2 */
+#define _PATH_SSH_SYSTEM_HOSTFILE2     SSHDIR "/ssh_known_hosts2"
+
+/*
+ * Of these, ssh_host_key must be readable only by root, whereas ssh_config
+ * should be world-readable.
+ */
+#define _PATH_SERVER_CONFIG_FILE       SSHDIR "/sshd_config"
+#define _PATH_HOST_CONFIG_FILE         SSHDIR "/ssh_config"
+#define _PATH_HOST_KEY_FILE            SSHDIR "/ssh_host_key"
+#define _PATH_HOST_DSA_KEY_FILE                SSHDIR "/ssh_host_dsa_key"
+#define _PATH_HOST_ECDSA_KEY_FILE      SSHDIR "/ssh_host_ecdsa_key"
+#define _PATH_HOST_RSA_KEY_FILE                SSHDIR "/ssh_host_rsa_key"
+#define _PATH_DH_MODULI                        SSHDIR "/moduli"
+/* Backwards compatibility */
+#define _PATH_DH_PRIMES                        SSHDIR "/primes"
+
+#ifndef _PATH_SSH_PROGRAM
+#define _PATH_SSH_PROGRAM              "/usr/bin/ssh"
+#endif
+
+/*
+ * The process id of the daemon listening for connections is saved here to
+ * make it easier to kill the correct daemon when necessary.
+ */
+#define _PATH_SSH_DAEMON_PID_FILE      _PATH_SSH_PIDDIR "/sshd.pid"
+
+/*
+ * The directory in user's home directory in which the files reside. The
+ * directory should be world-readable (though not all files are).
+ */
+#define _PATH_SSH_USER_DIR             ".ssh"
+
+/*
+ * Per-user file containing host keys of known hosts.  This file need not be
+ * readable by anyone except the user him/herself, though this does not
+ * contain anything particularly secret.
+ */
+#define _PATH_SSH_USER_HOSTFILE                "~/.ssh/known_hosts"
+/* backward compat for protocol 2 */
+#define _PATH_SSH_USER_HOSTFILE2       "~/.ssh/known_hosts2"
+
+/*
+ * Name of the default file containing client-side authentication key. This
+ * file should only be readable by the user him/herself.
+ */
+#define _PATH_SSH_CLIENT_IDENTITY      ".ssh/identity"
+#define _PATH_SSH_CLIENT_ID_DSA                ".ssh/id_dsa"
+#define _PATH_SSH_CLIENT_ID_ECDSA      ".ssh/id_ecdsa"
+#define _PATH_SSH_CLIENT_ID_RSA                ".ssh/id_rsa"
+
+/*
+ * Configuration file in user's home directory.  This file need not be
+ * readable by anyone but the user him/herself, but does not contain anything
+ * particularly secret.  If the user's home directory resides on an NFS
+ * volume where root is mapped to nobody, this may need to be world-readable.
+ */
+#define _PATH_SSH_USER_CONFFILE                ".ssh/config"
+
+/*
+ * File containing a list of those rsa keys that permit logging in as this
+ * user.  This file need not be readable by anyone but the user him/herself,
+ * but does not contain anything particularly secret.  If the user's home
+ * directory resides on an NFS volume where root is mapped to nobody, this
+ * may need to be world-readable.  (This file is read by the daemon which is
+ * running as root.)
+ */
+#define _PATH_SSH_USER_PERMITTED_KEYS  ".ssh/authorized_keys"
+
+/* backward compat for protocol v2 */
+#define _PATH_SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2"
+
+/*
+ * Per-user and system-wide ssh "rc" files.  These files are executed with
+ * /bin/sh before starting the shell or command if they exist.  They will be
+ * passed "proto cookie" as arguments if X11 forwarding with spoofing is in
+ * use.  xauth will be run if neither of these exists.
+ */
+#define _PATH_SSH_USER_RC              ".ssh/rc"
+#define _PATH_SSH_SYSTEM_RC            SSHDIR "/sshrc"
+
+/*
+ * Ssh-only version of /etc/hosts.equiv.  Additionally, the daemon may use
+ * ~/.rhosts and /etc/hosts.equiv if rhosts authentication is enabled.
+ */
+#define _PATH_SSH_HOSTS_EQUIV          SSHDIR "/shosts.equiv"
+#define _PATH_RHOSTS_EQUIV             "/etc/hosts.equiv"
+
+/*
+ * Default location of askpass
+ */
+#ifndef _PATH_SSH_ASKPASS_DEFAULT
+#define _PATH_SSH_ASKPASS_DEFAULT      "/usr/X11R6/bin/ssh-askpass"
+#endif
+
+/* Location of ssh-keysign for hostbased authentication */
+#ifndef _PATH_SSH_KEY_SIGN
+#define _PATH_SSH_KEY_SIGN             "/usr/libexec/ssh-keysign"
+#endif
+
+/* Location of ssh-pkcs11-helper to support keys in tokens */
+#ifndef _PATH_SSH_PKCS11_HELPER
+#define _PATH_SSH_PKCS11_HELPER                "/usr/libexec/ssh-pkcs11-helper"
+#endif
+
+/* xauth for X11 forwarding */
+#ifndef _PATH_XAUTH
+#define _PATH_XAUTH                    "/usr/X11R6/bin/xauth"
+#endif
+
+/* UNIX domain socket for X11 server; displaynum will replace %u */
+#ifndef _PATH_UNIX_X
+#define _PATH_UNIX_X "/tmp/.X11-unix/X%u"
+#endif
+
+/* for scp */
+#ifndef _PATH_CP
+#define _PATH_CP                       "cp"
+#endif
+
+/* for sftp */
+#ifndef _PATH_SFTP_SERVER
+#define _PATH_SFTP_SERVER              "/usr/libexec/sftp-server"
+#endif
+
+/* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */
+#ifndef _PATH_PRIVSEP_CHROOT_DIR
+#define _PATH_PRIVSEP_CHROOT_DIR       "/var/empty"
+#endif
+
+/* for passwd change */
+#ifndef _PATH_PASSWD_PROG
+#define _PATH_PASSWD_PROG             "/usr/bin/passwd"
+#endif
+
+#ifndef _PATH_LS
+#define _PATH_LS                       "ls"
+#endif
+
+/* path to login program */
+#ifndef LOGIN_PROGRAM
+# ifdef LOGIN_PROGRAM_FALLBACK
+#  define LOGIN_PROGRAM         LOGIN_PROGRAM_FALLBACK
+# else
+#  define LOGIN_PROGRAM         "/usr/bin/login"
+# endif
+#endif /* LOGIN_PROGRAM */
+
+/* Askpass program define */
+#ifndef ASKPASS_PROGRAM
+#define ASKPASS_PROGRAM         "/usr/lib/ssh/ssh-askpass"
+#endif /* ASKPASS_PROGRAM */
diff --git a/.pc/ssh-vulnkey.patch/readconf.c b/.pc/ssh-vulnkey.patch/readconf.c
new file mode 100644 (file)
index 0000000..60befde
--- /dev/null
@@ -0,0 +1,1515 @@
+/* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for reading the configuration files.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "compat.h"
+#include "cipher.h"
+#include "pathnames.h"
+#include "log.h"
+#include "key.h"
+#include "readconf.h"
+#include "match.h"
+#include "misc.h"
+#include "buffer.h"
+#include "kex.h"
+#include "mac.h"
+
+/* Format of the configuration file:
+
+   # Configuration data is parsed as follows:
+   #  1. command line options
+   #  2. user-specific file
+   #  3. system-wide file
+   # Any configuration value is only changed the first time it is set.
+   # Thus, host-specific definitions should be at the beginning of the
+   # configuration file, and defaults at the end.
+
+   # Host-specific declarations.  These may override anything above.  A single
+   # host may match multiple declarations; these are processed in the order
+   # that they are given in.
+
+   Host *.ngs.fi ngs.fi
+     User foo
+
+   Host fake.com
+     HostName another.host.name.real.org
+     User blaah
+     Port 34289
+     ForwardX11 no
+     ForwardAgent no
+
+   Host books.com
+     RemoteForward 9999 shadows.cs.hut.fi:9999
+     Cipher 3des
+
+   Host fascist.blob.com
+     Port 23123
+     User tylonen
+     PasswordAuthentication no
+
+   Host puukko.hut.fi
+     User t35124p
+     ProxyCommand ssh-proxy %h %p
+
+   Host *.fr
+     PublicKeyAuthentication no
+
+   Host *.su
+     Cipher none
+     PasswordAuthentication no
+
+   Host vpn.fake.com
+     Tunnel yes
+     TunnelDevice 3
+
+   # Defaults for various options
+   Host *
+     ForwardAgent no
+     ForwardX11 no
+     PasswordAuthentication yes
+     RSAAuthentication yes
+     RhostsRSAAuthentication yes
+     StrictHostKeyChecking yes
+     TcpKeepAlive no
+     IdentityFile ~/.ssh/identity
+     Port 22
+     EscapeChar ~
+
+*/
+
+/* Keyword tokens. */
+
+typedef enum {
+       oBadOption,
+       oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
+       oGatewayPorts, oExitOnForwardFailure,
+       oPasswordAuthentication, oRSAAuthentication,
+       oChallengeResponseAuthentication, oXAuthLocation,
+       oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
+       oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+       oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
+       oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
+       oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
+       oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
+       oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
+       oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
+       oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
+       oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
+       oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+       oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
+       oGssServerIdentity, 
+       oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+       oSendEnv, oControlPath, oControlMaster, oControlPersist,
+       oHashKnownHosts,
+       oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
+       oKexAlgorithms, oIPQoS, oRequestTTY,
+       oDeprecated, oUnsupported
+} OpCodes;
+
+/* Textual representations of the tokens. */
+
+static struct {
+       const char *name;
+       OpCodes opcode;
+} keywords[] = {
+       { "forwardagent", oForwardAgent },
+       { "forwardx11", oForwardX11 },
+       { "forwardx11trusted", oForwardX11Trusted },
+       { "forwardx11timeout", oForwardX11Timeout },
+       { "exitonforwardfailure", oExitOnForwardFailure },
+       { "xauthlocation", oXAuthLocation },
+       { "gatewayports", oGatewayPorts },
+       { "useprivilegedport", oUsePrivilegedPort },
+       { "rhostsauthentication", oDeprecated },
+       { "passwordauthentication", oPasswordAuthentication },
+       { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
+       { "kbdinteractivedevices", oKbdInteractiveDevices },
+       { "rsaauthentication", oRSAAuthentication },
+       { "pubkeyauthentication", oPubkeyAuthentication },
+       { "dsaauthentication", oPubkeyAuthentication },             /* alias */
+       { "rhostsrsaauthentication", oRhostsRSAAuthentication },
+       { "hostbasedauthentication", oHostbasedAuthentication },
+       { "challengeresponseauthentication", oChallengeResponseAuthentication },
+       { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
+       { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
+       { "kerberosauthentication", oUnsupported },
+       { "kerberostgtpassing", oUnsupported },
+       { "afstokenpassing", oUnsupported },
+#if defined(GSSAPI)
+       { "gssapiauthentication", oGssAuthentication },
+       { "gssapikeyexchange", oGssKeyEx },
+       { "gssapidelegatecredentials", oGssDelegateCreds },
+       { "gssapitrustdns", oGssTrustDns },
+       { "gssapiclientidentity", oGssClientIdentity },
+       { "gssapiserveridentity", oGssServerIdentity },
+       { "gssapirenewalforcesrekey", oGssRenewalRekey },
+#else
+       { "gssapiauthentication", oUnsupported },
+       { "gssapikeyexchange", oUnsupported },
+       { "gssapidelegatecredentials", oUnsupported },
+       { "gssapitrustdns", oUnsupported },
+       { "gssapiclientidentity", oUnsupported },
+       { "gssapirenewalforcesrekey", oUnsupported },
+#endif
+       { "fallbacktorsh", oDeprecated },
+       { "usersh", oDeprecated },
+       { "identityfile", oIdentityFile },
+       { "identityfile2", oIdentityFile },                     /* obsolete */
+       { "identitiesonly", oIdentitiesOnly },
+       { "hostname", oHostName },
+       { "hostkeyalias", oHostKeyAlias },
+       { "proxycommand", oProxyCommand },
+       { "port", oPort },
+       { "cipher", oCipher },
+       { "ciphers", oCiphers },
+       { "macs", oMacs },
+       { "protocol", oProtocol },
+       { "remoteforward", oRemoteForward },
+       { "localforward", oLocalForward },
+       { "user", oUser },
+       { "host", oHost },
+       { "escapechar", oEscapeChar },
+       { "globalknownhostsfile", oGlobalKnownHostsFile },
+       { "globalknownhostsfile2", oDeprecated },
+       { "userknownhostsfile", oUserKnownHostsFile },
+       { "userknownhostsfile2", oDeprecated }, 
+       { "connectionattempts", oConnectionAttempts },
+       { "batchmode", oBatchMode },
+       { "checkhostip", oCheckHostIP },
+       { "stricthostkeychecking", oStrictHostKeyChecking },
+       { "compression", oCompression },
+       { "compressionlevel", oCompressionLevel },
+       { "tcpkeepalive", oTCPKeepAlive },
+       { "keepalive", oTCPKeepAlive },                         /* obsolete */
+       { "numberofpasswordprompts", oNumberOfPasswordPrompts },
+       { "loglevel", oLogLevel },
+       { "dynamicforward", oDynamicForward },
+       { "preferredauthentications", oPreferredAuthentications },
+       { "hostkeyalgorithms", oHostKeyAlgorithms },
+       { "bindaddress", oBindAddress },
+#ifdef ENABLE_PKCS11
+       { "smartcarddevice", oPKCS11Provider },
+       { "pkcs11provider", oPKCS11Provider },
+#else
+       { "smartcarddevice", oUnsupported },
+       { "pkcs11provider", oUnsupported },
+#endif
+       { "clearallforwardings", oClearAllForwardings },
+       { "enablesshkeysign", oEnableSSHKeysign },
+       { "verifyhostkeydns", oVerifyHostKeyDNS },
+       { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
+       { "rekeylimit", oRekeyLimit },
+       { "connecttimeout", oConnectTimeout },
+       { "addressfamily", oAddressFamily },
+       { "serveraliveinterval", oServerAliveInterval },
+       { "serveralivecountmax", oServerAliveCountMax },
+       { "sendenv", oSendEnv },
+       { "controlpath", oControlPath },
+       { "controlmaster", oControlMaster },
+       { "controlpersist", oControlPersist },
+       { "hashknownhosts", oHashKnownHosts },
+       { "tunnel", oTunnel },
+       { "tunneldevice", oTunnelDevice },
+       { "localcommand", oLocalCommand },
+       { "permitlocalcommand", oPermitLocalCommand },
+       { "visualhostkey", oVisualHostKey },
+       { "useroaming", oUseRoaming },
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication",
+           oZeroKnowledgePasswordAuthentication },
+#else
+       { "zeroknowledgepasswordauthentication", oUnsupported },
+#endif
+       { "kexalgorithms", oKexAlgorithms },
+       { "ipqos", oIPQoS },
+       { "requesttty", oRequestTTY },
+
+       { NULL, oBadOption }
+};
+
+/*
+ * Adds a local TCP/IP port forward to options.  Never returns if there is an
+ * error.
+ */
+
+void
+add_local_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+#ifndef NO_IPPORT_RESERVED_CONCEPT
+       extern uid_t original_real_uid;
+       if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
+               fatal("Privileged ports can only be forwarded by root.");
+#endif
+       options->local_forwards = xrealloc(options->local_forwards,
+           options->num_local_forwards + 1,
+           sizeof(*options->local_forwards));
+       fwd = &options->local_forwards[options->num_local_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+}
+
+/*
+ * Adds a remote TCP/IP port forward to options.  Never returns if there is
+ * an error.
+ */
+
+void
+add_remote_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+
+       options->remote_forwards = xrealloc(options->remote_forwards,
+           options->num_remote_forwards + 1,
+           sizeof(*options->remote_forwards));
+       fwd = &options->remote_forwards[options->num_remote_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+       fwd->allocated_port = 0;
+}
+
+static void
+clear_forwardings(Options *options)
+{
+       int i;
+
+       for (i = 0; i < options->num_local_forwards; i++) {
+               if (options->local_forwards[i].listen_host != NULL)
+                       xfree(options->local_forwards[i].listen_host);
+               xfree(options->local_forwards[i].connect_host);
+       }
+       if (options->num_local_forwards > 0) {
+               xfree(options->local_forwards);
+               options->local_forwards = NULL;
+       }
+       options->num_local_forwards = 0;
+       for (i = 0; i < options->num_remote_forwards; i++) {
+               if (options->remote_forwards[i].listen_host != NULL)
+                       xfree(options->remote_forwards[i].listen_host);
+               xfree(options->remote_forwards[i].connect_host);
+       }
+       if (options->num_remote_forwards > 0) {
+               xfree(options->remote_forwards);
+               options->remote_forwards = NULL;
+       }
+       options->num_remote_forwards = 0;
+       options->tun_open = SSH_TUNMODE_NO;
+}
+
+/*
+ * Returns the number of the token pointed to by cp or oBadOption.
+ */
+
+static OpCodes
+parse_token(const char *cp, const char *filename, int linenum)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0)
+                       return keywords[i].opcode;
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return oBadOption;
+}
+
+/*
+ * Processes a single option line as used in the configuration files. This
+ * only sets those values that have not already been set.
+ */
+#define WHITESPACE " \t\r\n"
+
+int
+process_config_line(Options *options, const char *host,
+                   char *line, const char *filename, int linenum,
+                   int *activep)
+{
+       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+       char **cpptr, fwdarg[256];
+       u_int *uintptr, max_entries = 0;
+       int negated, opcode, *intptr, value, value2, scale;
+       LogLevel *log_level_ptr;
+       long long orig, val64;
+       size_t len;
+       Forward fwd;
+
+       /* Strip trailing whitespace */
+       for (len = strlen(line) - 1; len > 0; len--) {
+               if (strchr(WHITESPACE, line[len]) == NULL)
+                       break;
+               line[len] = '\0';
+       }
+
+       s = line;
+       /* Get the keyword. (Each line is supposed to begin with a keyword). */
+       if ((keyword = strdelim(&s)) == NULL)
+               return 0;
+       /* Ignore leading whitespace. */
+       if (*keyword == '\0')
+               keyword = strdelim(&s);
+       if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
+               return 0;
+
+       opcode = parse_token(keyword, filename, linenum);
+
+       switch (opcode) {
+       case oBadOption:
+               /* don't panic, but count bad options */
+               return -1;
+               /* NOTREACHED */
+       case oConnectTimeout:
+               intptr = &options->connection_timeout;
+parse_time:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardAgent:
+               intptr = &options->forward_agent;
+parse_flag:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else
+                       fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardX11:
+               intptr = &options->forward_x11;
+               goto parse_flag;
+
+       case oForwardX11Trusted:
+               intptr = &options->forward_x11_trusted;
+               goto parse_flag;
+       
+       case oForwardX11Timeout:
+               intptr = &options->forward_x11_timeout;
+               goto parse_time;
+
+       case oGatewayPorts:
+               intptr = &options->gateway_ports;
+               goto parse_flag;
+
+       case oExitOnForwardFailure:
+               intptr = &options->exit_on_forward_failure;
+               goto parse_flag;
+
+       case oUsePrivilegedPort:
+               intptr = &options->use_privileged_port;
+               goto parse_flag;
+
+       case oPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case oZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveDevices:
+               charptr = &options->kbd_interactive_devices;
+               goto parse_string;
+
+       case oPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case oRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case oRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case oHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case oChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case oGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case oGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
+       case oGssDelegateCreds:
+               intptr = &options->gss_deleg_creds;
+               goto parse_flag;
+
+       case oGssTrustDns:
+               intptr = &options->gss_trust_dns;
+               goto parse_flag;
+
+       case oGssClientIdentity:
+               charptr = &options->gss_client_identity;
+               goto parse_string;
+
+       case oGssServerIdentity:
+               charptr = &options->gss_server_identity;
+               goto parse_string;
+
+       case oGssRenewalRekey:
+               intptr = &options->gss_renewal_rekey;
+               goto parse_flag;
+
+       case oBatchMode:
+               intptr = &options->batch_mode;
+               goto parse_flag;
+
+       case oCheckHostIP:
+               intptr = &options->check_host_ip;
+               goto parse_flag;
+
+       case oVerifyHostKeyDNS:
+               intptr = &options->verify_host_key_dns;
+               goto parse_yesnoask;
+
+       case oStrictHostKeyChecking:
+               intptr = &options->strict_host_key_checking;
+parse_yesnoask:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no/ask argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "ask") == 0)
+                       value = 2;
+               else
+                       fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCompression:
+               intptr = &options->compression;
+               goto parse_flag;
+
+       case oTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case oNoHostAuthenticationForLocalhost:
+               intptr = &options->no_host_authentication_for_localhost;
+               goto parse_flag;
+
+       case oNumberOfPasswordPrompts:
+               intptr = &options->number_of_password_prompts;
+               goto parse_int;
+
+       case oCompressionLevel:
+               intptr = &options->compression_level;
+               goto parse_int;
+
+       case oRekeyLimit:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               orig = val64 = strtoll(arg, &endofnumber, 10);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               switch (toupper(*endofnumber)) {
+               case '\0':
+                       scale = 1;
+                       break;
+               case 'K':
+                       scale = 1<<10;
+                       break;
+               case 'M':
+                       scale = 1<<20;
+                       break;
+               case 'G':
+                       scale = 1<<30;
+                       break;
+               default:
+                       fatal("%.200s line %d: Invalid RekeyLimit suffix",
+                           filename, linenum);
+               }
+               val64 *= scale;
+               /* detect integer wrap and too-large limits */
+               if ((val64 / scale) != orig || val64 > UINT_MAX)
+                       fatal("%.200s line %d: RekeyLimit too large",
+                           filename, linenum);
+               if (val64 < 16)
+                       fatal("%.200s line %d: RekeyLimit too small",
+                           filename, linenum);
+               if (*activep && options->rekey_limit == -1)
+                       options->rekey_limit = (u_int32_t)val64;
+               break;
+
+       case oIdentityFile:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (*activep) {
+                       intptr = &options->num_identity_files;
+                       if (*intptr >= SSH_MAX_IDENTITY_FILES)
+                               fatal("%.200s line %d: Too many identity files specified (max %d).",
+                                   filename, linenum, SSH_MAX_IDENTITY_FILES);
+                       charptr = &options->identity_files[*intptr];
+                       *charptr = xstrdup(arg);
+                       *intptr = *intptr + 1;
+               }
+               break;
+
+       case oXAuthLocation:
+               charptr=&options->xauth_location;
+               goto parse_string;
+
+       case oUser:
+               charptr = &options->user;
+parse_string:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case oGlobalKnownHostsFile:
+               cpptr = (char **)&options->system_hostfiles;
+               uintptr = &options->num_system_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+parse_char_array:
+               if (*activep && *uintptr == 0) {
+                       while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                               if ((*uintptr) >= max_entries)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               cpptr[(*uintptr)++] = xstrdup(arg);
+                       }
+               }
+               return 0;
+
+       case oUserKnownHostsFile:
+               cpptr = (char **)&options->user_hostfiles;
+               uintptr = &options->num_user_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+               goto parse_char_array;
+
+       case oHostName:
+               charptr = &options->hostname;
+               goto parse_string;
+
+       case oHostKeyAlias:
+               charptr = &options->host_key_alias;
+               goto parse_string;
+
+       case oPreferredAuthentications:
+               charptr = &options->preferred_authentications;
+               goto parse_string;
+
+       case oBindAddress:
+               charptr = &options->bind_address;
+               goto parse_string;
+
+       case oPKCS11Provider:
+               charptr = &options->pkcs11_provider;
+               goto parse_string;
+
+       case oProxyCommand:
+               charptr = &options->proxy_command;
+parse_command:
+               if (s == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               len = strspn(s, WHITESPACE "=");
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(s + len);
+               return 0;
+
+       case oPort:
+               intptr = &options->port;
+parse_int:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+
+               /* Octal, decimal, or hex format? */
+               value = strtol(arg, &endofnumber, 0);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oConnectionAttempts:
+               intptr = &options->connection_attempts;
+               goto parse_int;
+
+       case oCipher:
+               intptr = &options->cipher;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = cipher_number(arg);
+               if (value == -1)
+                       fatal("%.200s line %d: Bad cipher '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCiphers:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case oMacs:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case oKexAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case oHostKeyAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!key_names_valid2(arg))
+                       fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->hostkeyalgorithms == NULL)
+                       options->hostkeyalgorithms = xstrdup(arg);
+               break;
+
+       case oProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%.200s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case oLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&s);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case oLocalForward:
+       case oRemoteForward:
+       case oDynamicForward:
+               arg = strdelim(&s);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%.200s line %d: Missing port argument.",
+                           filename, linenum);
+
+               if (opcode == oLocalForward ||
+                   opcode == oRemoteForward) {
+                       arg2 = strdelim(&s);
+                       if (arg2 == NULL || *arg2 == '\0')
+                               fatal("%.200s line %d: Missing target argument.",
+                                   filename, linenum);
+
+                       /* construct a string for parse_forward */
+                       snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
+               } else if (opcode == oDynamicForward) {
+                       strlcpy(fwdarg, arg, sizeof(fwdarg));
+               }
+
+               if (parse_forward(&fwd, fwdarg,
+                   opcode == oDynamicForward ? 1 : 0,
+                   opcode == oRemoteForward ? 1 : 0) == 0)
+                       fatal("%.200s line %d: Bad forwarding specification.",
+                           filename, linenum);
+
+               if (*activep) {
+                       if (opcode == oLocalForward ||
+                           opcode == oDynamicForward)
+                               add_local_forward(options, &fwd);
+                       else if (opcode == oRemoteForward)
+                               add_remote_forward(options, &fwd);
+               }
+               break;
+
+       case oClearAllForwardings:
+               intptr = &options->clear_forwardings;
+               goto parse_flag;
+
+       case oHost:
+               *activep = 0;
+               arg2 = NULL;
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       negated = *arg == '!';
+                       if (negated)
+                               arg++;
+                       if (match_pattern(host, arg)) {
+                               if (negated) {
+                                       debug("%.200s line %d: Skipping Host "
+                                           "block because of negated match "
+                                           "for %.100s", filename, linenum,
+                                           arg);
+                                       *activep = 0;
+                                       break;
+                               }
+                               if (!*activep)
+                                       arg2 = arg; /* logged below */
+                               *activep = 1;
+                       }
+               }
+               if (*activep)
+                       debug("%.200s line %d: Applying options for %.100s",
+                           filename, linenum, arg2);
+               /* Avoid garbage check below, as strdelim is done. */
+               return 0;
+
+       case oEscapeChar:
+               intptr = &options->escape_char;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] == '^' && arg[2] == 0 &&
+                   (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
+                       value = (u_char) arg[1] & 31;
+               else if (strlen(arg) == 1)
+                       value = (u_char) arg[0];
+               else if (strcmp(arg, "none") == 0)
+                       value = SSH_ESCAPECHAR_NONE;
+               else {
+                       fatal("%.200s line %d: Bad escape character.",
+                           filename, linenum);
+                       /* NOTREACHED */
+                       value = 0;      /* Avoid compiler warning. */
+               }
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oAddressFamily:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing address family.",
+                           filename, linenum);
+               intptr = &options->address_family;
+               if (strcasecmp(arg, "inet") == 0)
+                       value = AF_INET;
+               else if (strcasecmp(arg, "inet6") == 0)
+                       value = AF_INET6;
+               else if (strcasecmp(arg, "any") == 0)
+                       value = AF_UNSPEC;
+               else
+                       fatal("Unsupported AddressFamily \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oEnableSSHKeysign:
+               intptr = &options->enable_ssh_keysign;
+               goto parse_flag;
+
+       case oIdentitiesOnly:
+               intptr = &options->identities_only;
+               goto parse_flag;
+
+       case oServerAliveInterval:
+               intptr = &options->server_alive_interval;
+               goto parse_time;
+
+       case oServerAliveCountMax:
+               intptr = &options->server_alive_count_max;
+               goto parse_int;
+
+       case oSendEnv:
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (!*activep)
+                               continue;
+                       if (options->num_send_env >= MAX_SEND_ENV)
+                               fatal("%s line %d: too many send env.",
+                                   filename, linenum);
+                       options->send_env[options->num_send_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case oControlPath:
+               charptr = &options->control_path;
+               goto parse_string;
+
+       case oControlMaster:
+               intptr = &options->control_master;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlMaster argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = SSHCTL_MASTER_YES;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = SSHCTL_MASTER_NO;
+               else if (strcmp(arg, "auto") == 0)
+                       value = SSHCTL_MASTER_AUTO;
+               else if (strcmp(arg, "ask") == 0)
+                       value = SSHCTL_MASTER_ASK;
+               else if (strcmp(arg, "autoask") == 0)
+                       value = SSHCTL_MASTER_AUTO_ASK;
+               else
+                       fatal("%.200s line %d: Bad ControlMaster argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oControlPersist:
+               /* no/false/yes/true, or a time spec */
+               intptr = &options->control_persist;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlPersist"
+                           " argument.", filename, linenum);
+               value = 0;
+               value2 = 0;     /* timeout */
+               if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if ((value2 = convtime(arg)) >= 0)
+                       value = 1;
+               else
+                       fatal("%.200s line %d: Bad ControlPersist argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1) {
+                       *intptr = value;
+                       options->control_persist_timeout = value2;
+               }
+               break;
+
+       case oHashKnownHosts:
+               intptr = &options->hash_known_hosts;
+               goto parse_flag;
+
+       case oTunnel:
+               intptr = &options->tun_open;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcasecmp(arg, "ethernet") == 0)
+                       value = SSH_TUNMODE_ETHERNET;
+               else if (strcasecmp(arg, "point-to-point") == 0)
+                       value = SSH_TUNMODE_POINTOPOINT;
+               else if (strcasecmp(arg, "yes") == 0)
+                       value = SSH_TUNMODE_DEFAULT;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = SSH_TUNMODE_NO;
+               else
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*activep)
+                       *intptr = value;
+               break;
+
+       case oTunnelDevice:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = a2tun(arg, &value2);
+               if (value == SSH_TUNID_ERR)
+                       fatal("%.200s line %d: Bad tun device.", filename, linenum);
+               if (*activep) {
+                       options->tun_local = value;
+                       options->tun_remote = value2;
+               }
+               break;
+
+       case oLocalCommand:
+               charptr = &options->local_command;
+               goto parse_command;
+
+       case oPermitLocalCommand:
+               intptr = &options->permit_local_command;
+               goto parse_flag;
+
+       case oVisualHostKey:
+               intptr = &options->visual_host_key;
+               goto parse_flag;
+
+       case oIPQoS:
+               arg = strdelim(&s);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&s);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case oUseRoaming:
+               intptr = &options->use_roaming;
+               goto parse_flag;
+
+       case oRequestTTY:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               intptr = &options->request_tty;
+               if (strcasecmp(arg, "yes") == 0)
+                       value = REQUEST_TTY_YES;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = REQUEST_TTY_NO;
+               else if (strcasecmp(arg, "force") == 0)
+                       value = REQUEST_TTY_FORCE;
+               else if (strcasecmp(arg, "auto") == 0)
+                       value = REQUEST_TTY_AUTO;
+               else
+                       fatal("Unsupported RequestTTY \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oDeprecated:
+               debug("%s line %d: Deprecated option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       case oUnsupported:
+               error("%s line %d: Unsupported option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       default:
+               fatal("process_config_line: Unimplemented opcode %d", opcode);
+       }
+
+       /* Check that there is no garbage at end of line. */
+       if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+               fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       }
+       return 0;
+}
+
+
+/*
+ * Reads the config file and modifies the options accordingly.  Options
+ * should already be initialized before this call.  This never returns if
+ * there is an error.  If the file does not exist, this returns 0.
+ */
+
+int
+read_config_file(const char *filename, const char *host, Options *options,
+    int checkperm)
+{
+       FILE *f;
+       char line[1024];
+       int active, linenum;
+       int bad_options = 0;
+
+       if ((f = fopen(filename, "r")) == NULL)
+               return 0;
+
+       if (checkperm) {
+               struct stat sb;
+
+               if (fstat(fileno(f), &sb) == -1)
+                       fatal("fstat %s: %s", filename, strerror(errno));
+               if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
+                   (sb.st_mode & 022) != 0))
+                       fatal("Bad owner or permissions on %s", filename);
+       }
+
+       debug("Reading configuration data %.200s", filename);
+
+       /*
+        * Mark that we are now processing the options.  This flag is turned
+        * on/off by Host specifications.
+        */
+       active = 1;
+       linenum = 0;
+       while (fgets(line, sizeof(line), f)) {
+               /* Update line number counter. */
+               linenum++;
+               if (process_config_line(options, host, line, filename, linenum, &active) != 0)
+                       bad_options++;
+       }
+       fclose(f);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+       return 1;
+}
+
+/*
+ * Initializes options to special values that indicate that they have not yet
+ * been set.  Read_config_file will only set options with this value. Options
+ * are processed in the following order: command line, user config file,
+ * system config file.  Last, fill_default_options is called.
+ */
+
+void
+initialize_options(Options * options)
+{
+       memset(options, 'X', sizeof(*options));
+       options->forward_agent = -1;
+       options->forward_x11 = -1;
+       options->forward_x11_trusted = -1;
+       options->forward_x11_timeout = -1;
+       options->exit_on_forward_failure = -1;
+       options->xauth_location = NULL;
+       options->gateway_ports = -1;
+       options->use_privileged_port = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->gss_authentication = -1;
+       options->gss_keyex = -1;
+       options->gss_deleg_creds = -1;
+       options->gss_trust_dns = -1;
+       options->gss_renewal_rekey = -1;
+       options->gss_client_identity = NULL;
+       options->gss_server_identity = NULL;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->kbd_interactive_devices = NULL;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->batch_mode = -1;
+       options->check_host_ip = -1;
+       options->strict_host_key_checking = -1;
+       options->compression = -1;
+       options->tcp_keep_alive = -1;
+       options->compression_level = -1;
+       options->port = -1;
+       options->address_family = -1;
+       options->connection_attempts = -1;
+       options->connection_timeout = -1;
+       options->number_of_password_prompts = -1;
+       options->cipher = -1;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->hostkeyalgorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->num_identity_files = 0;
+       options->hostname = NULL;
+       options->host_key_alias = NULL;
+       options->proxy_command = NULL;
+       options->user = NULL;
+       options->escape_char = -1;
+       options->num_system_hostfiles = 0;
+       options->num_user_hostfiles = 0;
+       options->local_forwards = NULL;
+       options->num_local_forwards = 0;
+       options->remote_forwards = NULL;
+       options->num_remote_forwards = 0;
+       options->clear_forwardings = -1;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->preferred_authentications = NULL;
+       options->bind_address = NULL;
+       options->pkcs11_provider = NULL;
+       options->enable_ssh_keysign = - 1;
+       options->no_host_authentication_for_localhost = - 1;
+       options->identities_only = - 1;
+       options->rekey_limit = - 1;
+       options->verify_host_key_dns = -1;
+       options->server_alive_interval = -1;
+       options->server_alive_count_max = -1;
+       options->num_send_env = 0;
+       options->control_path = NULL;
+       options->control_master = -1;
+       options->control_persist = -1;
+       options->control_persist_timeout = 0;
+       options->hash_known_hosts = -1;
+       options->tun_open = -1;
+       options->tun_local = -1;
+       options->tun_remote = -1;
+       options->local_command = NULL;
+       options->permit_local_command = -1;
+       options->use_roaming = -1;
+       options->visual_host_key = -1;
+       options->zero_knowledge_password_authentication = -1;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+       options->request_tty = -1;
+}
+
+/*
+ * Called after processing other sources of option data, this fills those
+ * options for which no value has been specified with their default values.
+ */
+
+void
+fill_default_options(Options * options)
+{
+       int len;
+
+       if (options->forward_agent == -1)
+               options->forward_agent = 0;
+       if (options->forward_x11 == -1)
+               options->forward_x11 = 0;
+       if (options->forward_x11_trusted == -1)
+               options->forward_x11_trusted = 0;
+       if (options->forward_x11_timeout == -1)
+               options->forward_x11_timeout = 1200;
+       if (options->exit_on_forward_failure == -1)
+               options->exit_on_forward_failure = 0;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->use_privileged_port == -1)
+               options->use_privileged_port = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
+       if (options->gss_deleg_creds == -1)
+               options->gss_deleg_creds = 0;
+       if (options->gss_trust_dns == -1)
+               options->gss_trust_dns = 0;
+       if (options->gss_renewal_rekey == -1)
+               options->gss_renewal_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 1;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->batch_mode == -1)
+               options->batch_mode = 0;
+       if (options->check_host_ip == -1)
+               options->check_host_ip = 1;
+       if (options->strict_host_key_checking == -1)
+               options->strict_host_key_checking = 2;  /* 2 is default */
+       if (options->compression == -1)
+               options->compression = 0;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->compression_level == -1)
+               options->compression_level = 6;
+       if (options->port == -1)
+               options->port = 0;      /* Filled in ssh_connect. */
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (options->connection_attempts == -1)
+               options->connection_attempts = 1;
+       if (options->number_of_password_prompts == -1)
+               options->number_of_password_prompts = 3;
+       /* Selected in ssh_login(). */
+       if (options->cipher == -1)
+               options->cipher = SSH_CIPHER_NOT_SET;
+       /* options->ciphers, default set in myproposals.h */
+       /* options->macs, default set in myproposals.h */
+       /* options->kex_algorithms, default set in myproposals.h */
+       /* options->hostkeyalgorithms, default set in myproposals.h */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_identity_files == 0) {
+               if (options->protocol & SSH_PROTO_1) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
+               }
+               if (options->protocol & SSH_PROTO_2) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
+
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
+#ifdef OPENSSL_HAS_ECC
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
+#endif
+               }
+       }
+       if (options->escape_char == -1)
+               options->escape_char = '~';
+       if (options->num_system_hostfiles == 0) {
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
+       }
+       if (options->num_user_hostfiles == 0) {
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE);
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE2);
+       }
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->clear_forwardings == 1)
+               clear_forwardings(options);
+       if (options->no_host_authentication_for_localhost == - 1)
+               options->no_host_authentication_for_localhost = 0;
+       if (options->identities_only == -1)
+               options->identities_only = 0;
+       if (options->enable_ssh_keysign == -1)
+               options->enable_ssh_keysign = 0;
+       if (options->rekey_limit == -1)
+               options->rekey_limit = 0;
+       if (options->verify_host_key_dns == -1)
+               options->verify_host_key_dns = 0;
+       if (options->server_alive_interval == -1)
+               options->server_alive_interval = 0;
+       if (options->server_alive_count_max == -1)
+               options->server_alive_count_max = 3;
+       if (options->control_master == -1)
+               options->control_master = 0;
+       if (options->control_persist == -1) {
+               options->control_persist = 0;
+               options->control_persist_timeout = 0;
+       }
+       if (options->hash_known_hosts == -1)
+               options->hash_known_hosts = 0;
+       if (options->tun_open == -1)
+               options->tun_open = SSH_TUNMODE_NO;
+       if (options->tun_local == -1)
+               options->tun_local = SSH_TUNID_ANY;
+       if (options->tun_remote == -1)
+               options->tun_remote = SSH_TUNID_ANY;
+       if (options->permit_local_command == -1)
+               options->permit_local_command = 0;
+       if (options->use_roaming == -1)
+               options->use_roaming = 1;
+       if (options->visual_host_key == -1)
+               options->visual_host_key = 0;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+       if (options->request_tty == -1)
+               options->request_tty = REQUEST_TTY_AUTO;
+       /* options->local_command should not be set by default */
+       /* options->proxy_command should not be set by default */
+       /* options->user will be set in the main program if appropriate */
+       /* options->hostname will be set in the main program if appropriate */
+       /* options->host_key_alias should not be set by default */
+       /* options->preferred_authentications will be set in ssh */
+}
+
+/*
+ * parse_forward
+ * parses a string containing a port forwarding specification of the form:
+ *   dynamicfwd == 0
+ *     [listenhost:]listenport:connecthost:connectport
+ *   dynamicfwd == 1
+ *     [listenhost:]listenport
+ * returns number of arguments parsed or zero on error
+ */
+int
+parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
+{
+       int i;
+       char *p, *cp, *fwdarg[4];
+
+       memset(fwd, '\0', sizeof(*fwd));
+
+       cp = p = xstrdup(fwdspec);
+
+       /* skip leading spaces */
+       while (isspace(*cp))
+               cp++;
+
+       for (i = 0; i < 4; ++i)
+               if ((fwdarg[i] = hpdelim(&cp)) == NULL)
+                       break;
+
+       /* Check for trailing garbage */
+       if (cp != NULL)
+               i = 0;  /* failure */
+
+       switch (i) {
+       case 1:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 2:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 3:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
+               fwd->connect_port = a2port(fwdarg[2]);
+               break;
+
+       case 4:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
+               fwd->connect_port = a2port(fwdarg[3]);
+               break;
+       default:
+               i = 0; /* failure */
+       }
+
+       xfree(p);
+
+       if (dynamicfwd) {
+               if (!(i == 1 || i == 2))
+                       goto fail_free;
+       } else {
+               if (!(i == 3 || i == 4))
+                       goto fail_free;
+               if (fwd->connect_port <= 0)
+                       goto fail_free;
+       }
+
+       if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
+               goto fail_free;
+
+       if (fwd->connect_host != NULL &&
+           strlen(fwd->connect_host) >= NI_MAXHOST)
+               goto fail_free;
+       if (fwd->listen_host != NULL &&
+           strlen(fwd->listen_host) >= NI_MAXHOST)
+               goto fail_free;
+
+
+       return (i);
+
+ fail_free:
+       if (fwd->connect_host != NULL) {
+               xfree(fwd->connect_host);
+               fwd->connect_host = NULL;
+       }
+       if (fwd->listen_host != NULL) {
+               xfree(fwd->listen_host);
+               fwd->listen_host = NULL;
+       }
+       return (0);
+}
diff --git a/.pc/ssh-vulnkey.patch/readconf.h b/.pc/ssh-vulnkey.patch/readconf.h
new file mode 100644 (file)
index 0000000..617686f
--- /dev/null
@@ -0,0 +1,166 @@
+/* $OpenBSD: readconf.h,v 1.90 2011/05/24 07:15:47 djm Exp $ */
+
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for reading the configuration file.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#ifndef READCONF_H
+#define READCONF_H
+
+/* Data structure for representing a forwarding request. */
+
+typedef struct {
+       char     *listen_host;          /* Host (address) to listen on. */
+       int       listen_port;          /* Port to forward. */
+       char     *connect_host;         /* Host to connect. */
+       int       connect_port;         /* Port to connect on connect_host. */
+       int       allocated_port;       /* Dynamically allocated listen port */
+}       Forward;
+/* Data structure for representing option data. */
+
+#define MAX_SEND_ENV           256
+#define SSH_MAX_HOSTS_FILES    256
+
+typedef struct {
+       int     forward_agent;  /* Forward authentication agent. */
+       int     forward_x11;    /* Forward X11 display. */
+       int     forward_x11_timeout;    /* Expiration for Cookies */
+       int     forward_x11_trusted;    /* Trust Forward X11 display. */
+       int     exit_on_forward_failure;        /* Exit if bind(2) fails for -L/-R */
+       char   *xauth_location; /* Location for xauth program */
+       int     gateway_ports;  /* Allow remote connects to forwarded ports. */
+       int     use_privileged_port;    /* Don't use privileged port if false. */
+       int     rhosts_rsa_authentication;      /* Try rhosts with RSA
+                                                * authentication. */
+       int     rsa_authentication;     /* Try RSA authentication. */
+       int     pubkey_authentication;  /* Try ssh2 pubkey authentication. */
+       int     hostbased_authentication;       /* ssh2's rhosts_rsa */
+       int     challenge_response_authentication;
+                                       /* Try S/Key or TIS, authentication. */
+       int     gss_authentication;     /* Try GSS authentication */
+       int     gss_keyex;              /* Try GSS key exchange */
+       int     gss_deleg_creds;        /* Delegate GSS credentials */
+       int     gss_trust_dns;          /* Trust DNS for GSS canonicalization */
+       int     gss_renewal_rekey;      /* Credential renewal forces rekey */
+       char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
+       char    *gss_server_identity;   /* GSSAPI target principal */
+       int     password_authentication;        /* Try password
+                                                * authentication. */
+       int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
+       char    *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
+       int     zero_knowledge_password_authentication; /* Try jpake */
+       int     batch_mode;     /* Batch mode: do not ask for passwords. */
+       int     check_host_ip;  /* Also keep track of keys for IP address */
+       int     strict_host_key_checking;       /* Strict host key checking. */
+       int     compression;    /* Compress packets in both directions. */
+       int     compression_level;      /* Compression level 1 (fast) to 9
+                                        * (best). */
+       int     tcp_keep_alive; /* Set SO_KEEPALIVE. */
+       int     ip_qos_interactive;     /* IP ToS/DSCP/class for interactive */
+       int     ip_qos_bulk;            /* IP ToS/DSCP/class for bulk traffic */
+       LogLevel log_level;     /* Level for logging. */
+
+       int     port;           /* Port to connect. */
+       int     address_family;
+       int     connection_attempts;    /* Max attempts (seconds) before
+                                        * giving up */
+       int     connection_timeout;     /* Max time (seconds) before
+                                        * aborting connection attempt */
+       int     number_of_password_prompts;     /* Max number of password
+                                                * prompts. */
+       int     cipher;         /* Cipher to use. */
+       char   *ciphers;        /* SSH2 ciphers in order of preference. */
+       char   *macs;           /* SSH2 macs in order of preference. */
+       char   *hostkeyalgorithms;      /* SSH2 server key types in order of preference. */
+       char   *kex_algorithms; /* SSH2 kex methods in order of preference. */
+       int     protocol;       /* Protocol in order of preference. */
+       char   *hostname;       /* Real host to connect. */
+       char   *host_key_alias; /* hostname alias for .ssh/known_hosts */
+       char   *proxy_command;  /* Proxy command for connecting the host. */
+       char   *user;           /* User to log in as. */
+       int     escape_char;    /* Escape character; -2 = none */
+
+       u_int   num_system_hostfiles;   /* Paths for /etc/ssh/ssh_known_hosts */
+       char   *system_hostfiles[SSH_MAX_HOSTS_FILES];
+       u_int   num_user_hostfiles;     /* Path for $HOME/.ssh/known_hosts */
+       char   *user_hostfiles[SSH_MAX_HOSTS_FILES];
+       char   *preferred_authentications;
+       char   *bind_address;   /* local socket address for connection to sshd */
+       char   *pkcs11_provider; /* PKCS#11 provider */
+       int     verify_host_key_dns;    /* Verify host key using DNS */
+
+       int     num_identity_files;     /* Number of files for RSA/DSA identities. */
+       char   *identity_files[SSH_MAX_IDENTITY_FILES];
+       Key    *identity_keys[SSH_MAX_IDENTITY_FILES];
+
+       /* Local TCP/IP forward requests. */
+       int     num_local_forwards;
+       Forward *local_forwards;
+
+       /* Remote TCP/IP forward requests. */
+       int     num_remote_forwards;
+       Forward *remote_forwards;
+       int     clear_forwardings;
+
+       int     enable_ssh_keysign;
+       int64_t rekey_limit;
+       int     no_host_authentication_for_localhost;
+       int     identities_only;
+       int     server_alive_interval;
+       int     server_alive_count_max;
+
+       int     num_send_env;
+       char   *send_env[MAX_SEND_ENV];
+
+       char    *control_path;
+       int     control_master;
+       int     control_persist; /* ControlPersist flag */
+       int     control_persist_timeout; /* ControlPersist timeout (seconds) */
+
+       int     hash_known_hosts;
+
+       int     tun_open;       /* tun(4) */
+       int     tun_local;      /* force tun device (optional) */
+       int     tun_remote;     /* force tun device (optional) */
+
+       char    *local_command;
+       int     permit_local_command;
+       int     visual_host_key;
+
+       int     use_roaming;
+
+       int     request_tty;
+}       Options;
+
+#define SSHCTL_MASTER_NO       0
+#define SSHCTL_MASTER_YES      1
+#define SSHCTL_MASTER_AUTO     2
+#define SSHCTL_MASTER_ASK      3
+#define SSHCTL_MASTER_AUTO_ASK 4
+
+#define REQUEST_TTY_AUTO       0
+#define REQUEST_TTY_NO         1
+#define REQUEST_TTY_YES                2
+#define REQUEST_TTY_FORCE      3
+
+void     initialize_options(Options *);
+void     fill_default_options(Options *);
+int     read_config_file(const char *, const char *, Options *, int);
+int     parse_forward(Forward *, const char *, int, int);
+
+int
+process_config_line(Options *, const char *, char *, const char *, int, int *);
+
+void    add_local_forward(Options *, const Forward *);
+void    add_remote_forward(Options *, const Forward *);
+
+#endif                         /* READCONF_H */
diff --git a/.pc/ssh-vulnkey.patch/servconf.c b/.pc/ssh-vulnkey.patch/servconf.c
new file mode 100644 (file)
index 0000000..9bff59d
--- /dev/null
@@ -0,0 +1,1834 @@
+/* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */
+/*
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "compat.h"
+#include "pathnames.h"
+#include "misc.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "mac.h"
+#include "match.h"
+#include "channels.h"
+#include "groupaccess.h"
+
+static void add_listen_addr(ServerOptions *, char *, int);
+static void add_one_listen_addr(ServerOptions *, char *, int);
+
+/* Use of privilege separation or not */
+extern int use_privsep;
+extern Buffer cfg;
+
+/* Initializes the server options to their default values. */
+
+void
+initialize_server_options(ServerOptions *options)
+{
+       memset(options, 0, sizeof(*options));
+
+       /* Portable-specific options */
+       options->use_pam = -1;
+
+       /* Standard Options */
+       options->num_ports = 0;
+       options->ports_from_cmdline = 0;
+       options->listen_addrs = NULL;
+       options->address_family = -1;
+       options->num_host_key_files = 0;
+       options->num_host_cert_files = 0;
+       options->pid_file = NULL;
+       options->server_key_bits = -1;
+       options->login_grace_time = -1;
+       options->key_regeneration_time = -1;
+       options->permit_root_login = PERMIT_NOT_SET;
+       options->ignore_rhosts = -1;
+       options->ignore_user_known_hosts = -1;
+       options->print_motd = -1;
+       options->print_lastlog = -1;
+       options->x11_forwarding = -1;
+       options->x11_display_offset = -1;
+       options->x11_use_localhost = -1;
+       options->xauth_location = NULL;
+       options->strict_modes = -1;
+       options->tcp_keep_alive = -1;
+       options->log_facility = SYSLOG_FACILITY_NOT_SET;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->hostbased_uses_name_from_packet_only = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->kerberos_authentication = -1;
+       options->kerberos_or_local_passwd = -1;
+       options->kerberos_ticket_cleanup = -1;
+       options->kerberos_get_afs_token = -1;
+       options->gss_authentication=-1;
+       options->gss_keyex = -1;
+       options->gss_cleanup_creds = -1;
+       options->gss_strict_acceptor = -1;
+       options->gss_store_rekey = -1;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->permit_empty_passwd = -1;
+       options->permit_user_env = -1;
+       options->use_login = -1;
+       options->compression = -1;
+       options->allow_tcp_forwarding = -1;
+       options->allow_agent_forwarding = -1;
+       options->num_allow_users = 0;
+       options->num_deny_users = 0;
+       options->num_allow_groups = 0;
+       options->num_deny_groups = 0;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->gateway_ports = -1;
+       options->num_subsystems = 0;
+       options->max_startups_begin = -1;
+       options->max_startups_rate = -1;
+       options->max_startups = -1;
+       options->max_authtries = -1;
+       options->max_sessions = -1;
+       options->banner = NULL;
+       options->use_dns = -1;
+       options->client_alive_interval = -1;
+       options->client_alive_count_max = -1;
+       options->num_authkeys_files = 0;
+       options->num_accept_env = 0;
+       options->permit_tun = -1;
+       options->num_permitted_opens = -1;
+       options->adm_forced_command = NULL;
+       options->chroot_directory = NULL;
+       options->zero_knowledge_password_authentication = -1;
+       options->revoked_keys_file = NULL;
+       options->trusted_user_ca_keys = NULL;
+       options->authorized_principals_file = NULL;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+}
+
+void
+fill_default_server_options(ServerOptions *options)
+{
+       /* Portable-specific options */
+       if (options->use_pam == -1)
+               options->use_pam = 0;
+
+       /* Standard Options */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_host_key_files == 0) {
+               /* fill default hostkeys for protocols */
+               if (options->protocol & SSH_PROTO_1)
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_KEY_FILE;
+               if (options->protocol & SSH_PROTO_2) {
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_RSA_KEY_FILE;
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_DSA_KEY_FILE;
+#ifdef OPENSSL_HAS_ECC
+                       options->host_key_files[options->num_host_key_files++] =
+                           _PATH_HOST_ECDSA_KEY_FILE;
+#endif
+               }
+       }
+       /* No certificates by default */
+       if (options->num_ports == 0)
+               options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+       if (options->listen_addrs == NULL)
+               add_listen_addr(options, NULL, 0);
+       if (options->pid_file == NULL)
+               options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
+       if (options->server_key_bits == -1)
+               options->server_key_bits = 1024;
+       if (options->login_grace_time == -1)
+               options->login_grace_time = 120;
+       if (options->key_regeneration_time == -1)
+               options->key_regeneration_time = 3600;
+       if (options->permit_root_login == PERMIT_NOT_SET)
+               options->permit_root_login = PERMIT_YES;
+       if (options->ignore_rhosts == -1)
+               options->ignore_rhosts = 1;
+       if (options->ignore_user_known_hosts == -1)
+               options->ignore_user_known_hosts = 0;
+       if (options->print_motd == -1)
+               options->print_motd = 1;
+       if (options->print_lastlog == -1)
+               options->print_lastlog = 1;
+       if (options->x11_forwarding == -1)
+               options->x11_forwarding = 0;
+       if (options->x11_display_offset == -1)
+               options->x11_display_offset = 10;
+       if (options->x11_use_localhost == -1)
+               options->x11_use_localhost = 1;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->strict_modes == -1)
+               options->strict_modes = 1;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
+               options->log_facility = SYSLOG_FACILITY_AUTH;
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->hostbased_uses_name_from_packet_only == -1)
+               options->hostbased_uses_name_from_packet_only = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->kerberos_authentication == -1)
+               options->kerberos_authentication = 0;
+       if (options->kerberos_or_local_passwd == -1)
+               options->kerberos_or_local_passwd = 1;
+       if (options->kerberos_ticket_cleanup == -1)
+               options->kerberos_ticket_cleanup = 1;
+       if (options->kerberos_get_afs_token == -1)
+               options->kerberos_get_afs_token = 0;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
+       if (options->gss_cleanup_creds == -1)
+               options->gss_cleanup_creds = 1;
+       if (options->gss_strict_acceptor == -1)
+               options->gss_strict_acceptor = 1;
+       if (options->gss_store_rekey == -1)
+               options->gss_store_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 0;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->permit_empty_passwd == -1)
+               options->permit_empty_passwd = 0;
+       if (options->permit_user_env == -1)
+               options->permit_user_env = 0;
+       if (options->use_login == -1)
+               options->use_login = 0;
+       if (options->compression == -1)
+               options->compression = COMP_DELAYED;
+       if (options->allow_tcp_forwarding == -1)
+               options->allow_tcp_forwarding = 1;
+       if (options->allow_agent_forwarding == -1)
+               options->allow_agent_forwarding = 1;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->max_startups == -1)
+               options->max_startups = 10;
+       if (options->max_startups_rate == -1)
+               options->max_startups_rate = 100;               /* 100% */
+       if (options->max_startups_begin == -1)
+               options->max_startups_begin = options->max_startups;
+       if (options->max_authtries == -1)
+               options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
+       if (options->max_sessions == -1)
+               options->max_sessions = DEFAULT_SESSIONS_MAX;
+       if (options->use_dns == -1)
+               options->use_dns = 1;
+       if (options->client_alive_interval == -1)
+               options->client_alive_interval = 0;
+       if (options->client_alive_count_max == -1)
+               options->client_alive_count_max = 3;
+       if (options->num_authkeys_files == 0) {
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
+       }
+       if (options->permit_tun == -1)
+               options->permit_tun = SSH_TUNMODE_NO;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+
+       /* Turn privilege separation on by default */
+       if (use_privsep == -1)
+               use_privsep = PRIVSEP_ON;
+
+#ifndef HAVE_MMAP
+       if (use_privsep && options->compression == 1) {
+               error("This platform does not support both privilege "
+                   "separation and compression");
+               error("Compression disabled");
+               options->compression = 0;
+       }
+#endif
+
+}
+
+/* Keyword tokens. */
+typedef enum {
+       sBadOption,             /* == unknown option */
+       /* Portable-specific options */
+       sUsePAM,
+       /* Standard Options */
+       sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
+       sPermitRootLogin, sLogFacility, sLogLevel,
+       sRhostsRSAAuthentication, sRSAAuthentication,
+       sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
+       sKerberosGetAFSToken,
+       sKerberosTgtPassing, sChallengeResponseAuthentication,
+       sPasswordAuthentication, sKbdInteractiveAuthentication,
+       sListenAddress, sAddressFamily,
+       sPrintMotd, sPrintLastLog, sIgnoreRhosts,
+       sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+       sStrictModes, sEmptyPasswd, sTCPKeepAlive,
+       sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
+       sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+       sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
+       sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
+       sMaxStartups, sMaxAuthTries, sMaxSessions,
+       sBanner, sUseDNS, sHostbasedAuthentication,
+       sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
+       sClientAliveCountMax, sAuthorizedKeysFile,
+       sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+       sGssKeyEx, sGssStoreRekey,
+       sAcceptEnv, sPermitTunnel,
+       sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
+       sUsePrivilegeSeparation, sAllowAgentForwarding,
+       sZeroKnowledgePasswordAuthentication, sHostCertificate,
+       sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+       sKexAlgorithms, sIPQoS,
+       sDeprecated, sUnsupported
+} ServerOpCodes;
+
+#define SSHCFG_GLOBAL  0x01    /* allowed in main section of sshd_config */
+#define SSHCFG_MATCH   0x02    /* allowed inside a Match section */
+#define SSHCFG_ALL     (SSHCFG_GLOBAL|SSHCFG_MATCH)
+
+/* Textual representation of the tokens. */
+static struct {
+       const char *name;
+       ServerOpCodes opcode;
+       u_int flags;
+} keywords[] = {
+       /* Portable-specific options */
+#ifdef USE_PAM
+       { "usepam", sUsePAM, SSHCFG_GLOBAL },
+#else
+       { "usepam", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
+       /* Standard Options */
+       { "port", sPort, SSHCFG_GLOBAL },
+       { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
+       { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },          /* alias */
+       { "pidfile", sPidFile, SSHCFG_GLOBAL },
+       { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
+       { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
+       { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
+       { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
+       { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
+       { "loglevel", sLogLevel, SSHCFG_GLOBAL },
+       { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
+       { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
+       { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
+       { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
+       { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
+       { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
+       { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
+#ifdef KRB5
+       { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
+       { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
+       { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
+#ifdef USE_AFS
+       { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
+#else
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+#endif
+#else
+       { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
+       { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
+       { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
+#ifdef GSSAPI
+       { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+       { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL },
+       { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
+#else
+       { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
+#endif
+       { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
+       { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
+       { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
+       { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
+       { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
+#else
+       { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
+#endif
+       { "checkmail", sDeprecated, SSHCFG_GLOBAL },
+       { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
+       { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
+       { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
+       { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
+       { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
+       { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
+       { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
+       { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
+       { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
+       { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
+       { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
+       { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
+       { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
+       { "uselogin", sUseLogin, SSHCFG_GLOBAL },
+       { "compression", sCompression, SSHCFG_GLOBAL },
+       { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
+       { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },  /* obsolete alias */
+       { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
+       { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
+       { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
+       { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
+       { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
+       { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
+       { "ciphers", sCiphers, SSHCFG_GLOBAL },
+       { "macs", sMacs, SSHCFG_GLOBAL },
+       { "protocol", sProtocol, SSHCFG_GLOBAL },
+       { "gatewayports", sGatewayPorts, SSHCFG_ALL },
+       { "subsystem", sSubsystem, SSHCFG_GLOBAL },
+       { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
+       { "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
+       { "maxsessions", sMaxSessions, SSHCFG_ALL },
+       { "banner", sBanner, SSHCFG_ALL },
+       { "usedns", sUseDNS, SSHCFG_GLOBAL },
+       { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
+       { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
+       { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
+       { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
+       { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
+       { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
+       { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
+       { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
+       { "permittunnel", sPermitTunnel, SSHCFG_ALL },
+       { "match", sMatch, SSHCFG_ALL },
+       { "permitopen", sPermitOpen, SSHCFG_ALL },
+       { "forcecommand", sForceCommand, SSHCFG_ALL },
+       { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+       { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
+       { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
+       { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
+       { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
+       { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+       { "ipqos", sIPQoS, SSHCFG_ALL },
+       { NULL, sBadOption, 0 }
+};
+
+static struct {
+       int val;
+       char *text;
+} tunmode_desc[] = {
+       { SSH_TUNMODE_NO, "no" },
+       { SSH_TUNMODE_POINTOPOINT, "point-to-point" },
+       { SSH_TUNMODE_ETHERNET, "ethernet" },
+       { SSH_TUNMODE_YES, "yes" },
+       { -1, NULL }
+};
+
+/*
+ * Returns the number of the token pointed to by cp or sBadOption.
+ */
+
+static ServerOpCodes
+parse_token(const char *cp, const char *filename,
+           int linenum, u_int *flags)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0) {
+                       *flags = keywords[i].flags;
+                       return keywords[i].opcode;
+               }
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return sBadOption;
+}
+
+char *
+derelativise_path(const char *path)
+{
+       char *expanded, *ret, cwd[MAXPATHLEN];
+
+       expanded = tilde_expand_filename(path, getuid());
+       if (*expanded == '/')
+               return expanded;
+       if (getcwd(cwd, sizeof(cwd)) == NULL)
+               fatal("%s: getcwd: %s", __func__, strerror(errno));
+       xasprintf(&ret, "%s/%s", cwd, expanded);
+       xfree(expanded);
+       return ret;
+}
+
+static void
+add_listen_addr(ServerOptions *options, char *addr, int port)
+{
+       u_int i;
+
+       if (options->num_ports == 0)
+               options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (port == 0)
+               for (i = 0; i < options->num_ports; i++)
+                       add_one_listen_addr(options, addr, options->ports[i]);
+       else
+               add_one_listen_addr(options, addr, port);
+}
+
+static void
+add_one_listen_addr(ServerOptions *options, char *addr, int port)
+{
+       struct addrinfo hints, *ai, *aitop;
+       char strport[NI_MAXSERV];
+       int gaierr;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = options->address_family;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
+       snprintf(strport, sizeof strport, "%d", port);
+       if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
+               fatal("bad addr or host: %s (%s)",
+                   addr ? addr : "<NULL>",
+                   ssh_gai_strerror(gaierr));
+       for (ai = aitop; ai->ai_next; ai = ai->ai_next)
+               ;
+       ai->ai_next = options->listen_addrs;
+       options->listen_addrs = aitop;
+}
+
+/*
+ * The strategy for the Match blocks is that the config file is parsed twice.
+ *
+ * The first time is at startup.  activep is initialized to 1 and the
+ * directives in the global context are processed and acted on.  Hitting a
+ * Match directive unsets activep and the directives inside the block are
+ * checked for syntax only.
+ *
+ * The second time is after a connection has been established but before
+ * authentication.  activep is initialized to 2 and global config directives
+ * are ignored since they have already been processed.  If the criteria in a
+ * Match block is met, activep is set and the subsequent directives
+ * processed and actioned until EOF or another Match block unsets it.  Any
+ * options set are copied into the main server config.
+ *
+ * Potential additions/improvements:
+ *  - Add Match support for pre-kex directives, eg Protocol, Ciphers.
+ *
+ *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
+ *     Match Address 192.168.0.*
+ *             Tag trusted
+ *     Match Group wheel
+ *             Tag trusted
+ *     Match Tag trusted
+ *             AllowTcpForwarding yes
+ *             GatewayPorts clientspecified
+ *             [...]
+ *
+ *  - Add a PermittedChannelRequests directive
+ *     Match Group shell
+ *             PermittedChannelRequests session,forwarded-tcpip
+ */
+
+static int
+match_cfg_line_group(const char *grps, int line, const char *user)
+{
+       int result = 0;
+       struct passwd *pw;
+
+       if (user == NULL)
+               goto out;
+
+       if ((pw = getpwnam(user)) == NULL) {
+               debug("Can't match group at line %d because user %.100s does "
+                   "not exist", line, user);
+       } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+               debug("Can't Match group because user %.100s not in any group "
+                   "at line %d", user, line);
+       } else if (ga_match_pattern_list(grps) != 1) {
+               debug("user %.100s does not match group list %.100s at line %d",
+                   user, grps, line);
+       } else {
+               debug("user %.100s matched group list %.100s at line %d", user,
+                   grps, line);
+               result = 1;
+       }
+out:
+       ga_free();
+       return result;
+}
+
+static int
+match_cfg_line(char **condition, int line, const char *user, const char *host,
+    const char *address)
+{
+       int result = 1;
+       char *arg, *attrib, *cp = *condition;
+       size_t len;
+
+       if (user == NULL)
+               debug3("checking syntax for 'Match %s'", cp);
+       else
+               debug3("checking match for '%s' user %s host %s addr %s", cp,
+                   user ? user : "(null)", host ? host : "(null)",
+                   address ? address : "(null)");
+
+       while ((attrib = strdelim(&cp)) && *attrib != '\0') {
+               if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
+                       error("Missing Match criteria for %s", attrib);
+                       return -1;
+               }
+               len = strlen(arg);
+               if (strcasecmp(attrib, "user") == 0) {
+                       if (!user) {
+                               result = 0;
+                               continue;
+                       }
+                       if (match_pattern_list(user, arg, len, 0) != 1)
+                               result = 0;
+                       else
+                               debug("user %.100s matched 'User %.100s' at "
+                                   "line %d", user, arg, line);
+               } else if (strcasecmp(attrib, "group") == 0) {
+                       switch (match_cfg_line_group(arg, line, user)) {
+                       case -1:
+                               return -1;
+                       case 0:
+                               result = 0;
+                       }
+               } else if (strcasecmp(attrib, "host") == 0) {
+                       if (!host) {
+                               result = 0;
+                               continue;
+                       }
+                       if (match_hostname(host, arg, len) != 1)
+                               result = 0;
+                       else
+                               debug("connection from %.100s matched 'Host "
+                                   "%.100s' at line %d", host, arg, line);
+               } else if (strcasecmp(attrib, "address") == 0) {
+                       switch (addr_match_list(address, arg)) {
+                       case 1:
+                               debug("connection from %.100s matched 'Address "
+                                   "%.100s' at line %d", address, arg, line);
+                               break;
+                       case 0:
+                       case -1:
+                               result = 0;
+                               break;
+                       case -2:
+                               return -1;
+                       }
+               } else {
+                       error("Unsupported Match attribute %s", attrib);
+                       return -1;
+               }
+       }
+       if (user != NULL)
+               debug3("match %sfound", result ? "" : "not ");
+       *condition = cp;
+       return result;
+}
+
+#define WHITESPACE " \t\r\n"
+
+/* Multistate option parsing */
+struct multistate {
+       char *key;
+       int value;
+};
+static const struct multistate multistate_addressfamily[] = {
+       { "inet",                       AF_INET },
+       { "inet6",                      AF_INET6 },
+       { "any",                        AF_UNSPEC },
+       { NULL, -1 }
+};
+static const struct multistate multistate_permitrootlogin[] = {
+       { "without-password",           PERMIT_NO_PASSWD },
+       { "forced-commands-only",       PERMIT_FORCED_ONLY },
+       { "yes",                        PERMIT_YES },
+       { "no",                         PERMIT_NO },
+       { NULL, -1 }
+};
+static const struct multistate multistate_compression[] = {
+       { "delayed",                    COMP_DELAYED },
+       { "yes",                        COMP_ZLIB },
+       { "no",                         COMP_NONE },
+       { NULL, -1 }
+};
+static const struct multistate multistate_gatewayports[] = {
+       { "clientspecified",            2 },
+       { "yes",                        1 },
+       { "no",                         0 },
+       { NULL, -1 }
+};
+static const struct multistate multistate_privsep[] = {
+       { "sandbox",                    PRIVSEP_SANDBOX },
+       { "yes",                        PRIVSEP_ON },
+       { "no",                         PRIVSEP_OFF },
+       { NULL, -1 }
+};
+
+int
+process_server_config_line(ServerOptions *options, char *line,
+    const char *filename, int linenum, int *activep, const char *user,
+    const char *host, const char *address)
+{
+       char *cp, **charptr, *arg, *p;
+       int cmdline = 0, *intptr, value, value2, n;
+       SyslogFacility *log_facility_ptr;
+       LogLevel *log_level_ptr;
+       ServerOpCodes opcode;
+       int port;
+       u_int i, flags = 0;
+       size_t len;
+       const struct multistate *multistate_ptr;
+
+       cp = line;
+       if ((arg = strdelim(&cp)) == NULL)
+               return 0;
+       /* Ignore leading whitespace */
+       if (*arg == '\0')
+               arg = strdelim(&cp);
+       if (!arg || !*arg || *arg == '#')
+               return 0;
+       intptr = NULL;
+       charptr = NULL;
+       opcode = parse_token(arg, filename, linenum, &flags);
+
+       if (activep == NULL) { /* We are processing a command line directive */
+               cmdline = 1;
+               activep = &cmdline;
+       }
+       if (*activep && opcode != sMatch)
+               debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
+       if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
+               if (user == NULL) {
+                       fatal("%s line %d: Directive '%s' is not allowed "
+                           "within a Match block", filename, linenum, arg);
+               } else { /* this is a directive we have already processed */
+                       while (arg)
+                               arg = strdelim(&cp);
+                       return 0;
+               }
+       }
+
+       switch (opcode) {
+       /* Portable-specific options */
+       case sUsePAM:
+               intptr = &options->use_pam;
+               goto parse_flag;
+
+       /* Standard Options */
+       case sBadOption:
+               return -1;
+       case sPort:
+               /* ignore ports from configfile if cmdline specifies ports */
+               if (options->ports_from_cmdline)
+                       return 0;
+               if (options->listen_addrs != NULL)
+                       fatal("%s line %d: ports must be specified before "
+                           "ListenAddress.", filename, linenum);
+               if (options->num_ports >= MAX_PORTS)
+                       fatal("%s line %d: too many ports.",
+                           filename, linenum);
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing port number.",
+                           filename, linenum);
+               options->ports[options->num_ports++] = a2port(arg);
+               if (options->ports[options->num_ports-1] <= 0)
+                       fatal("%s line %d: Badly formatted port number.",
+                           filename, linenum);
+               break;
+
+       case sServerKeyBits:
+               intptr = &options->server_key_bits;
+ parse_int:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing integer value.",
+                           filename, linenum);
+               value = atoi(arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sLoginGraceTime:
+               intptr = &options->login_grace_time;
+ parse_time:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sKeyRegenerationTime:
+               intptr = &options->key_regeneration_time;
+               goto parse_time;
+
+       case sListenAddress:
+               arg = strdelim(&cp);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%s line %d: missing address",
+                           filename, linenum);
+               /* check for bare IPv6 address: no "[]" and 2 or more ":" */
+               if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
+                   && strchr(p+1, ':') != NULL) {
+                       add_listen_addr(options, arg, 0);
+                       break;
+               }
+               p = hpdelim(&arg);
+               if (p == NULL)
+                       fatal("%s line %d: bad address:port usage",
+                           filename, linenum);
+               p = cleanhostname(p);
+               if (arg == NULL)
+                       port = 0;
+               else if ((port = a2port(arg)) <= 0)
+                       fatal("%s line %d: bad port number", filename, linenum);
+
+               add_listen_addr(options, p, port);
+
+               break;
+
+       case sAddressFamily:
+               intptr = &options->address_family;
+               multistate_ptr = multistate_addressfamily;
+               if (options->listen_addrs != NULL)
+                       fatal("%s line %d: address family must be specified "
+                           "before ListenAddress.", filename, linenum);
+ parse_multistate:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               value = -1;
+               for (i = 0; multistate_ptr[i].key != NULL; i++) {
+                       if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
+                               value = multistate_ptr[i].value;
+                               break;
+                       }
+               }
+               if (value == -1)
+                       fatal("%s line %d: unsupported option \"%s\".",
+                           filename, linenum, arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sHostKeyFile:
+               intptr = &options->num_host_key_files;
+               if (*intptr >= MAX_HOSTKEYS)
+                       fatal("%s line %d: too many host keys specified (max %d).",
+                           filename, linenum, MAX_HOSTKEYS);
+               charptr = &options->host_key_files[*intptr];
+ parse_filename:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL) {
+                       *charptr = derelativise_path(arg);
+                       /* increase optional counter */
+                       if (intptr != NULL)
+                               *intptr = *intptr + 1;
+               }
+               break;
+
+       case sHostCertificate:
+               intptr = &options->num_host_cert_files;
+               if (*intptr >= MAX_HOSTKEYS)
+                       fatal("%s line %d: too many host certificates "
+                           "specified (max %d).", filename, linenum,
+                           MAX_HOSTCERTS);
+               charptr = &options->host_cert_files[*intptr];
+               goto parse_filename;
+               break;
+
+       case sPidFile:
+               charptr = &options->pid_file;
+               goto parse_filename;
+
+       case sPermitRootLogin:
+               intptr = &options->permit_root_login;
+               multistate_ptr = multistate_permitrootlogin;
+               goto parse_multistate;
+
+       case sIgnoreRhosts:
+               intptr = &options->ignore_rhosts;
+ parse_flag:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing yes/no argument.",
+                           filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcmp(arg, "yes") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0)
+                       value = 0;
+               else
+                       fatal("%s line %d: Bad yes/no argument: %s",
+                               filename, linenum, arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sIgnoreUserKnownHosts:
+               intptr = &options->ignore_user_known_hosts;
+               goto parse_flag;
+
+       case sRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case sHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case sHostbasedUsesNameFromPacketOnly:
+               intptr = &options->hostbased_uses_name_from_packet_only;
+               goto parse_flag;
+
+       case sRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case sPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case sKerberosAuthentication:
+               intptr = &options->kerberos_authentication;
+               goto parse_flag;
+
+       case sKerberosOrLocalPasswd:
+               intptr = &options->kerberos_or_local_passwd;
+               goto parse_flag;
+
+       case sKerberosTicketCleanup:
+               intptr = &options->kerberos_ticket_cleanup;
+               goto parse_flag;
+
+       case sKerberosGetAFSToken:
+               intptr = &options->kerberos_get_afs_token;
+               goto parse_flag;
+
+       case sGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case sGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
+       case sGssCleanupCreds:
+               intptr = &options->gss_cleanup_creds;
+               goto parse_flag;
+
+       case sGssStrictAcceptor:
+               intptr = &options->gss_strict_acceptor;
+               goto parse_flag;
+
+       case sGssStoreRekey:
+               intptr = &options->gss_store_rekey;
+               goto parse_flag;
+
+       case sPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case sZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case sKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case sChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case sPrintMotd:
+               intptr = &options->print_motd;
+               goto parse_flag;
+
+       case sPrintLastLog:
+               intptr = &options->print_lastlog;
+               goto parse_flag;
+
+       case sX11Forwarding:
+               intptr = &options->x11_forwarding;
+               goto parse_flag;
+
+       case sX11DisplayOffset:
+               intptr = &options->x11_display_offset;
+               goto parse_int;
+
+       case sX11UseLocalhost:
+               intptr = &options->x11_use_localhost;
+               goto parse_flag;
+
+       case sXAuthLocation:
+               charptr = &options->xauth_location;
+               goto parse_filename;
+
+       case sStrictModes:
+               intptr = &options->strict_modes;
+               goto parse_flag;
+
+       case sTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case sEmptyPasswd:
+               intptr = &options->permit_empty_passwd;
+               goto parse_flag;
+
+       case sPermitUserEnvironment:
+               intptr = &options->permit_user_env;
+               goto parse_flag;
+
+       case sUseLogin:
+               intptr = &options->use_login;
+               goto parse_flag;
+
+       case sCompression:
+               intptr = &options->compression;
+               multistate_ptr = multistate_compression;
+               goto parse_multistate;
+
+       case sGatewayPorts:
+               intptr = &options->gateway_ports;
+               multistate_ptr = multistate_gatewayports;
+               goto parse_multistate;
+
+       case sUseDNS:
+               intptr = &options->use_dns;
+               goto parse_flag;
+
+       case sLogFacility:
+               log_facility_ptr = &options->log_facility;
+               arg = strdelim(&cp);
+               value = log_facility_number(arg);
+               if (value == SYSLOG_FACILITY_NOT_SET)
+                       fatal("%.200s line %d: unsupported log facility '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*log_facility_ptr == -1)
+                       *log_facility_ptr = (SyslogFacility) value;
+               break;
+
+       case sLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&cp);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*log_level_ptr == -1)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case sAllowTcpForwarding:
+               intptr = &options->allow_tcp_forwarding;
+               goto parse_flag;
+
+       case sAllowAgentForwarding:
+               intptr = &options->allow_agent_forwarding;
+               goto parse_flag;
+
+       case sUsePrivilegeSeparation:
+               intptr = &use_privsep;
+               multistate_ptr = multistate_privsep;
+               goto parse_multistate;
+
+       case sAllowUsers:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_allow_users >= MAX_ALLOW_USERS)
+                               fatal("%s line %d: too many allow users.",
+                                   filename, linenum);
+                       options->allow_users[options->num_allow_users++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sDenyUsers:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_deny_users >= MAX_DENY_USERS)
+                               fatal("%s line %d: too many deny users.",
+                                   filename, linenum);
+                       options->deny_users[options->num_deny_users++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sAllowGroups:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
+                               fatal("%s line %d: too many allow groups.",
+                                   filename, linenum);
+                       options->allow_groups[options->num_allow_groups++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sDenyGroups:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (options->num_deny_groups >= MAX_DENY_GROUPS)
+                               fatal("%s line %d: too many deny groups.",
+                                   filename, linenum);
+                       options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
+               }
+               break;
+
+       case sCiphers:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case sMacs:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%s line %d: Bad SSH2 mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case sKexAlgorithms:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case sProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case sSubsystem:
+               if (options->num_subsystems >= MAX_SUBSYSTEMS) {
+                       fatal("%s line %d: too many subsystems defined.",
+                           filename, linenum);
+               }
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing subsystem name.",
+                           filename, linenum);
+               if (!*activep) {
+                       arg = strdelim(&cp);
+                       break;
+               }
+               for (i = 0; i < options->num_subsystems; i++)
+                       if (strcmp(arg, options->subsystem_name[i]) == 0)
+                               fatal("%s line %d: Subsystem '%s' already defined.",
+                                   filename, linenum, arg);
+               options->subsystem_name[options->num_subsystems] = xstrdup(arg);
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing subsystem command.",
+                           filename, linenum);
+               options->subsystem_command[options->num_subsystems] = xstrdup(arg);
+
+               /* Collect arguments (separate to executable) */
+               p = xstrdup(arg);
+               len = strlen(p) + 1;
+               while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
+                       len += 1 + strlen(arg);
+                       p = xrealloc(p, 1, len);
+                       strlcat(p, " ", len);
+                       strlcat(p, arg, len);
+               }
+               options->subsystem_args[options->num_subsystems] = p;
+               options->num_subsystems++;
+               break;
+
+       case sMaxStartups:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing MaxStartups spec.",
+                           filename, linenum);
+               if ((n = sscanf(arg, "%d:%d:%d",
+                   &options->max_startups_begin,
+                   &options->max_startups_rate,
+                   &options->max_startups)) == 3) {
+                       if (options->max_startups_begin >
+                           options->max_startups ||
+                           options->max_startups_rate > 100 ||
+                           options->max_startups_rate < 1)
+                               fatal("%s line %d: Illegal MaxStartups spec.",
+                                   filename, linenum);
+               } else if (n != 1)
+                       fatal("%s line %d: Illegal MaxStartups spec.",
+                           filename, linenum);
+               else
+                       options->max_startups = options->max_startups_begin;
+               break;
+
+       case sMaxAuthTries:
+               intptr = &options->max_authtries;
+               goto parse_int;
+
+       case sMaxSessions:
+               intptr = &options->max_sessions;
+               goto parse_int;
+
+       case sBanner:
+               charptr = &options->banner;
+               goto parse_filename;
+
+       /*
+        * These options can contain %X options expanded at
+        * connect time, so that you can specify paths like:
+        *
+        * AuthorizedKeysFile   /etc/ssh_keys/%u
+        */
+       case sAuthorizedKeysFile:
+               if (*activep && options->num_authkeys_files == 0) {
+                       while ((arg = strdelim(&cp)) && *arg != '\0') {
+                               if (options->num_authkeys_files >=
+                                   MAX_AUTHKEYS_FILES)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               options->authorized_keys_files[
+                                   options->num_authkeys_files++] =
+                                   tilde_expand_filename(arg, getuid());
+                       }
+               }
+               return 0;
+
+       case sAuthorizedPrincipalsFile:
+               charptr = &options->authorized_principals_file;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL) {
+                       *charptr = tilde_expand_filename(arg, getuid());
+                       /* increase optional counter */
+                       if (intptr != NULL)
+                               *intptr = *intptr + 1;
+               }
+               break;
+
+       case sClientAliveInterval:
+               intptr = &options->client_alive_interval;
+               goto parse_time;
+
+       case sClientAliveCountMax:
+               intptr = &options->client_alive_count_max;
+               goto parse_int;
+
+       case sAcceptEnv:
+               while ((arg = strdelim(&cp)) && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (options->num_accept_env >= MAX_ACCEPT_ENV)
+                               fatal("%s line %d: too many allow env.",
+                                   filename, linenum);
+                       if (!*activep)
+                               break;
+                       options->accept_env[options->num_accept_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case sPermitTunnel:
+               intptr = &options->permit_tun;
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = -1;
+               for (i = 0; tunmode_desc[i].val != -1; i++)
+                       if (strcmp(tunmode_desc[i].text, arg) == 0) {
+                               value = tunmode_desc[i].val;
+                               break;
+                       }
+               if (value == -1)
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*intptr == -1)
+                       *intptr = value;
+               break;
+
+       case sMatch:
+               if (cmdline)
+                       fatal("Match directive not supported as a command-line "
+                          "option");
+               value = match_cfg_line(&cp, linenum, user, host, address);
+               if (value < 0)
+                       fatal("%s line %d: Bad Match condition", filename,
+                           linenum);
+               *activep = value;
+               break;
+
+       case sPermitOpen:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing PermitOpen specification",
+                           filename, linenum);
+               n = options->num_permitted_opens;       /* modified later */
+               if (strcmp(arg, "any") == 0) {
+                       if (*activep && n == -1) {
+                               channel_clear_adm_permitted_opens();
+                               options->num_permitted_opens = 0;
+                       }
+                       break;
+               }
+               if (*activep && n == -1)
+                       channel_clear_adm_permitted_opens();
+               for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
+                       p = hpdelim(&arg);
+                       if (p == NULL)
+                               fatal("%s line %d: missing host in PermitOpen",
+                                   filename, linenum);
+                       p = cleanhostname(p);
+                       if (arg == NULL || (port = a2port(arg)) <= 0)
+                               fatal("%s line %d: bad port number in "
+                                   "PermitOpen", filename, linenum);
+                       if (*activep && n == -1)
+                               options->num_permitted_opens =
+                                   channel_add_adm_permitted_opens(p, port);
+               }
+               break;
+
+       case sForceCommand:
+               if (cp == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename,
+                           linenum);
+               len = strspn(cp, WHITESPACE);
+               if (*activep && options->adm_forced_command == NULL)
+                       options->adm_forced_command = xstrdup(cp + len);
+               return 0;
+
+       case sChrootDirectory:
+               charptr = &options->chroot_directory;
+
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing file name.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case sTrustedUserCAKeys:
+               charptr = &options->trusted_user_ca_keys;
+               goto parse_filename;
+
+       case sRevokedKeys:
+               charptr = &options->revoked_keys_file;
+               goto parse_filename;
+
+       case sIPQoS:
+               arg = strdelim(&cp);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&cp);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case sDeprecated:
+               logit("%s line %d: Deprecated option %s",
+                   filename, linenum, arg);
+               while (arg)
+                   arg = strdelim(&cp);
+               break;
+
+       case sUnsupported:
+               logit("%s line %d: Unsupported option %s",
+                   filename, linenum, arg);
+               while (arg)
+                   arg = strdelim(&cp);
+               break;
+
+       default:
+               fatal("%s line %d: Missing handler for opcode %s (%d)",
+                   filename, linenum, arg, opcode);
+       }
+       if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
+               fatal("%s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       return 0;
+}
+
+/* Reads the server configuration file. */
+
+void
+load_server_config(const char *filename, Buffer *conf)
+{
+       char line[1024], *cp;
+       FILE *f;
+
+       debug2("%s: filename %s", __func__, filename);
+       if ((f = fopen(filename, "r")) == NULL) {
+               perror(filename);
+               exit(1);
+       }
+       buffer_clear(conf);
+       while (fgets(line, sizeof(line), f)) {
+               /*
+                * Trim out comments and strip whitespace
+                * NB - preserve newlines, they are needed to reproduce
+                * line numbers later for error messages
+                */
+               if ((cp = strchr(line, '#')) != NULL)
+                       memcpy(cp, "\n", 2);
+               cp = line + strspn(line, " \t\r");
+
+               buffer_append(conf, cp, strlen(cp));
+       }
+       buffer_append(conf, "\0", 1);
+       fclose(f);
+       debug2("%s: done config len = %d", __func__, buffer_len(conf));
+}
+
+void
+parse_server_match_config(ServerOptions *options, const char *user,
+    const char *host, const char *address)
+{
+       ServerOptions mo;
+
+       initialize_server_options(&mo);
+       parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
+       copy_set_server_options(options, &mo, 0);
+}
+
+/* Helper macros */
+#define M_CP_INTOPT(n) do {\
+       if (src->n != -1) \
+               dst->n = src->n; \
+} while (0)
+#define M_CP_STROPT(n) do {\
+       if (src->n != NULL) { \
+               if (dst->n != NULL) \
+                       xfree(dst->n); \
+               dst->n = src->n; \
+       } \
+} while(0)
+#define M_CP_STRARRAYOPT(n, num_n) do {\
+       if (src->num_n != 0) { \
+               for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
+                       dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
+       } \
+} while(0)
+
+/*
+ * Copy any supported values that are set.
+ *
+ * If the preauth flag is set, we do not bother copying the string or
+ * array values that are not used pre-authentication, because any that we
+ * do use must be explictly sent in mm_getpwnamallow().
+ */
+void
+copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
+{
+       M_CP_INTOPT(password_authentication);
+       M_CP_INTOPT(gss_authentication);
+       M_CP_INTOPT(rsa_authentication);
+       M_CP_INTOPT(pubkey_authentication);
+       M_CP_INTOPT(kerberos_authentication);
+       M_CP_INTOPT(hostbased_authentication);
+       M_CP_INTOPT(hostbased_uses_name_from_packet_only);
+       M_CP_INTOPT(kbd_interactive_authentication);
+       M_CP_INTOPT(zero_knowledge_password_authentication);
+       M_CP_INTOPT(permit_root_login);
+       M_CP_INTOPT(permit_empty_passwd);
+
+       M_CP_INTOPT(allow_tcp_forwarding);
+       M_CP_INTOPT(allow_agent_forwarding);
+       M_CP_INTOPT(permit_tun);
+       M_CP_INTOPT(gateway_ports);
+       M_CP_INTOPT(x11_display_offset);
+       M_CP_INTOPT(x11_forwarding);
+       M_CP_INTOPT(x11_use_localhost);
+       M_CP_INTOPT(max_sessions);
+       M_CP_INTOPT(max_authtries);
+       M_CP_INTOPT(ip_qos_interactive);
+       M_CP_INTOPT(ip_qos_bulk);
+
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+
+       /*
+        * The only things that should be below this point are string options
+        * which are only used after authentication.
+        */
+       if (preauth)
+               return;
+
+       M_CP_STROPT(adm_forced_command);
+       M_CP_STROPT(chroot_directory);
+}
+
+#undef M_CP_INTOPT
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+
+void
+parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
+    const char *user, const char *host, const char *address)
+{
+       int active, linenum, bad_options = 0;
+       char *cp, *obuf, *cbuf;
+
+       debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
+
+       obuf = cbuf = xstrdup(buffer_ptr(conf));
+       active = user ? 0 : 1;
+       linenum = 1;
+       while ((cp = strsep(&cbuf, "\n")) != NULL) {
+               if (process_server_config_line(options, cp, filename,
+                   linenum++, &active, user, host, address) != 0)
+                       bad_options++;
+       }
+       xfree(obuf);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+}
+
+static const char *
+fmt_multistate_int(int val, const struct multistate *m)
+{
+       u_int i;
+
+       for (i = 0; m[i].key != NULL; i++) {
+               if (m[i].value == val)
+                       return m[i].key;
+       }
+       return "UNKNOWN";
+}
+
+static const char *
+fmt_intarg(ServerOpCodes code, int val)
+{
+       if (val == -1)
+               return "unset";
+       switch (code) {
+       case sAddressFamily:
+               return fmt_multistate_int(val, multistate_addressfamily);
+       case sPermitRootLogin:
+               return fmt_multistate_int(val, multistate_permitrootlogin);
+       case sGatewayPorts:
+               return fmt_multistate_int(val, multistate_gatewayports);
+       case sCompression:
+               return fmt_multistate_int(val, multistate_compression);
+       case sUsePrivilegeSeparation:
+               return fmt_multistate_int(val, multistate_privsep);
+       case sProtocol:
+               switch (val) {
+               case SSH_PROTO_1:
+                       return "1";
+               case SSH_PROTO_2:
+                       return "2";
+               case (SSH_PROTO_1|SSH_PROTO_2):
+                       return "2,1";
+               default:
+                       return "UNKNOWN";
+               }
+       default:
+               switch (val) {
+               case 0:
+                       return "no";
+               case 1:
+                       return "yes";
+               default:
+                       return "UNKNOWN";
+               }
+       }
+}
+
+static const char *
+lookup_opcode_name(ServerOpCodes code)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name != NULL; i++)
+               if (keywords[i].opcode == code)
+                       return(keywords[i].name);
+       return "UNKNOWN";
+}
+
+static void
+dump_cfg_int(ServerOpCodes code, int val)
+{
+       printf("%s %d\n", lookup_opcode_name(code), val);
+}
+
+static void
+dump_cfg_fmtint(ServerOpCodes code, int val)
+{
+       printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
+}
+
+static void
+dump_cfg_string(ServerOpCodes code, const char *val)
+{
+       if (val == NULL)
+               return;
+       printf("%s %s\n", lookup_opcode_name(code), val);
+}
+
+static void
+dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
+{
+       u_int i;
+
+       for (i = 0; i < count; i++)
+               printf("%s %s\n", lookup_opcode_name(code), vals[i]);
+}
+
+static void
+dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
+{
+       u_int i;
+
+       printf("%s", lookup_opcode_name(code));
+       for (i = 0; i < count; i++)
+               printf(" %s",  vals[i]);
+       printf("\n");
+}
+
+void
+dump_config(ServerOptions *o)
+{
+       u_int i;
+       int ret;
+       struct addrinfo *ai;
+       char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
+
+       /* these are usually at the top of the config */
+       for (i = 0; i < o->num_ports; i++)
+               printf("port %d\n", o->ports[i]);
+       dump_cfg_fmtint(sProtocol, o->protocol);
+       dump_cfg_fmtint(sAddressFamily, o->address_family);
+
+       /* ListenAddress must be after Port */
+       for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
+                   sizeof(addr), port, sizeof(port),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           (ret != EAI_SYSTEM) ? gai_strerror(ret) :
+                           strerror(errno));
+               } else {
+                       if (ai->ai_family == AF_INET6)
+                               printf("listenaddress [%s]:%s\n", addr, port);
+                       else
+                               printf("listenaddress %s:%s\n", addr, port);
+               }
+       }
+
+       /* integer arguments */
+#ifdef USE_PAM
+       dump_cfg_int(sUsePAM, o->use_pam);
+#endif
+       dump_cfg_int(sServerKeyBits, o->server_key_bits);
+       dump_cfg_int(sLoginGraceTime, o->login_grace_time);
+       dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
+       dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
+       dump_cfg_int(sMaxAuthTries, o->max_authtries);
+       dump_cfg_int(sMaxSessions, o->max_sessions);
+       dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
+       dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
+
+       /* formatted integer arguments */
+       dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
+       dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
+       dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
+       dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
+       dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
+       dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
+           o->hostbased_uses_name_from_packet_only);
+       dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
+       dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
+#ifdef KRB5
+       dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
+       dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
+       dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
+# ifdef USE_AFS
+       dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
+# endif
+#endif
+#ifdef GSSAPI
+       dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+       dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
+       dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
+       dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
+       dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
+#endif
+#ifdef JPAKE
+       dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
+           o->zero_knowledge_password_authentication);
+#endif
+       dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
+       dump_cfg_fmtint(sKbdInteractiveAuthentication,
+           o->kbd_interactive_authentication);
+       dump_cfg_fmtint(sChallengeResponseAuthentication,
+           o->challenge_response_authentication);
+       dump_cfg_fmtint(sPrintMotd, o->print_motd);
+       dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
+       dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
+       dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
+       dump_cfg_fmtint(sStrictModes, o->strict_modes);
+       dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
+       dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
+       dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
+       dump_cfg_fmtint(sUseLogin, o->use_login);
+       dump_cfg_fmtint(sCompression, o->compression);
+       dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
+       dump_cfg_fmtint(sUseDNS, o->use_dns);
+       dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
+       dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
+
+       /* string arguments */
+       dump_cfg_string(sPidFile, o->pid_file);
+       dump_cfg_string(sXAuthLocation, o->xauth_location);
+       dump_cfg_string(sCiphers, o->ciphers);
+       dump_cfg_string(sMacs, o->macs);
+       dump_cfg_string(sBanner, o->banner);
+       dump_cfg_string(sForceCommand, o->adm_forced_command);
+       dump_cfg_string(sChrootDirectory, o->chroot_directory);
+       dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
+       dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
+       dump_cfg_string(sAuthorizedPrincipalsFile,
+           o->authorized_principals_file);
+
+       /* string arguments requiring a lookup */
+       dump_cfg_string(sLogLevel, log_level_name(o->log_level));
+       dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
+
+       /* string array arguments */
+       dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
+           o->authorized_keys_files);
+       dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
+            o->host_key_files);
+       dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
+            o->host_cert_files);
+       dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
+       dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
+       dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
+       dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
+       dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
+
+       /* other arguments */
+       for (i = 0; i < o->num_subsystems; i++)
+               printf("subsystem %s %s\n", o->subsystem_name[i],
+                   o->subsystem_args[i]);
+
+       printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
+           o->max_startups_rate, o->max_startups);
+
+       for (i = 0; tunmode_desc[i].val != -1; i++)
+               if (tunmode_desc[i].val == o->permit_tun) {
+                       s = tunmode_desc[i].text;
+                       break;
+               }
+       dump_cfg_string(sPermitTunnel, s);
+
+       printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
+       printf("%s\n", iptos2str(o->ip_qos_bulk));
+
+       channel_print_adm_permitted_opens();
+}
diff --git a/.pc/ssh-vulnkey.patch/servconf.h b/.pc/ssh-vulnkey.patch/servconf.h
new file mode 100644 (file)
index 0000000..a434c6f
--- /dev/null
@@ -0,0 +1,201 @@
+/* $OpenBSD: servconf.h,v 1.99 2011/06/22 21:57:01 djm Exp $ */
+
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Definitions for server configuration data and for the functions reading it.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#ifndef SERVCONF_H
+#define SERVCONF_H
+
+#define MAX_PORTS              256     /* Max # ports. */
+
+#define MAX_ALLOW_USERS                256     /* Max # users on allow list. */
+#define MAX_DENY_USERS         256     /* Max # users on deny list. */
+#define MAX_ALLOW_GROUPS       256     /* Max # groups on allow list. */
+#define MAX_DENY_GROUPS                256     /* Max # groups on deny list. */
+#define MAX_SUBSYSTEMS         256     /* Max # subsystems. */
+#define MAX_HOSTKEYS           256     /* Max # hostkeys. */
+#define MAX_HOSTCERTS          256     /* Max # host certificates. */
+#define MAX_ACCEPT_ENV         256     /* Max # of env vars. */
+#define MAX_MATCH_GROUPS       256     /* Max # of groups for Match. */
+#define MAX_AUTHKEYS_FILES     256     /* Max # of authorized_keys files. */
+
+/* permit_root_login */
+#define        PERMIT_NOT_SET          -1
+#define        PERMIT_NO               0
+#define        PERMIT_FORCED_ONLY      1
+#define        PERMIT_NO_PASSWD        2
+#define        PERMIT_YES              3
+
+/* use_privsep */
+#define PRIVSEP_OFF            0
+#define PRIVSEP_ON             1
+#define PRIVSEP_SANDBOX                2
+
+#define DEFAULT_AUTH_FAIL_MAX  6       /* Default for MaxAuthTries */
+#define DEFAULT_SESSIONS_MAX   10      /* Default for MaxSessions */
+
+/* Magic name for internal sftp-server */
+#define INTERNAL_SFTP_NAME     "internal-sftp"
+
+typedef struct {
+       u_int   num_ports;
+       u_int   ports_from_cmdline;
+       int     ports[MAX_PORTS];       /* Port number to listen on. */
+       char   *listen_addr;            /* Address on which the server listens. */
+       struct addrinfo *listen_addrs;  /* Addresses on which the server listens. */
+       int     address_family;         /* Address family used by the server. */
+       char   *host_key_files[MAX_HOSTKEYS];   /* Files containing host keys. */
+       int     num_host_key_files;     /* Number of files for host keys. */
+       char   *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */
+       int     num_host_cert_files;     /* Number of files for host certs. */
+       char   *pid_file;       /* Where to put our pid */
+       int     server_key_bits;/* Size of the server key. */
+       int     login_grace_time;       /* Disconnect if no auth in this time
+                                        * (sec). */
+       int     key_regeneration_time;  /* Server key lifetime (seconds). */
+       int     permit_root_login;      /* PERMIT_*, see above */
+       int     ignore_rhosts;  /* Ignore .rhosts and .shosts. */
+       int     ignore_user_known_hosts;        /* Ignore ~/.ssh/known_hosts
+                                                * for RhostsRsaAuth */
+       int     print_motd;     /* If true, print /etc/motd. */
+       int     print_lastlog;  /* If true, print lastlog */
+       int     x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
+       int     x11_display_offset;     /* What DISPLAY number to start
+                                        * searching at */
+       int     x11_use_localhost;      /* If true, use localhost for fake X11 server. */
+       char   *xauth_location; /* Location of xauth program */
+       int     strict_modes;   /* If true, require string home dir modes. */
+       int     tcp_keep_alive; /* If true, set SO_KEEPALIVE. */
+       int     ip_qos_interactive;     /* IP ToS/DSCP/class for interactive */
+       int     ip_qos_bulk;            /* IP ToS/DSCP/class for bulk traffic */
+       char   *ciphers;        /* Supported SSH2 ciphers. */
+       char   *macs;           /* Supported SSH2 macs. */
+       char   *kex_algorithms; /* SSH2 kex methods in order of preference. */
+       int     protocol;       /* Supported protocol versions. */
+       int     gateway_ports;  /* If true, allow remote connects to forwarded ports. */
+       SyslogFacility log_facility;    /* Facility for system logging. */
+       LogLevel log_level;     /* Level for system logging. */
+       int     rhosts_rsa_authentication;      /* If true, permit rhosts RSA
+                                                * authentication. */
+       int     hostbased_authentication;       /* If true, permit ssh2 hostbased auth */
+       int     hostbased_uses_name_from_packet_only; /* experimental */
+       int     rsa_authentication;     /* If true, permit RSA authentication. */
+       int     pubkey_authentication;  /* If true, permit ssh2 pubkey authentication. */
+       int     kerberos_authentication;        /* If true, permit Kerberos
+                                                * authentication. */
+       int     kerberos_or_local_passwd;       /* If true, permit kerberos
+                                                * and any other password
+                                                * authentication mechanism,
+                                                * such as SecurID or
+                                                * /etc/passwd */
+       int     kerberos_ticket_cleanup;        /* If true, destroy ticket
+                                                * file on logout. */
+       int     kerberos_get_afs_token;         /* If true, try to get AFS token if
+                                                * authenticated with Kerberos. */
+       int     gss_authentication;     /* If true, permit GSSAPI authentication */
+       int     gss_keyex;              /* If true, permit GSSAPI key exchange */
+       int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
+       int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
+       int     gss_store_rekey;
+       int     password_authentication;        /* If true, permit password
+                                                * authentication. */
+       int     kbd_interactive_authentication; /* If true, permit */
+       int     challenge_response_authentication;
+       int     zero_knowledge_password_authentication;
+                                       /* If true, permit jpake auth */
+       int     permit_empty_passwd;    /* If false, do not permit empty
+                                        * passwords. */
+       int     permit_user_env;        /* If true, read ~/.ssh/environment */
+       int     use_login;      /* If true, login(1) is used */
+       int     compression;    /* If true, compression is allowed */
+       int     allow_tcp_forwarding;
+       int     allow_agent_forwarding;
+       u_int num_allow_users;
+       char   *allow_users[MAX_ALLOW_USERS];
+       u_int num_deny_users;
+       char   *deny_users[MAX_DENY_USERS];
+       u_int num_allow_groups;
+       char   *allow_groups[MAX_ALLOW_GROUPS];
+       u_int num_deny_groups;
+       char   *deny_groups[MAX_DENY_GROUPS];
+
+       u_int num_subsystems;
+       char   *subsystem_name[MAX_SUBSYSTEMS];
+       char   *subsystem_command[MAX_SUBSYSTEMS];
+       char   *subsystem_args[MAX_SUBSYSTEMS];
+
+       u_int num_accept_env;
+       char   *accept_env[MAX_ACCEPT_ENV];
+
+       int     max_startups_begin;
+       int     max_startups_rate;
+       int     max_startups;
+       int     max_authtries;
+       int     max_sessions;
+       char   *banner;                 /* SSH-2 banner message */
+       int     use_dns;
+       int     client_alive_interval;  /*
+                                        * poke the client this often to
+                                        * see if it's still there
+                                        */
+       int     client_alive_count_max; /*
+                                        * If the client is unresponsive
+                                        * for this many intervals above,
+                                        * disconnect the session
+                                        */
+
+       u_int num_authkeys_files;       /* Files containing public keys */
+       char   *authorized_keys_files[MAX_AUTHKEYS_FILES];
+
+       char   *adm_forced_command;
+
+       int     use_pam;                /* Enable auth via PAM */
+
+       int     permit_tun;
+
+       int     num_permitted_opens;
+
+       char   *chroot_directory;
+       char   *revoked_keys_file;
+       char   *trusted_user_ca_keys;
+       char   *authorized_principals_file;
+}       ServerOptions;
+
+/*
+ * These are string config options that must be copied between the
+ * Match sub-config and the main config, and must be sent from the
+ * privsep slave to the privsep master. We use a macro to ensure all
+ * the options are copied and the copies are done in the correct order.
+ */
+#define COPY_MATCH_STRING_OPTS() do { \
+               M_CP_STROPT(banner); \
+               M_CP_STROPT(trusted_user_ca_keys); \
+               M_CP_STROPT(revoked_keys_file); \
+               M_CP_STROPT(authorized_principals_file); \
+               M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
+       } while (0)
+
+void    initialize_server_options(ServerOptions *);
+void    fill_default_server_options(ServerOptions *);
+int     process_server_config_line(ServerOptions *, char *, const char *, int,
+            int *, const char *, const char *, const char *);
+void    load_server_config(const char *, Buffer *);
+void    parse_server_config(ServerOptions *, const char *, Buffer *,
+            const char *, const char *, const char *);
+void    parse_server_match_config(ServerOptions *, const char *, const char *,
+            const char *);
+void    copy_set_server_options(ServerOptions *, ServerOptions *, int);
+void    dump_config(ServerOptions *);
+char   *derelativise_path(const char *);
+
+#endif                         /* SERVCONF_H */
diff --git a/.pc/ssh-vulnkey.patch/ssh-add.1 b/.pc/ssh-vulnkey.patch/ssh-add.1
new file mode 100644 (file)
index 0000000..fd48ff9
--- /dev/null
@@ -0,0 +1,195 @@
+.\"    $OpenBSD: ssh-add.1,v 1.55 2010/10/28 18:33:28 jmc Exp $
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd $Mdocdate: October 28 2010 $
+.Dt SSH-ADD 1
+.Os
+.Sh NAME
+.Nm ssh-add
+.Nd adds private key identities to the authentication agent
+.Sh SYNOPSIS
+.Nm ssh-add
+.Op Fl cDdLlXx
+.Op Fl t Ar life
+.Op Ar
+.Nm ssh-add
+.Fl s Ar pkcs11
+.Nm ssh-add
+.Fl e Ar pkcs11
+.Sh DESCRIPTION
+.Nm
+adds private key identities to the authentication agent,
+.Xr ssh-agent 1 .
+When run without arguments, it adds the files
+.Pa ~/.ssh/id_rsa ,
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/identity .
+After loading a private key,
+.Nm
+will try to load corresponding certificate information from the
+filename obtained by appending
+.Pa -cert.pub
+to the name of the private key file.
+Alternative file names can be given on the command line.
+.Pp
+If any file requires a passphrase,
+.Nm
+asks for the passphrase from the user.
+The passphrase is read from the user's tty.
+.Nm
+retries the last passphrase if multiple identity files are given.
+.Pp
+The authentication agent must be running and the
+.Ev SSH_AUTH_SOCK
+environment variable must contain the name of its socket for
+.Nm
+to work.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c
+Indicates that added identities should be subject to confirmation before
+being used for authentication.
+Confirmation is performed by the
+.Ev SSH_ASKPASS
+program mentioned below.
+Successful confirmation is signaled by a zero exit status from the
+.Ev SSH_ASKPASS
+program, rather than text entered into the requester.
+.It Fl D
+Deletes all identities from the agent.
+.It Fl d
+Instead of adding identities, removes identities from the agent.
+If
+.Nm
+has been run without arguments, the keys for the default identities will
+be removed.
+Otherwise, the argument list will be interpreted as a list of paths to
+public key files and matching keys will be removed from the agent.
+If no public key is found at a given path,
+.Nm
+will append
+.Pa .pub
+and retry.
+.It Fl e Ar pkcs11
+Remove keys provided by the PKCS#11 shared library
+.Ar pkcs11 .
+.It Fl L
+Lists public key parameters of all identities currently represented
+by the agent.
+.It Fl l
+Lists fingerprints of all identities currently represented by the agent.
+.It Fl s Ar pkcs11
+Add keys provided by the PKCS#11 shared library
+.Ar pkcs11 .
+.It Fl t Ar life
+Set a maximum lifetime when adding identities to an agent.
+The lifetime may be specified in seconds or in a time format
+specified in
+.Xr sshd_config 5 .
+.It Fl X
+Unlock the agent.
+.It Fl x
+Lock the agent with a password.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev "DISPLAY" and "SSH_ASKPASS"
+If
+.Nm
+needs a passphrase, it will read the passphrase from the current
+terminal if it was run from a terminal.
+If
+.Nm
+does not have a terminal associated with it but
+.Ev DISPLAY
+and
+.Ev SSH_ASKPASS
+are set, it will execute the program specified by
+.Ev SSH_ASKPASS
+and open an X11 window to read the passphrase.
+This is particularly useful when calling
+.Nm
+from a
+.Pa .xsession
+or related script.
+(Note that on some machines it
+may be necessary to redirect the input from
+.Pa /dev/null
+to make this work.)
+.It Ev SSH_AUTH_SOCK
+Identifies the path of a
+.Ux Ns -domain
+socket used to communicate with the agent.
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/identity
+Contains the protocol version 1 RSA authentication identity of the user.
+.It Pa ~/.ssh/id_dsa
+Contains the protocol version 2 DSA authentication identity of the user.
+.It Pa ~/.ssh/id_ecdsa
+Contains the protocol version 2 ECDSA authentication identity of the user.
+.It Pa ~/.ssh/id_rsa
+Contains the protocol version 2 RSA authentication identity of the user.
+.El
+.Pp
+Identity files should not be readable by anyone but the user.
+Note that
+.Nm
+ignores identity files if they are accessible by others.
+.Sh EXIT STATUS
+Exit status is 0 on success, 1 if the specified command fails,
+and 2 if
+.Nm
+is unable to contact the authentication agent.
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-keygen 1 ,
+.Xr sshd 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/ssh-vulnkey.patch/ssh-add.c b/.pc/ssh-vulnkey.patch/ssh-add.c
new file mode 100644 (file)
index 0000000..6d5e2a9
--- /dev/null
@@ -0,0 +1,488 @@
+/* $OpenBSD: ssh-add.c,v 1.101 2011/05/04 21:15:29 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Adds an identity to the authentication server, or removes an identity.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 implementation,
+ * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <openssl/evp.h>
+#include "openbsd-compat/openssl-compat.h"
+
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "rsa.h"
+#include "log.h"
+#include "key.h"
+#include "buffer.h"
+#include "authfd.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "misc.h"
+
+/* argv0 */
+extern char *__progname;
+
+/* Default files to add */
+static char *default_files[] = {
+       _PATH_SSH_CLIENT_ID_RSA,
+       _PATH_SSH_CLIENT_ID_DSA,
+#ifdef OPENSSL_HAS_ECC
+       _PATH_SSH_CLIENT_ID_ECDSA,
+#endif
+       _PATH_SSH_CLIENT_IDENTITY,
+       NULL
+};
+
+/* Default lifetime (0 == forever) */
+static int lifetime = 0;
+
+/* User has to confirm key use */
+static int confirm = 0;
+
+/* we keep a cache of one passphrases */
+static char *pass = NULL;
+static void
+clear_pass(void)
+{
+       if (pass) {
+               memset(pass, 0, strlen(pass));
+               xfree(pass);
+               pass = NULL;
+       }
+}
+
+static int
+delete_file(AuthenticationConnection *ac, const char *filename)
+{
+       Key *public;
+       char *comment = NULL;
+       int ret = -1;
+
+       public = key_load_public(filename, &comment);
+       if (public == NULL) {
+               printf("Bad key file %s\n", filename);
+               return -1;
+       }
+       if (ssh_remove_identity(ac, public)) {
+               fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
+               ret = 0;
+       } else
+               fprintf(stderr, "Could not remove identity: %s\n", filename);
+
+       key_free(public);
+       xfree(comment);
+
+       return ret;
+}
+
+/* Send a request to remove all identities. */
+static int
+delete_all(AuthenticationConnection *ac)
+{
+       int ret = -1;
+
+       if (ssh_remove_all_identities(ac, 1))
+               ret = 0;
+       /* ignore error-code for ssh2 */
+       ssh_remove_all_identities(ac, 2);
+
+       if (ret == 0)
+               fprintf(stderr, "All identities removed.\n");
+       else
+               fprintf(stderr, "Failed to remove all identities.\n");
+
+       return ret;
+}
+
+static int
+add_file(AuthenticationConnection *ac, const char *filename)
+{
+       Key *private, *cert;
+       char *comment = NULL;
+       char msg[1024], *certpath;
+       int fd, perms_ok, ret = -1;
+       Buffer keyblob;
+
+       if (strcmp(filename, "-") == 0) {
+               fd = STDIN_FILENO;
+               filename = "(stdin)";
+       } else if ((fd = open(filename, O_RDONLY)) < 0) {
+               perror(filename);
+               return -1;
+       }
+
+       /*
+        * Since we'll try to load a keyfile multiple times, permission errors
+        * will occur multiple times, so check perms first and bail if wrong.
+        */
+       if (fd != STDIN_FILENO) {
+               perms_ok = key_perm_ok(fd, filename);
+               if (!perms_ok) {
+                       close(fd);
+                       return -1;
+               }
+       }
+       buffer_init(&keyblob);
+       if (!key_load_file(fd, filename, &keyblob)) {
+               buffer_free(&keyblob);
+               close(fd);
+               return -1;
+       }
+       close(fd);
+
+       /* At first, try empty passphrase */
+       private = key_parse_private(&keyblob, filename, "", &comment);
+       if (comment == NULL)
+               comment = xstrdup(filename);
+       /* try last */
+       if (private == NULL && pass != NULL)
+               private = key_parse_private(&keyblob, filename, pass, NULL);
+       if (private == NULL) {
+               /* clear passphrase since it did not work */
+               clear_pass();
+               snprintf(msg, sizeof msg, "Enter passphrase for %.200s: ",
+                   comment);
+               for (;;) {
+                       pass = read_passphrase(msg, RP_ALLOW_STDIN);
+                       if (strcmp(pass, "") == 0) {
+                               clear_pass();
+                               xfree(comment);
+                               buffer_free(&keyblob);
+                               return -1;
+                       }
+                       private = key_parse_private(&keyblob, filename, pass,
+                           &comment);
+                       if (private != NULL)
+                               break;
+                       clear_pass();
+                       snprintf(msg, sizeof msg,
+                           "Bad passphrase, try again for %.200s: ", comment);
+               }
+       }
+       buffer_free(&keyblob);
+
+       if (ssh_add_identity_constrained(ac, private, comment, lifetime,
+           confirm)) {
+               fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
+               ret = 0;
+               if (lifetime != 0)
+                       fprintf(stderr,
+                           "Lifetime set to %d seconds\n", lifetime);
+               if (confirm != 0)
+                       fprintf(stderr,
+                           "The user must confirm each use of the key\n");
+       } else {
+               fprintf(stderr, "Could not add identity: %s\n", filename);
+       }
+
+
+       /* Now try to add the certificate flavour too */
+       xasprintf(&certpath, "%s-cert.pub", filename);
+       if ((cert = key_load_public(certpath, NULL)) == NULL)
+               goto out;
+
+       if (!key_equal_public(cert, private)) {
+               error("Certificate %s does not match private key %s",
+                   certpath, filename);
+               key_free(cert);
+               goto out;
+       } 
+
+       /* Graft with private bits */
+       if (key_to_certified(private, key_cert_is_legacy(cert)) != 0) {
+               error("%s: key_to_certified failed", __func__);
+               key_free(cert);
+               goto out;
+       }
+       key_cert_copy(cert, private);
+       key_free(cert);
+
+       if (!ssh_add_identity_constrained(ac, private, comment,
+           lifetime, confirm)) {
+               error("Certificate %s (%s) add failed", certpath,
+                   private->cert->key_id);
+       }
+       fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
+           private->cert->key_id);
+       if (lifetime != 0)
+               fprintf(stderr, "Lifetime set to %d seconds\n", lifetime);
+       if (confirm != 0)
+               fprintf(stderr, "The user must confirm each use of the key\n");
+ out:
+       xfree(certpath);
+       xfree(comment);
+       key_free(private);
+
+       return ret;
+}
+
+static int
+update_card(AuthenticationConnection *ac, int add, const char *id)
+{
+       char *pin;
+       int ret = -1;
+
+       pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN);
+       if (pin == NULL)
+               return -1;
+
+       if (ssh_update_card(ac, add, id, pin, lifetime, confirm)) {
+               fprintf(stderr, "Card %s: %s\n",
+                   add ? "added" : "removed", id);
+               ret = 0;
+       } else {
+               fprintf(stderr, "Could not %s card: %s\n",
+                   add ? "add" : "remove", id);
+               ret = -1;
+       }
+       xfree(pin);
+       return ret;
+}
+
+static int
+list_identities(AuthenticationConnection *ac, int do_fp)
+{
+       Key *key;
+       char *comment, *fp;
+       int had_identities = 0;
+       int version;
+
+       for (version = 1; version <= 2; version++) {
+               for (key = ssh_get_first_identity(ac, &comment, version);
+                   key != NULL;
+                   key = ssh_get_next_identity(ac, &comment, version)) {
+                       had_identities = 1;
+                       if (do_fp) {
+                               fp = key_fingerprint(key, SSH_FP_MD5,
+                                   SSH_FP_HEX);
+                               printf("%d %s %s (%s)\n",
+                                   key_size(key), fp, comment, key_type(key));
+                               xfree(fp);
+                       } else {
+                               if (!key_write(key, stdout))
+                                       fprintf(stderr, "key_write failed");
+                               fprintf(stdout, " %s\n", comment);
+                       }
+                       key_free(key);
+                       xfree(comment);
+               }
+       }
+       if (!had_identities) {
+               printf("The agent has no identities.\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int
+lock_agent(AuthenticationConnection *ac, int lock)
+{
+       char prompt[100], *p1, *p2;
+       int passok = 1, ret = -1;
+
+       strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
+       p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
+       if (lock) {
+               strlcpy(prompt, "Again: ", sizeof prompt);
+               p2 = read_passphrase(prompt, RP_ALLOW_STDIN);
+               if (strcmp(p1, p2) != 0) {
+                       fprintf(stderr, "Passwords do not match.\n");
+                       passok = 0;
+               }
+               memset(p2, 0, strlen(p2));
+               xfree(p2);
+       }
+       if (passok && ssh_lock_agent(ac, lock, p1)) {
+               fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
+               ret = 0;
+       } else
+               fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un");
+       memset(p1, 0, strlen(p1));
+       xfree(p1);
+       return (ret);
+}
+
+static int
+do_file(AuthenticationConnection *ac, int deleting, char *file)
+{
+       if (deleting) {
+               if (delete_file(ac, file) == -1)
+                       return -1;
+       } else {
+               if (add_file(ac, file) == -1)
+                       return -1;
+       }
+       return 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage: %s [options] [file ...]\n", __progname);
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "  -l          List fingerprints of all identities.\n");
+       fprintf(stderr, "  -L          List public key parameters of all identities.\n");
+       fprintf(stderr, "  -d          Delete identity.\n");
+       fprintf(stderr, "  -D          Delete all identities.\n");
+       fprintf(stderr, "  -x          Lock agent.\n");
+       fprintf(stderr, "  -X          Unlock agent.\n");
+       fprintf(stderr, "  -t life     Set lifetime (in seconds) when adding identities.\n");
+       fprintf(stderr, "  -c          Require confirmation to sign using identities\n");
+       fprintf(stderr, "  -s pkcs11   Add keys from PKCS#11 provider.\n");
+       fprintf(stderr, "  -e pkcs11   Remove keys provided by PKCS#11 provider.\n");
+}
+
+int
+main(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind;
+       AuthenticationConnection *ac = NULL;
+       char *pkcs11provider = NULL;
+       int i, ch, deleting = 0, ret = 0;
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       __progname = ssh_get_progname(argv[0]);
+       seed_rng();
+
+       OpenSSL_add_all_algorithms();
+
+       /* At first, get a connection to the authentication agent. */
+       ac = ssh_get_authentication_connection();
+       if (ac == NULL) {
+               fprintf(stderr,
+                   "Could not open a connection to your authentication agent.\n");
+               exit(2);
+       }
+       while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
+               switch (ch) {
+               case 'l':
+               case 'L':
+                       if (list_identities(ac, ch == 'l' ? 1 : 0) == -1)
+                               ret = 1;
+                       goto done;
+               case 'x':
+               case 'X':
+                       if (lock_agent(ac, ch == 'x' ? 1 : 0) == -1)
+                               ret = 1;
+                       goto done;
+               case 'c':
+                       confirm = 1;
+                       break;
+               case 'd':
+                       deleting = 1;
+                       break;
+               case 'D':
+                       if (delete_all(ac) == -1)
+                               ret = 1;
+                       goto done;
+               case 's':
+                       pkcs11provider = optarg;
+                       break;
+               case 'e':
+                       deleting = 1;
+                       pkcs11provider = optarg;
+                       break;
+               case 't':
+                       if ((lifetime = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid lifetime\n");
+                               ret = 1;
+                               goto done;
+                       }
+                       break;
+               default:
+                       usage();
+                       ret = 1;
+                       goto done;
+               }
+       }
+       argc -= optind;
+       argv += optind;
+       if (pkcs11provider != NULL) {
+               if (update_card(ac, !deleting, pkcs11provider) == -1)
+                       ret = 1;
+               goto done;
+       }
+       if (argc == 0) {
+               char buf[MAXPATHLEN];
+               struct passwd *pw;
+               struct stat st;
+               int count = 0;
+
+               if ((pw = getpwuid(getuid())) == NULL) {
+                       fprintf(stderr, "No user found with uid %u\n",
+                           (u_int)getuid());
+                       ret = 1;
+                       goto done;
+               }
+
+               for (i = 0; default_files[i]; i++) {
+                       snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
+                           default_files[i]);
+                       if (stat(buf, &st) < 0)
+                               continue;
+                       if (do_file(ac, deleting, buf) == -1)
+                               ret = 1;
+                       else
+                               count++;
+               }
+               if (count == 0)
+                       ret = 1;
+       } else {
+               for (i = 0; i < argc; i++) {
+                       if (do_file(ac, deleting, argv[i]) == -1)
+                               ret = 1;
+               }
+       }
+       clear_pass();
+
+done:
+       ssh_close_authentication_connection(ac);
+       return ret;
+}
diff --git a/.pc/ssh-vulnkey.patch/ssh-keygen.1 b/.pc/ssh-vulnkey.patch/ssh-keygen.1
new file mode 100644 (file)
index 0000000..ede3792
--- /dev/null
@@ -0,0 +1,688 @@
+.\"    $OpenBSD: ssh-keygen.1,v 1.106 2011/04/13 04:09:37 djm Exp $
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd $Mdocdate: April 13 2011 $
+.Dt SSH-KEYGEN 1
+.Os
+.Sh NAME
+.Nm ssh-keygen
+.Nd authentication key generation, management and conversion
+.Sh SYNOPSIS
+.Bk -words
+.Nm ssh-keygen
+.Op Fl q
+.Op Fl b Ar bits
+.Fl t Ar type
+.Op Fl N Ar new_passphrase
+.Op Fl C Ar comment
+.Op Fl f Ar output_keyfile
+.Nm ssh-keygen
+.Fl p
+.Op Fl P Ar old_passphrase
+.Op Fl N Ar new_passphrase
+.Op Fl f Ar keyfile
+.Nm ssh-keygen
+.Fl i
+.Op Fl m Ar key_format
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl e
+.Op Fl m Ar key_format
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl y
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl c
+.Op Fl P Ar passphrase
+.Op Fl C Ar comment
+.Op Fl f Ar keyfile
+.Nm ssh-keygen
+.Fl l
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl B
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl D Ar pkcs11
+.Nm ssh-keygen
+.Fl F Ar hostname
+.Op Fl f Ar known_hosts_file
+.Op Fl l
+.Nm ssh-keygen
+.Fl H
+.Op Fl f Ar known_hosts_file
+.Nm ssh-keygen
+.Fl R Ar hostname
+.Op Fl f Ar known_hosts_file
+.Nm ssh-keygen
+.Fl r Ar hostname
+.Op Fl f Ar input_keyfile
+.Op Fl g
+.Nm ssh-keygen
+.Fl G Ar output_file
+.Op Fl v
+.Op Fl b Ar bits
+.Op Fl M Ar memory
+.Op Fl S Ar start_point
+.Nm ssh-keygen
+.Fl T Ar output_file
+.Fl f Ar input_file
+.Op Fl v
+.Op Fl a Ar num_trials
+.Op Fl W Ar generator
+.Nm ssh-keygen
+.Fl s Ar ca_key
+.Fl I Ar certificate_identity
+.Op Fl h
+.Op Fl n Ar principals
+.Op Fl O Ar option
+.Op Fl V Ar validity_interval
+.Op Fl z Ar serial_number
+.Ar
+.Nm ssh-keygen
+.Fl L
+.Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl A
+.Ek
+.Sh DESCRIPTION
+.Nm
+generates, manages and converts authentication keys for
+.Xr ssh 1 .
+.Nm
+can create RSA keys for use by SSH protocol version 1 and DSA, ECDSA or RSA
+keys for use by SSH protocol version 2.
+The type of key to be generated is specified with the
+.Fl t
+option.
+If invoked without any arguments,
+.Nm
+will generate an RSA key for use in SSH protocol 2 connections.
+.Pp
+.Nm
+is also used to generate groups for use in Diffie-Hellman group
+exchange (DH-GEX).
+See the
+.Sx MODULI GENERATION
+section for details.
+.Pp
+Normally each user wishing to use SSH
+with public key authentication runs this once to create the authentication
+key in
+.Pa ~/.ssh/identity ,
+.Pa ~/.ssh/id_ecdsa ,
+.Pa ~/.ssh/id_dsa
+or
+.Pa ~/.ssh/id_rsa .
+Additionally, the system administrator may use this to generate host keys,
+as seen in
+.Pa /etc/rc .
+.Pp
+Normally this program generates the key and asks for a file in which
+to store the private key.
+The public key is stored in a file with the same name but
+.Dq .pub
+appended.
+The program also asks for a passphrase.
+The passphrase may be empty to indicate no passphrase
+(host keys must have an empty passphrase), or it may be a string of
+arbitrary length.
+A passphrase is similar to a password, except it can be a phrase with a
+series of words, punctuation, numbers, whitespace, or any string of
+characters you want.
+Good passphrases are 10-30 characters long, are
+not simple sentences or otherwise easily guessable (English
+prose has only 1-2 bits of entropy per character, and provides very bad
+passphrases), and contain a mix of upper and lowercase letters,
+numbers, and non-alphanumeric characters.
+The passphrase can be changed later by using the
+.Fl p
+option.
+.Pp
+There is no way to recover a lost passphrase.
+If the passphrase is lost or forgotten, a new key must be generated
+and the corresponding public key copied to other machines.
+.Pp
+For RSA1 keys,
+there is also a comment field in the key file that is only for
+convenience to the user to help identify the key.
+The comment can tell what the key is for, or whatever is useful.
+The comment is initialized to
+.Dq user@host
+when the key is created, but can be changed using the
+.Fl c
+option.
+.Pp
+After a key is generated, instructions below detail where the keys
+should be placed to be activated.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl A
+For each of the key types (rsa1, rsa, dsa and ecdsa) for which host keys
+do not exist, generate the host keys with the default key file path,
+an empty passphrase, default bits for the key type, and default comment.
+This is used by
+.Pa /etc/rc
+to generate new host keys.
+.It Fl a Ar trials
+Specifies the number of primality tests to perform when screening DH-GEX
+candidates using the
+.Fl T
+command.
+.It Fl B
+Show the bubblebabble digest of specified private or public key file.
+.It Fl b Ar bits
+Specifies the number of bits in the key to create.
+For RSA keys, the minimum size is 768 bits and the default is 2048 bits.
+Generally, 2048 bits is considered sufficient.
+DSA keys must be exactly 1024 bits as specified by FIPS 186-2.
+For ECDSA keys, the
+.Fl b
+flag determines they key length by selecting from one of three elliptic
+curve sizes: 256, 384 or 521 bits.
+Attempting to use bit lengths other than these three values for ECDSA keys
+will fail.
+.It Fl C Ar comment
+Provides a new comment.
+.It Fl c
+Requests changing the comment in the private and public key files.
+This operation is only supported for RSA1 keys.
+The program will prompt for the file containing the private keys, for
+the passphrase if the key has one, and for the new comment.
+.It Fl D Ar pkcs11
+Download the RSA public keys provided by the PKCS#11 shared library
+.Ar pkcs11 .
+When used in combination with
+.Fl s ,
+this option indicates that a CA key resides in a PKCS#11 token (see the
+.Sx CERTIFICATES
+section for details).
+.It Fl e
+This option will read a private or public OpenSSH key file and
+print to stdout the key in one of the formats specified by the
+.Fl m
+option.
+The default export format is
+.Dq RFC4716 .
+This option allows exporting OpenSSH keys for use by other programs, including
+several commercial SSH implementations.
+.It Fl F Ar hostname
+Search for the specified
+.Ar hostname
+in a
+.Pa known_hosts
+file, listing any occurrences found.
+This option is useful to find hashed host names or addresses and may also be
+used in conjunction with the
+.Fl H
+option to print found keys in a hashed format.
+.It Fl f Ar filename
+Specifies the filename of the key file.
+.It Fl G Ar output_file
+Generate candidate primes for DH-GEX.
+These primes must be screened for
+safety (using the
+.Fl T
+option) before use.
+.It Fl g
+Use generic DNS format when printing fingerprint resource records using the
+.Fl r
+command.
+.It Fl H
+Hash a
+.Pa known_hosts
+file.
+This replaces all hostnames and addresses with hashed representations
+within the specified file; the original content is moved to a file with
+a .old suffix.
+These hashes may be used normally by
+.Nm ssh
+and
+.Nm sshd ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+This option will not modify existing hashed hostnames and is therefore safe
+to use on files that mix hashed and non-hashed names.
+.It Fl h
+When signing a key, create a host certificate instead of a user
+certificate.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl I Ar certificate_identity
+Specify the key identity when signing a public key.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl i
+This option will read an unencrypted private (or public) key file
+in the format specified by the
+.Fl m
+option and print an OpenSSH compatible private
+(or public) key to stdout.
+This option allows importing keys from other software, including several
+commercial SSH implementations.
+The default import format is
+.Dq RFC4716 .
+.It Fl L
+Prints the contents of a certificate.
+.It Fl l
+Show fingerprint of specified public key file.
+Private RSA1 keys are also supported.
+For RSA and DSA keys
+.Nm
+tries to find the matching public key file and prints its fingerprint.
+If combined with
+.Fl v ,
+an ASCII art representation of the key is supplied with the fingerprint.
+.It Fl M Ar memory
+Specify the amount of memory to use (in megabytes) when generating
+candidate moduli for DH-GEX.
+.It Fl m Ar key_format
+Specify a key format for the
+.Fl i
+(import) or
+.Fl e
+(export) conversion options.
+The supported key formats are:
+.Dq RFC4716
+(RFC 4716/SSH2 public or private key),
+.Dq PKCS8
+(PEM PKCS8 public key)
+or
+.Dq PEM
+(PEM public key).
+The default conversion format is
+.Dq RFC4716 .
+.It Fl N Ar new_passphrase
+Provides the new passphrase.
+.It Fl n Ar principals
+Specify one or more principals (user or host names) to be included in
+a certificate when signing a key.
+Multiple principals may be specified, separated by commas.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl O Ar option
+Specify a certificate option when signing a key.
+This option may be specified multiple times.
+Please see the
+.Sx CERTIFICATES
+section for details.
+The options that are valid for user certificates are:
+.Bl -tag -width Ds
+.It Ic clear
+Clear all enabled permissions.
+This is useful for clearing the default set of permissions so permissions may
+be added individually.
+.It Ic force-command Ns = Ns Ar command
+Forces the execution of
+.Ar command
+instead of any shell or command specified by the user when
+the certificate is used for authentication.
+.It Ic no-agent-forwarding
+Disable
+.Xr ssh-agent 1
+forwarding (permitted by default).
+.It Ic no-port-forwarding
+Disable port forwarding (permitted by default).
+.It Ic no-pty
+Disable PTY allocation (permitted by default).
+.It Ic no-user-rc
+Disable execution of
+.Pa ~/.ssh/rc
+by
+.Xr sshd 8
+(permitted by default).
+.It Ic no-x11-forwarding
+Disable X11 forwarding (permitted by default).
+.It Ic permit-agent-forwarding
+Allows
+.Xr ssh-agent 1
+forwarding.
+.It Ic permit-port-forwarding
+Allows port forwarding.
+.It Ic permit-pty
+Allows PTY allocation.
+.It Ic permit-user-rc
+Allows execution of
+.Pa ~/.ssh/rc
+by
+.Xr sshd 8 .
+.It Ic permit-x11-forwarding
+Allows X11 forwarding.
+.It Ic source-address Ns = Ns Ar address_list
+Restrict the source addresses from which the certificate is considered valid.
+The
+.Ar address_list
+is a comma-separated list of one or more address/netmask pairs in CIDR
+format.
+.El
+.Pp
+At present, no options are valid for host keys.
+.It Fl P Ar passphrase
+Provides the (old) passphrase.
+.It Fl p
+Requests changing the passphrase of a private key file instead of
+creating a new private key.
+The program will prompt for the file
+containing the private key, for the old passphrase, and twice for the
+new passphrase.
+.It Fl q
+Silence
+.Nm ssh-keygen .
+.It Fl R Ar hostname
+Removes all keys belonging to
+.Ar hostname
+from a
+.Pa known_hosts
+file.
+This option is useful to delete hashed hosts (see the
+.Fl H
+option above).
+.It Fl r Ar hostname
+Print the SSHFP fingerprint resource record named
+.Ar hostname
+for the specified public key file.
+.It Fl S Ar start
+Specify start point (in hex) when generating candidate moduli for DH-GEX.
+.It Fl s Ar ca_key
+Certify (sign) a public key using the specified CA key.
+Please see the
+.Sx CERTIFICATES
+section for details.
+.It Fl T Ar output_file
+Test DH group exchange candidate primes (generated using the
+.Fl G
+option) for safety.
+.It Fl t Ar type
+Specifies the type of key to create.
+The possible values are
+.Dq rsa1
+for protocol version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+for protocol version 2.
+.It Fl V Ar validity_interval
+Specify a validity interval when signing a certificate.
+A validity interval may consist of a single time, indicating that the
+certificate is valid beginning now and expiring at that time, or may consist
+of two times separated by a colon to indicate an explicit time interval.
+The start time may be specified as a date in YYYYMMDD format, a time
+in YYYYMMDDHHMMSS format or a relative time (to the current time) consisting
+of a minus sign followed by a relative time in the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMMSS time or
+a relative time starting with a plus character.
+.Pp
+For example:
+.Dq +52w1d
+(valid from now to 52 weeks and one day from now),
+.Dq -4w:+4w
+(valid from four weeks ago to four weeks from now),
+.Dq 20100101123000:20110101123000
+(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011),
+.Dq -1d:20110101
+(valid from yesterday to midnight, January 1st, 2011).
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful for debugging moduli generation.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.It Fl W Ar generator
+Specify desired generator when testing candidate moduli for DH-GEX.
+.It Fl y
+This option will read a private
+OpenSSH format file and print an OpenSSH public key to stdout.
+.It Fl z Ar serial_number
+Specifies a serial number to be embedded in the certificate to distinguish
+this certificate from others from the same CA.
+The default serial number is zero.
+.El
+.Sh MODULI GENERATION
+.Nm
+may be used to generate groups for the Diffie-Hellman Group Exchange
+(DH-GEX) protocol.
+Generating these groups is a two-step process: first, candidate
+primes are generated using a fast, but memory intensive process.
+These candidate primes are then tested for suitability (a CPU-intensive
+process).
+.Pp
+Generation of primes is performed using the
+.Fl G
+option.
+The desired length of the primes may be specified by the
+.Fl b
+option.
+For example:
+.Pp
+.Dl # ssh-keygen -G moduli-2048.candidates -b 2048
+.Pp
+By default, the search for primes begins at a random point in the
+desired length range.
+This may be overridden using the
+.Fl S
+option, which specifies a different start point (in hex).
+.Pp
+Once a set of candidates have been generated, they must be tested for
+suitability.
+This may be performed using the
+.Fl T
+option.
+In this mode
+.Nm
+will read candidates from standard input (or a file specified using the
+.Fl f
+option).
+For example:
+.Pp
+.Dl # ssh-keygen -T moduli-2048 -f moduli-2048.candidates
+.Pp
+By default, each candidate will be subjected to 100 primality tests.
+This may be overridden using the
+.Fl a
+option.
+The DH generator value will be chosen automatically for the
+prime under consideration.
+If a specific generator is desired, it may be requested using the
+.Fl W
+option.
+Valid generator values are 2, 3, and 5.
+.Pp
+Screened DH groups may be installed in
+.Pa /etc/moduli .
+It is important that this file contains moduli of a range of bit lengths and
+that both ends of a connection share common moduli.
+.Sh CERTIFICATES
+.Nm
+supports signing of keys to produce certificates that may be used for
+user or host authentication.
+Certificates consist of a public key, some identity information, zero or
+more principal (user or host) names and a set of options that
+are signed by a Certification Authority (CA) key.
+Clients or servers may then trust only the CA key and verify its signature
+on a certificate rather than trusting many user/host keys.
+Note that OpenSSH certificates are a different, and much simpler, format to
+the X.509 certificates used in
+.Xr ssl 8 .
+.Pp
+.Nm
+supports two types of certificates: user and host.
+User certificates authenticate users to servers, whereas host certificates
+authenticate server hosts to users.
+To generate a user certificate:
+.Pp
+.Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub
+.Pp
+The resultant certificate will be placed in
+.Pa /path/to/user_key-cert.pub .
+A host certificate requires the
+.Fl h
+option:
+.Pp
+.Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub
+.Pp
+The host certificate will be output to
+.Pa /path/to/host_key-cert.pub .
+.Pp
+It is possible to sign using a CA key stored in a PKCS#11 token by
+providing the token library using
+.Fl D
+and identifying the CA key by providing its public half as an argument
+to
+.Fl s :
+.Pp
+.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id host_key.pub
+.Pp
+In all cases,
+.Ar key_id
+is a "key identifier" that is logged by the server when the certificate
+is used for authentication.
+.Pp
+Certificates may be limited to be valid for a set of principal (user/host)
+names.
+By default, generated certificates are valid for all users or hosts.
+To generate a certificate for a specified set of principals:
+.Pp
+.Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
+.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub"
+.Pp
+Additional limitations on the validity and use of user certificates may
+be specified through certificate options.
+A certificate option may disable features of the SSH session, may be
+valid only when presented from particular source addresses or may
+force the use of a specific command.
+For a list of valid certificate options, see the documentation for the
+.Fl O
+option above.
+.Pp
+Finally, certificates may be defined with a validity lifetime.
+The
+.Fl V
+option allows specification of certificate start and end times.
+A certificate that is presented at a time outside this range will not be
+considered valid.
+By default, certificates have a maximum validity interval.
+.Pp
+For certificates to be used for user or host authentication, the CA
+public key must be trusted by
+.Xr sshd 8
+or
+.Xr ssh 1 .
+Please refer to those manual pages for details.
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.ssh/identity
+Contains the protocol version 1 RSA authentication identity of the user.
+This file should not be readable by anyone but the user.
+It is possible to
+specify a passphrase when generating the key; that passphrase will be
+used to encrypt the private part of this file using 3DES.
+This file is not automatically accessed by
+.Nm
+but it is offered as the default file for the private key.
+.Xr ssh 1
+will read this file when a login attempt is made.
+.Pp
+.It Pa ~/.ssh/identity.pub
+Contains the protocol version 1 RSA public key for authentication.
+The contents of this file should be added to
+.Pa ~/.ssh/authorized_keys
+on all machines
+where the user wishes to log in using RSA authentication.
+There is no need to keep the contents of this file secret.
+.Pp
+.It Pa ~/.ssh/id_dsa
+.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_rsa
+Contains the protocol version 2 DSA, ECDSA or RSA authentication identity of the user.
+This file should not be readable by anyone but the user.
+It is possible to
+specify a passphrase when generating the key; that passphrase will be
+used to encrypt the private part of this file using 128-bit AES.
+This file is not automatically accessed by
+.Nm
+but it is offered as the default file for the private key.
+.Xr ssh 1
+will read this file when a login attempt is made.
+.Pp
+.It Pa ~/.ssh/id_dsa.pub
+.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_rsa.pub
+Contains the protocol version 2 DSA, ECDSA or RSA public key for authentication.
+The contents of this file should be added to
+.Pa ~/.ssh/authorized_keys
+on all machines
+where the user wishes to log in using public key authentication.
+There is no need to keep the contents of this file secret.
+.Pp
+.It Pa /etc/moduli
+Contains Diffie-Hellman groups used for DH-GEX.
+The file format is described in
+.Xr moduli 5 .
+.El
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr moduli 5 ,
+.Xr sshd 8
+.Rs
+.%R RFC 4716
+.%T "The Secure Shell (SSH) Public Key File Format"
+.%D 2006
+.Re
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/ssh-vulnkey.patch/ssh-vulnkey.1 b/.pc/ssh-vulnkey.patch/ssh-vulnkey.1
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/.pc/ssh-vulnkey.patch/ssh-vulnkey.c b/.pc/ssh-vulnkey.patch/ssh-vulnkey.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/.pc/ssh-vulnkey.patch/ssh.1 b/.pc/ssh-vulnkey.patch/ssh.1
new file mode 100644 (file)
index 0000000..9c1ca4b
--- /dev/null
@@ -0,0 +1,1495 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh.1,v 1.320 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH 1
+.Os
+.Sh NAME
+.Nm ssh
+.Nd OpenSSH SSH client (remote login program)
+.Sh SYNOPSIS
+.Nm ssh
+.Bk -words
+.Op Fl 1246AaCfgKkMNnqsTtVvXxYy
+.Op Fl b Ar bind_address
+.Op Fl c Ar cipher_spec
+.Op Fl D Oo Ar bind_address : Oc Ns Ar port
+.Op Fl e Ar escape_char
+.Op Fl F Ar configfile
+.Op Fl I Ar pkcs11
+.Op Fl i Ar identity_file
+.Op Fl L Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl l Ar login_name
+.Op Fl m Ar mac_spec
+.Op Fl O Ar ctl_cmd
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Op Fl R Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl S Ar ctl_path
+.Op Fl W Ar host : Ns Ar port
+.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
+.Oo Ar user Ns @ Oc Ns Ar hostname
+.Op Ar command
+.Ek
+.Sh DESCRIPTION
+.Nm
+(SSH client) is a program for logging into a remote machine and for
+executing commands on a remote machine.
+It is intended to replace rlogin and rsh,
+and provide secure encrypted communications between
+two untrusted hosts over an insecure network.
+X11 connections and arbitrary TCP ports
+can also be forwarded over the secure channel.
+.Pp
+.Nm
+connects and logs into the specified
+.Ar hostname
+(with optional
+.Ar user
+name).
+The user must prove
+his/her identity to the remote machine using one of several methods
+depending on the protocol version used (see below).
+.Pp
+If
+.Ar command
+is specified,
+it is executed on the remote host instead of a login shell.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 1
+Forces
+.Nm
+to try protocol version 1 only.
+.It Fl 2
+Forces
+.Nm
+to try protocol version 2 only.
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl A
+Enables forwarding of the authentication agent connection.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's
+.Ux Ns -domain
+socket) can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Fl a
+Disables forwarding of the authentication agent connection.
+.It Fl b Ar bind_address
+Use
+.Ar bind_address
+on the local machine as the source address
+of the connection.
+Only useful on systems with more than one address.
+.It Fl C
+Requests compression of all data (including stdin, stdout, stderr, and
+data for forwarded X11 and TCP connections).
+The compression algorithm is the same used by
+.Xr gzip 1 ,
+and the
+.Dq level
+can be controlled by the
+.Cm CompressionLevel
+option for protocol version 1.
+Compression is desirable on modem lines and other
+slow connections, but will only slow down things on fast networks.
+The default value can be set on a host-by-host basis in the
+configuration files; see the
+.Cm Compression
+option.
+.It Fl c Ar cipher_spec
+Selects the cipher specification for encrypting the session.
+.Pp
+Protocol version 1 allows specification of a single cipher.
+The supported values are
+.Dq 3des ,
+.Dq blowfish ,
+and
+.Dq des .
+.Ar 3des
+(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
+It is believed to be secure.
+.Ar blowfish
+is a fast block cipher; it appears very secure and is much faster than
+.Ar 3des .
+.Ar des
+is only supported in the
+.Nm
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.Pp
+For protocol version 2,
+.Ar cipher_spec
+is a comma-separated list of ciphers
+listed in order of preference.
+See the
+.Cm Ciphers
+keyword in
+.Xr ssh_config 5
+for more information.
+.It Fl D Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port
+.Sm on
+.Xc
+Specifies a local
+.Dq dynamic
+application-level port forwarding.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Nm
+will act as a SOCKS server.
+Only root can forward privileged ports.
+Dynamic port forwardings can also be specified in the configuration file.
+.Pp
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl e Ar escape_char
+Sets the escape character for sessions with a pty (default:
+.Ql ~ ) .
+The escape character is only recognized at the beginning of a line.
+The escape character followed by a dot
+.Pq Ql \&.
+closes the connection;
+followed by control-Z suspends the connection;
+and followed by itself sends the escape character once.
+Setting the character to
+.Dq none
+disables any escapes and makes the session fully transparent.
+.It Fl F Ar configfile
+Specifies an alternative per-user configuration file.
+If a configuration file is given on the command line,
+the system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+will be ignored.
+The default for the per-user configuration file is
+.Pa ~/.ssh/config .
+.It Fl f
+Requests
+.Nm
+to go to background just before command execution.
+This is useful if
+.Nm
+is going to ask for passwords or passphrases, but the user
+wants it in the background.
+This implies
+.Fl n .
+The recommended way to start X11 programs at a remote site is with
+something like
+.Ic ssh -f host xterm .
+.Pp
+If the
+.Cm ExitOnForwardFailure
+configuration option is set to
+.Dq yes ,
+then a client started with
+.Fl f
+will wait for all remote port forwards to be successfully established
+before placing itself in the background.
+.It Fl g
+Allows remote hosts to connect to local forwarded ports.
+.It Fl I Ar pkcs11
+Specify the PKCS#11 shared library
+.Nm
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Fl i Ar identity_file
+Selects a file from which the identity (private key) for
+public key authentication is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Identity files may also be specified on
+a per-host basis in the configuration file.
+It is possible to have multiple
+.Fl i
+options (and multiple identities specified in
+configuration files).
+.Nm
+will also try to load certificate information from the filename obtained
+by appending
+.Pa -cert.pub
+to identity filenames.
+.It Fl K
+Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI
+credentials to the server.
+.It Fl k
+Disables forwarding (delegation) of GSSAPI credentials to the server.
+.It Fl L Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the local (client) host is to be
+forwarded to the given host and port on the remote side.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the remote machine.
+Port forwardings can also be specified in the configuration file.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl l Ar login_name
+Specifies the user to log in as on the remote machine.
+This also may be specified on a per-host basis in the configuration file.
+.It Fl M
+Places the
+.Nm
+client into
+.Dq master
+mode for connection sharing.
+Multiple
+.Fl M
+options places
+.Nm
+into
+.Dq master
+mode with confirmation required before slave connections are accepted.
+Refer to the description of
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl m Ar mac_spec
+Additionally, for protocol version 2 a comma-separated list of MAC
+(message authentication code) algorithms can
+be specified in order of preference.
+See the
+.Cm MACs
+keyword for more information.
+.It Fl N
+Do not execute a remote command.
+This is useful for just forwarding ports
+(protocol version 2 only).
+.It Fl n
+Redirects stdin from
+.Pa /dev/null
+(actually, prevents reading from stdin).
+This must be used when
+.Nm
+is run in the background.
+A common trick is to use this to run X11 programs on a remote machine.
+For example,
+.Ic ssh -n shadows.cs.hut.fi emacs &
+will start an emacs on shadows.cs.hut.fi, and the X11
+connection will be automatically forwarded over an encrypted channel.
+The
+.Nm
+program will be put in the background.
+(This does not work if
+.Nm
+needs to ask for a password or passphrase; see also the
+.Fl f
+option.)
+.It Fl O Ar ctl_cmd
+Control an active connection multiplexing master process.
+When the
+.Fl O
+option is specified, the
+.Ar ctl_cmd
+argument is interpreted and passed to the master process.
+Valid commands are:
+.Dq check
+(check that the master process is running),
+.Dq forward
+(request forwardings without command execution),
+.Dq exit
+(request the master to exit), and
+.Dq stop
+(request the master to stop accepting further multiplexing requests).
+.It Fl o Ar option
+Can be used to give options in the format used in the configuration file.
+This is useful for specifying options for which there is no separate
+command-line flag.
+For full details of the options listed below, and their possible values, see
+.Xr ssh_config 5 .
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It AddressFamily
+.It BatchMode
+.It BindAddress
+.It ChallengeResponseAuthentication
+.It CheckHostIP
+.It Cipher
+.It Ciphers
+.It ClearAllForwardings
+.It Compression
+.It CompressionLevel
+.It ConnectionAttempts
+.It ConnectTimeout
+.It ControlMaster
+.It ControlPath
+.It DynamicForward
+.It EscapeChar
+.It ExitOnForwardFailure
+.It ForwardAgent
+.It ForwardX11
+.It ForwardX11Trusted
+.It GatewayPorts
+.It GlobalKnownHostsFile
+.It GSSAPIAuthentication
+.It GSSAPIDelegateCredentials
+.It HashKnownHosts
+.It Host
+.It HostbasedAuthentication
+.It HostKeyAlgorithms
+.It HostKeyAlias
+.It HostName
+.It IdentityFile
+.It IdentitiesOnly
+.It IPQoS
+.It KbdInteractiveDevices
+.It KexAlgorithms
+.It LocalCommand
+.It LocalForward
+.It LogLevel
+.It MACs
+.It NoHostAuthenticationForLocalhost
+.It NumberOfPasswordPrompts
+.It PasswordAuthentication
+.It PermitLocalCommand
+.It PKCS11Provider
+.It Port
+.It PreferredAuthentications
+.It Protocol
+.It ProxyCommand
+.It PubkeyAuthentication
+.It RekeyLimit
+.It RemoteForward
+.It RequestTTY
+.It RhostsRSAAuthentication
+.It RSAAuthentication
+.It SendEnv
+.It ServerAliveInterval
+.It ServerAliveCountMax
+.It StrictHostKeyChecking
+.It TCPKeepAlive
+.It Tunnel
+.It TunnelDevice
+.It UsePrivilegedPort
+.It User
+.It UserKnownHostsFile
+.It VerifyHostKeyDNS
+.It VisualHostKey
+.It XAuthLocation
+.El
+.It Fl p Ar port
+Port to connect to on the remote host.
+This can be specified on a
+per-host basis in the configuration file.
+.It Fl q
+Quiet mode.
+Causes most warning and diagnostic messages to be suppressed.
+.It Fl R Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the remote (server) host is to be
+forwarded to the given host and port on the local side.
+This works by allocating a socket to listen to
+.Ar port
+on the remote side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the local machine.
+.Pp
+Port forwardings can also be specified in the configuration file.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+IPv6 addresses can be specified by enclosing the address in square braces.
+.Pp
+By default, the listening socket on the server will be bound to the loopback
+interface only.
+This may be overridden by specifying a
+.Ar bind_address .
+An empty
+.Ar bind_address ,
+or the address
+.Ql * ,
+indicates that the remote socket should listen on all interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+When used together with
+.Ic -O forward
+the allocated port will be printed to the standard output.
+.It Fl S Ar ctl_path
+Specifies the location of a control socket for connection sharing,
+or the string
+.Dq none
+to disable connection sharing.
+Refer to the description of
+.Cm ControlPath
+and
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl s
+May be used to request invocation of a subsystem on the remote system.
+Subsystems are a feature of the SSH2 protocol which facilitate the use
+of SSH as a secure transport for other applications (eg.\&
+.Xr sftp 1 ) .
+The subsystem is specified as the remote command.
+.It Fl T
+Disable pseudo-tty allocation.
+.It Fl t
+Force pseudo-tty allocation.
+This can be used to execute arbitrary
+screen-based programs on a remote machine, which can be very useful,
+e.g. when implementing menu services.
+Multiple
+.Fl t
+options force tty allocation, even if
+.Nm
+has no local tty.
+.It Fl V
+Display the version number and exit.
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in
+debugging connection, authentication, and configuration problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.It Fl W Ar host : Ns Ar port
+Requests that standard input and output on the client be forwarded to
+.Ar host
+on
+.Ar port
+over the secure channel.
+Implies
+.Fl N ,
+.Fl T ,
+.Cm ExitOnForwardFailure
+and
+.Cm ClearAllForwardings
+and works with Protocol version 2 only.
+.It Fl w Xo
+.Ar local_tun Ns Op : Ns Ar remote_tun
+.Xc
+Requests
+tunnel
+device forwarding with the specified
+.Xr tun 4
+devices between the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+See also the
+.Cm Tunnel
+and
+.Cm TunnelDevice
+directives in
+.Xr ssh_config 5 .
+If the
+.Cm Tunnel
+directive is unset, it is set to the default tunnel mode, which is
+.Dq point-to-point .
+.It Fl X
+Enables X11 forwarding.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring.
+.Pp
+For this reason, X11 forwarding is subjected to X11 SECURITY extension
+restrictions by default.
+Please refer to the
+.Nm
+.Fl Y
+option and the
+.Cm ForwardX11Trusted
+directive in
+.Xr ssh_config 5
+for more information.
+.It Fl x
+Disables X11 forwarding.
+.It Fl Y
+Enables trusted X11 forwarding.
+Trusted X11 forwardings are not subjected to the X11 SECURITY extension
+controls.
+.It Fl y
+Send log information using the
+.Xr syslog 3
+system module.
+By default this information is sent to stderr.
+.El
+.Pp
+.Nm
+may additionally obtain configuration data from
+a per-user configuration file and a system-wide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Sh AUTHENTICATION
+The OpenSSH SSH client supports SSH protocols 1 and 2.
+The default is to use protocol 2 only,
+though this can be changed via the
+.Cm Protocol
+option in
+.Xr ssh_config 5
+or the
+.Fl 1
+and
+.Fl 2
+options (see above).
+Both protocols support similar authentication methods,
+but protocol 2 is the default since
+it provides additional mechanisms for confidentiality
+(the traffic is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour)
+and integrity (hmac-md5, hmac-sha1,
+hmac-sha2-256, hmac-sha2-512,
+umac-64, hmac-ripemd160).
+Protocol 1 lacks a strong mechanism for ensuring the
+integrity of the connection.
+.Pp
+The methods available for authentication are:
+GSSAPI-based authentication,
+host-based authentication,
+public key authentication,
+challenge-response authentication,
+and password authentication.
+Authentication methods are tried in the order specified above,
+though protocol 2 has a configuration option to change the default order:
+.Cm PreferredAuthentications .
+.Pp
+Host-based authentication works as follows:
+If the machine the user logs in from is listed in
+.Pa /etc/hosts.equiv
+or
+.Pa /etc/shosts.equiv
+on the remote machine, and the user names are
+the same on both sides, or if the files
+.Pa ~/.rhosts
+or
+.Pa ~/.shosts
+exist in the user's home directory on the
+remote machine and contain a line containing the name of the client
+machine and the name of the user on that machine, the user is
+considered for login.
+Additionally, the server
+.Em must
+be able to verify the client's
+host key (see the description of
+.Pa /etc/ssh/ssh_known_hosts
+and
+.Pa ~/.ssh/known_hosts ,
+below)
+for login to be permitted.
+This authentication method closes security holes due to IP
+spoofing, DNS spoofing, and routing spoofing.
+[Note to the administrator:
+.Pa /etc/hosts.equiv ,
+.Pa ~/.rhosts ,
+and the rlogin/rsh protocol in general, are inherently insecure and should be
+disabled if security is desired.]
+.Pp
+Public key authentication works as follows:
+The scheme is based on public-key cryptography,
+using cryptosystems
+where encryption and decryption are done using separate keys,
+and it is unfeasible to derive the decryption key from the encryption key.
+The idea is that each user creates a public/private
+key pair for authentication purposes.
+The server knows the public key, and only the user knows the private key.
+.Nm
+implements public key authentication protocol automatically,
+using one of the DSA, ECDSA or RSA algorithms.
+Protocol 1 is restricted to using only RSA keys,
+but protocol 2 may use any.
+The
+.Sx HISTORY
+section of
+.Xr ssl 8
+contains a brief discussion of the DSA and RSA algorithms.
+.Pp
+The file
+.Pa ~/.ssh/authorized_keys
+lists the public keys that are permitted for logging in.
+When the user logs in, the
+.Nm
+program tells the server which key pair it would like to use for
+authentication.
+The client proves that it has access to the private key
+and the server checks that the corresponding public key
+is authorized to accept the account.
+.Pp
+The user creates his/her key pair by running
+.Xr ssh-keygen 1 .
+This stores the private key in
+.Pa ~/.ssh/identity
+(protocol 1),
+.Pa ~/.ssh/id_dsa
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa
+(protocol 2 RSA)
+and stores the public key in
+.Pa ~/.ssh/identity.pub
+(protocol 1),
+.Pa ~/.ssh/id_dsa.pub
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa.pub
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa.pub
+(protocol 2 RSA)
+in the user's home directory.
+The user should then copy the public key
+to
+.Pa ~/.ssh/authorized_keys
+in his/her home directory on the remote machine.
+The
+.Pa authorized_keys
+file corresponds to the conventional
+.Pa ~/.rhosts
+file, and has one key
+per line, though the lines can be very long.
+After this, the user can log in without giving the password.
+.Pp
+A variation on public key authentication
+is available in the form of certificate authentication:
+instead of a set of public/private keys,
+signed certificates are used.
+This has the advantage that a single trusted certification authority
+can be used in place of many public/private keys.
+See the
+.Sx CERTIFICATES
+section of
+.Xr ssh-keygen 1
+for more information.
+.Pp
+The most convenient way to use public key or certificate authentication
+may be with an authentication agent.
+See
+.Xr ssh-agent 1
+for more information.
+.Pp
+Challenge-response authentication works as follows:
+The server sends an arbitrary
+.Qq challenge
+text, and prompts for a response.
+Protocol 2 allows multiple challenges and responses;
+protocol 1 is restricted to just one challenge/response.
+Examples of challenge-response authentication include
+BSD Authentication (see
+.Xr login.conf 5 )
+and PAM (some non-OpenBSD systems).
+.Pp
+Finally, if other authentication methods fail,
+.Nm
+prompts the user for a password.
+The password is sent to the remote
+host for checking; however, since all communications are encrypted,
+the password cannot be seen by someone listening on the network.
+.Pp
+.Nm
+automatically maintains and checks a database containing
+identification for all hosts it has ever been used with.
+Host keys are stored in
+.Pa ~/.ssh/known_hosts
+in the user's home directory.
+Additionally, the file
+.Pa /etc/ssh/ssh_known_hosts
+is automatically checked for known hosts.
+Any new hosts are automatically added to the user's file.
+If a host's identification ever changes,
+.Nm
+warns about this and disables password authentication to prevent
+server spoofing or man-in-the-middle attacks,
+which could otherwise be used to circumvent the encryption.
+The
+.Cm StrictHostKeyChecking
+option can be used to control logins to machines whose
+host key is not known or has changed.
+.Pp
+When the user's identity has been accepted by the server, the server
+either executes the given command, or logs into the machine and gives
+the user a normal shell on the remote machine.
+All communication with
+the remote command or shell will be automatically encrypted.
+.Pp
+If a pseudo-terminal has been allocated (normal login session), the
+user may use the escape characters noted below.
+.Pp
+If no pseudo-tty has been allocated,
+the session is transparent and can be used to reliably transfer binary data.
+On most systems, setting the escape character to
+.Dq none
+will also make the session transparent even if a tty is used.
+.Pp
+The session terminates when the command or shell on the remote
+machine exits and all X11 and TCP connections have been closed.
+.Sh ESCAPE CHARACTERS
+When a pseudo-terminal has been requested,
+.Nm
+supports a number of functions through the use of an escape character.
+.Pp
+A single tilde character can be sent as
+.Ic ~~
+or by following the tilde by a character other than those described below.
+The escape character must always follow a newline to be interpreted as
+special.
+The escape character can be changed in configuration files using the
+.Cm EscapeChar
+configuration directive or on the command line by the
+.Fl e
+option.
+.Pp
+The supported escapes (assuming the default
+.Ql ~ )
+are:
+.Bl -tag -width Ds
+.It Cm ~.
+Disconnect.
+.It Cm ~^Z
+Background
+.Nm .
+.It Cm ~#
+List forwarded connections.
+.It Cm ~&
+Background
+.Nm
+at logout when waiting for forwarded connection / X11 sessions to terminate.
+.It Cm ~?
+Display a list of escape characters.
+.It Cm ~B
+Send a BREAK to the remote system
+(only useful for SSH protocol version 2 and if the peer supports it).
+.It Cm ~C
+Open command line.
+Currently this allows the addition of port forwardings using the
+.Fl L ,
+.Fl R
+and
+.Fl D
+options (see above).
+It also allows the cancellation of existing remote port-forwardings
+using
+.Sm off
+.Fl KR Oo Ar bind_address : Oc Ar port .
+.Sm on
+.Ic !\& Ns Ar command
+allows the user to execute a local command if the
+.Ic PermitLocalCommand
+option is enabled in
+.Xr ssh_config 5 .
+Basic help is available, using the
+.Fl h
+option.
+.It Cm ~R
+Request rekeying of the connection
+(only useful for SSH protocol version 2 and if the peer supports it).
+.El
+.Sh TCP FORWARDING
+Forwarding of arbitrary TCP connections over the secure channel can
+be specified either on the command line or in a configuration file.
+One possible application of TCP forwarding is a secure connection to a
+mail server; another is going through firewalls.
+.Pp
+In the example below, we look at encrypting communication between
+an IRC client and server, even though the IRC server does not directly
+support encrypted communications.
+This works as follows:
+the user connects to the remote host using
+.Nm ,
+specifying a port to be used to forward connections
+to the remote server.
+After that it is possible to start the service which is to be encrypted
+on the client machine,
+connecting to the same local port,
+and
+.Nm
+will encrypt and forward the connection.
+.Pp
+The following example tunnels an IRC session from client machine
+.Dq 127.0.0.1
+(localhost)
+to remote server
+.Dq server.example.com :
+.Bd -literal -offset 4n
+$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
+$ irc -c '#users' -p 1234 pinky 127.0.0.1
+.Ed
+.Pp
+This tunnels a connection to IRC server
+.Dq server.example.com ,
+joining channel
+.Dq #users ,
+nickname
+.Dq pinky ,
+using port 1234.
+It doesn't matter which port is used,
+as long as it's greater than 1023
+(remember, only root can open sockets on privileged ports)
+and doesn't conflict with any ports already in use.
+The connection is forwarded to port 6667 on the remote server,
+since that's the standard port for IRC services.
+.Pp
+The
+.Fl f
+option backgrounds
+.Nm
+and the remote command
+.Dq sleep 10
+is specified to allow an amount of time
+(10 seconds, in the example)
+to start the service which is to be tunnelled.
+If no connections are made within the time specified,
+.Nm
+will exit.
+.Sh X11 FORWARDING
+If the
+.Cm ForwardX11
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl X ,
+.Fl x ,
+and
+.Fl Y
+options above)
+and the user is using X11 (the
+.Ev DISPLAY
+environment variable is set), the connection to the X11 display is
+automatically forwarded to the remote side in such a way that any X11
+programs started from the shell (or command) will go through the
+encrypted channel, and the connection to the real X server will be made
+from the local machine.
+The user should not manually set
+.Ev DISPLAY .
+Forwarding of X11 connections can be
+configured on the command line or in configuration files.
+.Pp
+The
+.Ev DISPLAY
+value set by
+.Nm
+will point to the server machine, but with a display number greater than zero.
+This is normal, and happens because
+.Nm
+creates a
+.Dq proxy
+X server on the server machine for forwarding the
+connections over the encrypted channel.
+.Pp
+.Nm
+will also automatically set up Xauthority data on the server machine.
+For this purpose, it will generate a random authorization cookie,
+store it in Xauthority on the server, and verify that any forwarded
+connections carry this cookie and replace it by the real cookie when
+the connection is opened.
+The real authentication cookie is never
+sent to the server machine (and no cookies are sent in the plain).
+.Pp
+If the
+.Cm ForwardAgent
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl A
+and
+.Fl a
+options above) and
+the user is using an authentication agent, the connection to the agent
+is automatically forwarded to the remote side.
+.Sh VERIFYING HOST KEYS
+When connecting to a server for the first time,
+a fingerprint of the server's public key is presented to the user
+(unless the option
+.Cm StrictHostKeyChecking
+has been disabled).
+Fingerprints can be determined using
+.Xr ssh-keygen 1 :
+.Pp
+.Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
+.Pp
+If the fingerprint is already known, it can be matched
+and the key can be accepted or rejected.
+Because of the difficulty of comparing host keys
+just by looking at hex strings,
+there is also support to compare host keys visually,
+using
+.Em random art .
+By setting the
+.Cm VisualHostKey
+option to
+.Dq yes ,
+a small ASCII graphic gets displayed on every login to a server, no matter
+if the session itself is interactive or not.
+By learning the pattern a known server produces, a user can easily
+find out that the host key has changed when a completely different pattern
+is displayed.
+Because these patterns are not unambiguous however, a pattern that looks
+similar to the pattern remembered only gives a good probability that the
+host key is the same, not guaranteed proof.
+.Pp
+To get a listing of the fingerprints along with their random art for
+all known hosts, the following command line can be used:
+.Pp
+.Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts
+.Pp
+If the fingerprint is unknown,
+an alternative method of verification is available:
+SSH fingerprints verified by DNS.
+An additional resource record (RR),
+SSHFP,
+is added to a zonefile
+and the connecting client is able to match the fingerprint
+with that of the key presented.
+.Pp
+In this example, we are connecting a client to a server,
+.Dq host.example.com .
+The SSHFP resource records should first be added to the zonefile for
+host.example.com:
+.Bd -literal -offset indent
+$ ssh-keygen -r host.example.com.
+.Ed
+.Pp
+The output lines will have to be added to the zonefile.
+To check that the zone is answering fingerprint queries:
+.Pp
+.Dl $ dig -t SSHFP host.example.com
+.Pp
+Finally the client connects:
+.Bd -literal -offset indent
+$ ssh -o "VerifyHostKeyDNS ask" host.example.com
+[...]
+Matching host key fingerprint found in DNS.
+Are you sure you want to continue connecting (yes/no)?
+.Ed
+.Pp
+See the
+.Cm VerifyHostKeyDNS
+option in
+.Xr ssh_config 5
+for more information.
+.Sh SSH-BASED VIRTUAL PRIVATE NETWORKS
+.Nm
+contains support for Virtual Private Network (VPN) tunnelling
+using the
+.Xr tun 4
+network pseudo-device,
+allowing two networks to be joined securely.
+The
+.Xr sshd_config 5
+configuration option
+.Cm PermitTunnel
+controls whether the server supports this,
+and at what level (layer 2 or 3 traffic).
+.Pp
+The following example would connect client network 10.0.50.0/24
+with remote network 10.0.99.0/24 using a point-to-point connection
+from 10.1.1.1 to 10.1.1.2,
+provided that the SSH server running on the gateway to the remote network,
+at 192.168.1.15, allows it.
+.Pp
+On the client:
+.Bd -literal -offset indent
+# ssh -f -w 0:1 192.168.1.15 true
+# ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
+# route add 10.0.99.0/24 10.1.1.2
+.Ed
+.Pp
+On the server:
+.Bd -literal -offset indent
+# ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
+# route add 10.0.50.0/24 10.1.1.1
+.Ed
+.Pp
+Client access may be more finely tuned via the
+.Pa /root/.ssh/authorized_keys
+file (see below) and the
+.Cm PermitRootLogin
+server option.
+The following entry would permit connections on
+.Xr tun 4
+device 1 from user
+.Dq jane
+and on tun device 2 from user
+.Dq john ,
+if
+.Cm PermitRootLogin
+is set to
+.Dq forced-commands-only :
+.Bd -literal -offset 2n
+tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane
+tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john
+.Ed
+.Pp
+Since an SSH-based setup entails a fair amount of overhead,
+it may be more suited to temporary setups,
+such as for wireless VPNs.
+More permanent VPNs are better provided by tools such as
+.Xr ipsecctl 8
+and
+.Xr isakmpd 8 .
+.Sh ENVIRONMENT
+.Nm
+will normally set the following environment variables:
+.Bl -tag -width "SSH_ORIGINAL_COMMAND"
+.It Ev DISPLAY
+The
+.Ev DISPLAY
+variable indicates the location of the X11 server.
+It is automatically set by
+.Nm
+to point to a value of the form
+.Dq hostname:n ,
+where
+.Dq hostname
+indicates the host where the shell runs, and
+.Sq n
+is an integer \*(Ge 1.
+.Nm
+uses this special value to forward X11 connections over the secure
+channel.
+The user should normally not set
+.Ev DISPLAY
+explicitly, as that
+will render the X11 connection insecure (and will require the user to
+manually copy any required authorization cookies).
+.It Ev HOME
+Set to the path of the user's home directory.
+.It Ev LOGNAME
+Synonym for
+.Ev USER ;
+set for compatibility with systems that use this variable.
+.It Ev MAIL
+Set to the path of the user's mailbox.
+.It Ev PATH
+Set to the default
+.Ev PATH ,
+as specified when compiling
+.Nm .
+.It Ev SSH_ASKPASS
+If
+.Nm
+needs a passphrase, it will read the passphrase from the current
+terminal if it was run from a terminal.
+If
+.Nm
+does not have a terminal associated with it but
+.Ev DISPLAY
+and
+.Ev SSH_ASKPASS
+are set, it will execute the program specified by
+.Ev SSH_ASKPASS
+and open an X11 window to read the passphrase.
+This is particularly useful when calling
+.Nm
+from a
+.Pa .xsession
+or related script.
+(Note that on some machines it
+may be necessary to redirect the input from
+.Pa /dev/null
+to make this work.)
+.It Ev SSH_AUTH_SOCK
+Identifies the path of a
+.Ux Ns -domain
+socket used to communicate with the agent.
+.It Ev SSH_CONNECTION
+Identifies the client and server ends of the connection.
+The variable contains
+four space-separated values: client IP address, client port number,
+server IP address, and server port number.
+.It Ev SSH_ORIGINAL_COMMAND
+This variable contains the original command line if a forced command
+is executed.
+It can be used to extract the original arguments.
+.It Ev SSH_TTY
+This is set to the name of the tty (path to the device) associated
+with the current shell or command.
+If the current session has no tty,
+this variable is not set.
+.It Ev TZ
+This variable is set to indicate the present time zone if it
+was set when the daemon was started (i.e. the daemon passes the value
+on to new connections).
+.It Ev USER
+Set to the name of the user logging in.
+.El
+.Pp
+Additionally,
+.Nm
+reads
+.Pa ~/.ssh/environment ,
+and adds lines of the format
+.Dq VARNAME=value
+to the environment if the file exists and users are allowed to
+change their environment.
+For more information, see the
+.Cm PermitUserEnvironment
+option in
+.Xr sshd_config 5 .
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.rhosts
+This file is used for host-based authentication (see above).
+On some machines this file may need to be
+world-readable if the user's home directory is on an NFS partition,
+because
+.Xr sshd 8
+reads it as root.
+Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else.
+The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.Pp
+.It Pa ~/.shosts
+This file is used in exactly the same way as
+.Pa .rhosts ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa ~/.ssh/
+This directory is the default location for all user-specific configuration
+and authentication information.
+There is no general requirement to keep the entire contents of this directory
+secret, but the recommended permissions are read/write/execute for the user,
+and not accessible by others.
+.Pp
+.It Pa ~/.ssh/authorized_keys
+Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as
+this user.
+The format of this file is described in the
+.Xr sshd 8
+manual page.
+This file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.Pp
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+.Pp
+.It Pa ~/.ssh/environment
+Contains additional definitions for environment variables; see
+.Sx ENVIRONMENT ,
+above.
+.Pp
+.It Pa ~/.ssh/identity
+.It Pa ~/.ssh/id_dsa
+.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_rsa
+Contains the private key for authentication.
+These files
+contain sensitive data and should be readable by the user but not
+accessible by others (read/write/execute).
+.Nm
+will simply ignore a private key file if it is accessible by others.
+It is possible to specify a passphrase when
+generating the key which will be used to encrypt the
+sensitive part of this file using 3DES.
+.Pp
+.It Pa ~/.ssh/identity.pub
+.It Pa ~/.ssh/id_dsa.pub
+.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_rsa.pub
+Contains the public key for authentication.
+These files are not
+sensitive and can (but need not) be readable by anyone.
+.Pp
+.It Pa ~/.ssh/known_hosts
+Contains a list of host keys for all hosts the user has logged into
+that are not already in the systemwide list of known host keys.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa ~/.ssh/rc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is
+started.
+See the
+.Xr sshd 8
+manual page for more information.
+.Pp
+.It Pa /etc/hosts.equiv
+This file is for host-based authentication (see above).
+It should only be writable by root.
+.Pp
+.It Pa /etc/shosts.equiv
+This file is used in exactly the same way as
+.Pa hosts.equiv ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Pp
+.It Pa /etc/ssh/ssh_host_key
+.It Pa /etc/ssh/ssh_host_dsa_key
+.It Pa /etc/ssh/ssh_host_ecdsa_key
+.It Pa /etc/ssh/ssh_host_rsa_key
+These three files contain the private parts of the host keys
+and are used for host-based authentication.
+If protocol version 1 is used,
+.Nm
+must be setuid root, since the host key is readable only by root.
+For protocol version 2,
+.Nm
+uses
+.Xr ssh-keysign 8
+to access the host keys,
+eliminating the requirement that
+.Nm
+be setuid root when host-based authentication is used.
+By default
+.Nm
+is not setuid root.
+.Pp
+.It Pa /etc/ssh/ssh_known_hosts
+Systemwide list of known host keys.
+This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization.
+It should be world-readable.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa /etc/ssh/sshrc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is started.
+See the
+.Xr sshd 8
+manual page for more information.
+.El
+.Sh EXIT STATUS
+.Nm
+exits with the exit status of the remote command or with 255
+if an error occurred.
+.Sh SEE ALSO
+.Xr scp 1 ,
+.Xr sftp 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-keygen 1 ,
+.Xr ssh-keyscan 1 ,
+.Xr tun 4 ,
+.Xr hosts.equiv 5 ,
+.Xr ssh_config 5 ,
+.Xr ssh-keysign 8 ,
+.Xr sshd 8
+.Rs
+.%R RFC 4250
+.%T "The Secure Shell (SSH) Protocol Assigned Numbers"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4251
+.%T "The Secure Shell (SSH) Protocol Architecture"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4252
+.%T "The Secure Shell (SSH) Authentication Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4253
+.%T "The Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4254
+.%T "The Secure Shell (SSH) Connection Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4255
+.%T "Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4256
+.%T "Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4335
+.%T "The Secure Shell (SSH) Session Channel Break Extension"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4344
+.%T "The Secure Shell (SSH) Transport Layer Encryption Modes"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4345
+.%T "Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4419
+.%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4716
+.%T "The Secure Shell (SSH) Public Key File Format"
+.%D 2006
+.Re
+.Rs
+.%R RFC 5656
+.%T "Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer"
+.%D 2009
+.Re
+.Rs
+.%T "Hash Visualization: a New Technique to improve Real-World Security"
+.%A A. Perrig
+.%A D. Song
+.%D 1999
+.%O "International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)"
+.Re
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/ssh-vulnkey.patch/ssh.c b/.pc/ssh-vulnkey.patch/ssh.c
new file mode 100644 (file)
index 0000000..c717dcf
--- /dev/null
@@ -0,0 +1,1588 @@
+/* $OpenBSD: ssh.c,v 1.364 2011/08/02 23:15:03 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Ssh client program.  This program can be used to log into a remote machine.
+ * The software supports strong authentication, encryption, and forwarding
+ * of X11, TCP/IP, and authentication connections.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * Copyright (c) 1999 Niels Provos.  All rights reserved.
+ * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl.  All rights reserved.
+ *
+ * Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
+ * in Canada (German citizen).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "openbsd-compat/openssl-compat.h"
+#include "openbsd-compat/sys-queue.h"
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "canohost.h"
+#include "compat.h"
+#include "cipher.h"
+#include "packet.h"
+#include "buffer.h"
+#include "channels.h"
+#include "key.h"
+#include "authfd.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "dispatch.h"
+#include "clientloop.h"
+#include "log.h"
+#include "readconf.h"
+#include "sshconnect.h"
+#include "misc.h"
+#include "kex.h"
+#include "mac.h"
+#include "sshpty.h"
+#include "match.h"
+#include "msg.h"
+#include "uidswap.h"
+#include "roaming.h"
+#include "version.h"
+
+#ifdef ENABLE_PKCS11
+#include "ssh-pkcs11.h"
+#endif
+
+extern char *__progname;
+
+/* Saves a copy of argv for setproctitle emulation */
+#ifndef HAVE_SETPROCTITLE
+static char **saved_av;
+#endif
+
+/* Flag indicating whether debug mode is on.  May be set on the command line. */
+int debug_flag = 0;
+
+/* Flag indicating whether a tty should be requested */
+int tty_flag = 0;
+
+/* don't exec a shell */
+int no_shell_flag = 0;
+
+/*
+ * Flag indicating that nothing should be read from stdin.  This can be set
+ * on the command line.
+ */
+int stdin_null_flag = 0;
+
+/*
+ * Flag indicating that the current process should be backgrounded and
+ * a new slave launched in the foreground for ControlPersist.
+ */
+int need_controlpersist_detach = 0;
+
+/* Copies of flags for ControlPersist foreground slave */
+int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
+
+/*
+ * Flag indicating that ssh should fork after authentication.  This is useful
+ * so that the passphrase can be entered manually, and then ssh goes to the
+ * background.
+ */
+int fork_after_authentication_flag = 0;
+
+/* forward stdio to remote host and port */
+char *stdio_forward_host = NULL;
+int stdio_forward_port = 0;
+
+/*
+ * General data structure for command line options and options configurable
+ * in configuration files.  See readconf.h.
+ */
+Options options;
+
+/* optional user configfile */
+char *config = NULL;
+
+/*
+ * Name of the host we are connecting to.  This is the name given on the
+ * command line, or the HostName specified for the user-supplied name in a
+ * configuration file.
+ */
+char *host;
+
+/* socket address the host resolves to */
+struct sockaddr_storage hostaddr;
+
+/* Private host keys. */
+Sensitive sensitive_data;
+
+/* Original real UID. */
+uid_t original_real_uid;
+uid_t original_effective_uid;
+
+/* command to be executed */
+Buffer command;
+
+/* Should we execute a command or invoke a subsystem? */
+int subsystem_flag = 0;
+
+/* # of replies received for global requests */
+static int remote_forward_confirms_received = 0;
+
+/* mux.c */
+extern int muxserver_sock;
+extern u_int muxclient_command;
+
+/* Prints a help message to the user.  This function never returns. */
+
+static void
+usage(void)
+{
+       fprintf(stderr,
+"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
+"           [-D [bind_address:]port] [-e escape_char] [-F configfile]\n"
+"           [-I pkcs11] [-i identity_file]\n"
+"           [-L [bind_address:]port:host:hostport]\n"
+"           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
+"           [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
+"           [-W host:port] [-w local_tun[:remote_tun]]\n"
+"           [user@]hostname [command]\n"
+       );
+       exit(255);
+}
+
+static int ssh_session(void);
+static int ssh_session2(void);
+static void load_public_identity_files(void);
+static void main_sigchld_handler(int);
+
+/* from muxclient.c */
+void muxclient(const char *);
+void muxserver_listen(void);
+
+/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
+static void
+tilde_expand_paths(char **paths, u_int num_paths)
+{
+       u_int i;
+       char *cp;
+
+       for (i = 0; i < num_paths; i++) {
+               cp = tilde_expand_filename(paths[i], original_real_uid);
+               xfree(paths[i]);
+               paths[i] = cp;
+       }
+}
+
+/*
+ * Main program for the ssh client.
+ */
+int
+main(int ac, char **av)
+{
+       int i, r, opt, exit_status, use_syslog;
+       char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg;
+       char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
+       struct stat st;
+       struct passwd *pw;
+       int dummy, timeout_ms;
+       extern int optind, optreset;
+       extern char *optarg;
+
+       struct servent *sp;
+       Forward fwd;
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       __progname = ssh_get_progname(av[0]);
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       /* Save argv so it isn't clobbered by setproctitle() emulation */
+       saved_av = xcalloc(ac + 1, sizeof(*saved_av));
+       for (i = 0; i < ac; i++)
+               saved_av[i] = xstrdup(av[i]);
+       saved_av[i] = NULL;
+       compat_init_setproctitle(ac, av);
+       av = saved_av;
+#endif
+
+       /*
+        * Discard other fds that are hanging around. These can cause problem
+        * with backgrounded ssh processes started by ControlPersist.
+        */
+       closefrom(STDERR_FILENO + 1);
+
+       /*
+        * Save the original real uid.  It will be needed later (uid-swapping
+        * may clobber the real uid).
+        */
+       original_real_uid = getuid();
+       original_effective_uid = geteuid();
+
+       /*
+        * Use uid-swapping to give up root privileges for the duration of
+        * option processing.  We will re-instantiate the rights when we are
+        * ready to create the privileged port, and will permanently drop
+        * them when the port has been created (actually, when the connection
+        * has been made, as we may need to create the port several times).
+        */
+       PRIV_END;
+
+#ifdef HAVE_SETRLIMIT
+       /* If we are installed setuid root be careful to not drop core. */
+       if (original_real_uid != original_effective_uid) {
+               struct rlimit rlim;
+               rlim.rlim_cur = rlim.rlim_max = 0;
+               if (setrlimit(RLIMIT_CORE, &rlim) < 0)
+                       fatal("setrlimit failed: %.100s", strerror(errno));
+       }
+#endif
+       /* Get user data. */
+       pw = getpwuid(original_real_uid);
+       if (!pw) {
+               logit("You don't exist, go away!");
+               exit(255);
+       }
+       /* Take a copy of the returned structure. */
+       pw = pwcopy(pw);
+
+       /*
+        * Set our umask to something reasonable, as some files are created
+        * with the default umask.  This will make them world-readable but
+        * writable only by the owner, which is ok for all files for which we
+        * don't set the modes explicitly.
+        */
+       umask(022);
+
+       /*
+        * Initialize option structure to indicate that no values have been
+        * set.
+        */
+       initialize_options(&options);
+
+       /* Parse command-line arguments. */
+       host = NULL;
+       use_syslog = 0;
+       argv0 = av[0];
+
+ again:
+       while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
+           "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) {
+               switch (opt) {
+               case '1':
+                       options.protocol = SSH_PROTO_1;
+                       break;
+               case '2':
+                       options.protocol = SSH_PROTO_2;
+                       break;
+               case '4':
+                       options.address_family = AF_INET;
+                       break;
+               case '6':
+                       options.address_family = AF_INET6;
+                       break;
+               case 'n':
+                       stdin_null_flag = 1;
+                       break;
+               case 'f':
+                       fork_after_authentication_flag = 1;
+                       stdin_null_flag = 1;
+                       break;
+               case 'x':
+                       options.forward_x11 = 0;
+                       break;
+               case 'X':
+                       options.forward_x11 = 1;
+                       break;
+               case 'y':
+                       use_syslog = 1;
+                       break;
+               case 'Y':
+                       options.forward_x11 = 1;
+                       options.forward_x11_trusted = 1;
+                       break;
+               case 'g':
+                       options.gateway_ports = 1;
+                       break;
+               case 'O':
+                       if (stdio_forward_host != NULL)
+                               fatal("Cannot specify multiplexing "
+                                   "command with -W");
+                       else if (muxclient_command != 0)
+                               fatal("Multiplexing command already specified");
+                       if (strcmp(optarg, "check") == 0)
+                               muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
+                       else if (strcmp(optarg, "forward") == 0)
+                               muxclient_command = SSHMUX_COMMAND_FORWARD;
+                       else if (strcmp(optarg, "exit") == 0)
+                               muxclient_command = SSHMUX_COMMAND_TERMINATE;
+                       else if (strcmp(optarg, "stop") == 0)
+                               muxclient_command = SSHMUX_COMMAND_STOP;
+                       else
+                               fatal("Invalid multiplex command.");
+                       break;
+               case 'P':       /* deprecated */
+                       options.use_privileged_port = 0;
+                       break;
+               case 'a':
+                       options.forward_agent = 0;
+                       break;
+               case 'A':
+                       options.forward_agent = 1;
+                       break;
+               case 'k':
+                       options.gss_deleg_creds = 0;
+                       break;
+               case 'K':
+                       options.gss_authentication = 1;
+                       options.gss_deleg_creds = 1;
+                       break;
+               case 'i':
+                       if (stat(optarg, &st) < 0) {
+                               fprintf(stderr, "Warning: Identity file %s "
+                                   "not accessible: %s.\n", optarg,
+                                   strerror(errno));
+                               break;
+                       }
+                       if (options.num_identity_files >=
+                           SSH_MAX_IDENTITY_FILES)
+                               fatal("Too many identity files specified "
+                                   "(max %d)", SSH_MAX_IDENTITY_FILES);
+                       options.identity_files[options.num_identity_files++] =
+                           xstrdup(optarg);
+                       break;
+               case 'I':
+#ifdef ENABLE_PKCS11
+                       options.pkcs11_provider = xstrdup(optarg);
+#else
+                       fprintf(stderr, "no support for PKCS#11.\n");
+#endif
+                       break;
+               case 't':
+                       if (options.request_tty == REQUEST_TTY_YES)
+                               options.request_tty = REQUEST_TTY_FORCE;
+                       else
+                               options.request_tty = REQUEST_TTY_YES;
+                       break;
+               case 'v':
+                       if (debug_flag == 0) {
+                               debug_flag = 1;
+                               options.log_level = SYSLOG_LEVEL_DEBUG1;
+                       } else {
+                               if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                                       options.log_level++;
+                               break;
+                       }
+                       /* FALLTHROUGH */
+               case 'V':
+                       fprintf(stderr, "%s, %s\n",
+                           SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+                       if (opt == 'V')
+                               exit(0);
+                       break;
+               case 'w':
+                       if (options.tun_open == -1)
+                               options.tun_open = SSH_TUNMODE_DEFAULT;
+                       options.tun_local = a2tun(optarg, &options.tun_remote);
+                       if (options.tun_local == SSH_TUNID_ERR) {
+                               fprintf(stderr,
+                                   "Bad tun device '%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'W':
+                       if (stdio_forward_host != NULL)
+                               fatal("stdio forward already specified");
+                       if (muxclient_command != 0)
+                               fatal("Cannot specify stdio forward with -O");
+                       if (parse_forward(&fwd, optarg, 1, 0)) {
+                               stdio_forward_host = fwd.listen_host;
+                               stdio_forward_port = fwd.listen_port;
+                               xfree(fwd.connect_host);
+                       } else {
+                               fprintf(stderr,
+                                   "Bad stdio forwarding specification '%s'\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       options.request_tty = REQUEST_TTY_NO;
+                       no_shell_flag = 1;
+                       options.clear_forwardings = 1;
+                       options.exit_on_forward_failure = 1;
+                       break;
+               case 'q':
+                       options.log_level = SYSLOG_LEVEL_QUIET;
+                       break;
+               case 'e':
+                       if (optarg[0] == '^' && optarg[2] == 0 &&
+                           (u_char) optarg[1] >= 64 &&
+                           (u_char) optarg[1] < 128)
+                               options.escape_char = (u_char) optarg[1] & 31;
+                       else if (strlen(optarg) == 1)
+                               options.escape_char = (u_char) optarg[0];
+                       else if (strcmp(optarg, "none") == 0)
+                               options.escape_char = SSH_ESCAPECHAR_NONE;
+                       else {
+                               fprintf(stderr, "Bad escape character '%s'.\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'c':
+                       if (ciphers_valid(optarg)) {
+                               /* SSH2 only */
+                               options.ciphers = xstrdup(optarg);
+                               options.cipher = SSH_CIPHER_INVALID;
+                       } else {
+                               /* SSH1 only */
+                               options.cipher = cipher_number(optarg);
+                               if (options.cipher == -1) {
+                                       fprintf(stderr,
+                                           "Unknown cipher type '%s'\n",
+                                           optarg);
+                                       exit(255);
+                               }
+                               if (options.cipher == SSH_CIPHER_3DES)
+                                       options.ciphers = "3des-cbc";
+                               else if (options.cipher == SSH_CIPHER_BLOWFISH)
+                                       options.ciphers = "blowfish-cbc";
+                               else
+                                       options.ciphers = (char *)-1;
+                       }
+                       break;
+               case 'm':
+                       if (mac_valid(optarg))
+                               options.macs = xstrdup(optarg);
+                       else {
+                               fprintf(stderr, "Unknown mac type '%s'\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'M':
+                       if (options.control_master == SSHCTL_MASTER_YES)
+                               options.control_master = SSHCTL_MASTER_ASK;
+                       else
+                               options.control_master = SSHCTL_MASTER_YES;
+                       break;
+               case 'p':
+                       options.port = a2port(optarg);
+                       if (options.port <= 0) {
+                               fprintf(stderr, "Bad port '%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'l':
+                       options.user = optarg;
+                       break;
+
+               case 'L':
+                       if (parse_forward(&fwd, optarg, 0, 0))
+                               add_local_forward(&options, &fwd);
+                       else {
+                               fprintf(stderr,
+                                   "Bad local forwarding specification '%s'\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       break;
+
+               case 'R':
+                       if (parse_forward(&fwd, optarg, 0, 1)) {
+                               add_remote_forward(&options, &fwd);
+                       } else {
+                               fprintf(stderr,
+                                   "Bad remote forwarding specification "
+                                   "'%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+
+               case 'D':
+                       if (parse_forward(&fwd, optarg, 1, 0)) {
+                               add_local_forward(&options, &fwd);
+                       } else {
+                               fprintf(stderr,
+                                   "Bad dynamic forwarding specification "
+                                   "'%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+
+               case 'C':
+                       options.compression = 1;
+                       break;
+               case 'N':
+                       no_shell_flag = 1;
+                       options.request_tty = REQUEST_TTY_NO;
+                       break;
+               case 'T':
+                       options.request_tty = REQUEST_TTY_NO;
+                       break;
+               case 'o':
+                       dummy = 1;
+                       line = xstrdup(optarg);
+                       if (process_config_line(&options, host ? host : "",
+                           line, "command-line", 0, &dummy) != 0)
+                               exit(255);
+                       xfree(line);
+                       break;
+               case 's':
+                       subsystem_flag = 1;
+                       break;
+               case 'S':
+                       if (options.control_path != NULL)
+                               free(options.control_path);
+                       options.control_path = xstrdup(optarg);
+                       break;
+               case 'b':
+                       options.bind_address = optarg;
+                       break;
+               case 'F':
+                       config = optarg;
+                       break;
+               default:
+                       usage();
+               }
+       }
+
+       ac -= optind;
+       av += optind;
+
+       if (ac > 0 && !host) {
+               if (strrchr(*av, '@')) {
+                       p = xstrdup(*av);
+                       cp = strrchr(p, '@');
+                       if (cp == NULL || cp == p)
+                               usage();
+                       options.user = p;
+                       *cp = '\0';
+                       host = ++cp;
+               } else
+                       host = *av;
+               if (ac > 1) {
+                       optind = optreset = 1;
+                       goto again;
+               }
+               ac--, av++;
+       }
+
+       /* Check that we got a host name. */
+       if (!host)
+               usage();
+
+       OpenSSL_add_all_algorithms();
+       ERR_load_crypto_strings();
+
+       /* Initialize the command to execute on remote host. */
+       buffer_init(&command);
+
+       if (options.request_tty == REQUEST_TTY_YES ||
+           options.request_tty == REQUEST_TTY_FORCE)
+               tty_flag = 1;
+
+       /*
+        * Save the command to execute on the remote host in a buffer. There
+        * is no limit on the length of the command, except by the maximum
+        * packet size.  Also sets the tty flag if there is no command.
+        */
+       if (!ac) {
+               /* No command specified - execute shell on a tty. */
+               tty_flag = options.request_tty != REQUEST_TTY_NO;
+               if (subsystem_flag) {
+                       fprintf(stderr,
+                           "You must specify a subsystem to invoke.\n");
+                       usage();
+               }
+       } else {
+               /* A command has been specified.  Store it into the buffer. */
+               for (i = 0; i < ac; i++) {
+                       if (i)
+                               buffer_append(&command, " ", 1);
+                       buffer_append(&command, av[i], strlen(av[i]));
+               }
+       }
+
+       /* Cannot fork to background if no command. */
+       if (fork_after_authentication_flag && buffer_len(&command) == 0 &&
+           !no_shell_flag)
+               fatal("Cannot fork into background without a command "
+                   "to execute.");
+
+       /* Allocate a tty by default if no command specified. */
+       if (buffer_len(&command) == 0)
+               tty_flag = options.request_tty != REQUEST_TTY_NO;
+
+       /* Force no tty */
+       if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0)
+               tty_flag = 0;
+       /* Do not allocate a tty if stdin is not a tty. */
+       if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
+           options.request_tty != REQUEST_TTY_FORCE) {
+               if (tty_flag)
+                       logit("Pseudo-terminal will not be allocated because "
+                           "stdin is not a terminal.");
+               tty_flag = 0;
+       }
+
+       /*
+        * Initialize "log" output.  Since we are the client all output
+        * actually goes to stderr.
+        */
+       log_init(argv0,
+           options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
+           SYSLOG_FACILITY_USER, !use_syslog);
+
+       /*
+        * Read per-user configuration file.  Ignore the system wide config
+        * file if the user specifies a config file on the command line.
+        */
+       if (config != NULL) {
+               if (!read_config_file(config, host, &options, 0))
+                       fatal("Can't open user config file %.100s: "
+                           "%.100s", config, strerror(errno));
+       } else {
+               r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
+                   _PATH_SSH_USER_CONFFILE);
+               if (r > 0 && (size_t)r < sizeof(buf))
+                       (void)read_config_file(buf, host, &options, 1);
+
+               /* Read systemwide configuration file after user config. */
+               (void)read_config_file(_PATH_HOST_CONFIG_FILE, host,
+                   &options, 0);
+       }
+
+       /* Fill configuration defaults. */
+       fill_default_options(&options);
+
+       channel_set_af(options.address_family);
+
+       /* reinit */
+       log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);
+
+       seed_rng();
+
+       if (options.user == NULL)
+               options.user = xstrdup(pw->pw_name);
+
+       /* Get default port if port has not been set. */
+       if (options.port == 0) {
+               sp = getservbyname(SSH_SERVICE_NAME, "tcp");
+               options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
+       }
+
+       /* preserve host name given on command line for %n expansion */
+       host_arg = host;
+       if (options.hostname != NULL) {
+               host = percent_expand(options.hostname,
+                   "h", host, (char *)NULL);
+       }
+
+       if (gethostname(thishost, sizeof(thishost)) == -1)
+               fatal("gethostname: %s", strerror(errno));
+       strlcpy(shorthost, thishost, sizeof(shorthost));
+       shorthost[strcspn(thishost, ".")] = '\0';
+       snprintf(portstr, sizeof(portstr), "%d", options.port);
+
+       if (options.local_command != NULL) {
+               debug3("expanding LocalCommand: %s", options.local_command);
+               cp = options.local_command;
+               options.local_command = percent_expand(cp, "d", pw->pw_dir,
+                   "h", host, "l", thishost, "n", host_arg, "r", options.user,
+                   "p", portstr, "u", pw->pw_name, "L", shorthost,
+                   (char *)NULL);
+               debug3("expanded LocalCommand: %s", options.local_command);
+               xfree(cp);
+       }
+
+       /* force lowercase for hostkey matching */
+       if (options.host_key_alias != NULL) {
+               for (p = options.host_key_alias; *p; p++)
+                       if (isupper(*p))
+                               *p = (char)tolower(*p);
+       }
+
+       if (options.proxy_command != NULL &&
+           strcmp(options.proxy_command, "none") == 0) {
+               xfree(options.proxy_command);
+               options.proxy_command = NULL;
+       }
+       if (options.control_path != NULL &&
+           strcmp(options.control_path, "none") == 0) {
+               xfree(options.control_path);
+               options.control_path = NULL;
+       }
+
+       if (options.control_path != NULL) {
+               cp = tilde_expand_filename(options.control_path,
+                   original_real_uid);
+               xfree(options.control_path);
+               options.control_path = percent_expand(cp, "h", host,
+                   "l", thishost, "n", host_arg, "r", options.user,
+                   "p", portstr, "u", pw->pw_name, "L", shorthost,
+                   (char *)NULL);
+               xfree(cp);
+       }
+       if (muxclient_command != 0 && options.control_path == NULL)
+               fatal("No ControlPath specified for \"-O\" command");
+       if (options.control_path != NULL)
+               muxclient(options.control_path);
+
+       timeout_ms = options.connection_timeout * 1000;
+
+       /* Open a connection to the remote host. */
+       if (ssh_connect(host, &hostaddr, options.port,
+           options.address_family, options.connection_attempts, &timeout_ms,
+           options.tcp_keep_alive, 
+#ifdef HAVE_CYGWIN
+           options.use_privileged_port,
+#else
+           original_effective_uid == 0 && options.use_privileged_port,
+#endif
+           options.proxy_command) != 0)
+               exit(255);
+
+       if (timeout_ms > 0)
+               debug3("timeout: %d ms remain after connect", timeout_ms);
+
+       /*
+        * If we successfully made the connection, load the host private key
+        * in case we will need it later for combined rsa-rhosts
+        * authentication. This must be done before releasing extra
+        * privileges, because the file is only readable by root.
+        * If we cannot access the private keys, load the public keys
+        * instead and try to execute the ssh-keysign helper instead.
+        */
+       sensitive_data.nkeys = 0;
+       sensitive_data.keys = NULL;
+       sensitive_data.external_keysign = 0;
+       if (options.rhosts_rsa_authentication ||
+           options.hostbased_authentication) {
+               sensitive_data.nkeys = 7;
+               sensitive_data.keys = xcalloc(sensitive_data.nkeys,
+                   sizeof(Key));
+               for (i = 0; i < sensitive_data.nkeys; i++)
+                       sensitive_data.keys[i] = NULL;
+
+               PRIV_START;
+               sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
+                   _PATH_HOST_KEY_FILE, "", NULL, NULL);
+               sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
+                   _PATH_HOST_DSA_KEY_FILE, "", NULL);
+#ifdef OPENSSL_HAS_ECC
+               sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA,
+                   _PATH_HOST_ECDSA_KEY_FILE, "", NULL);
+#endif
+               sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
+                   _PATH_HOST_RSA_KEY_FILE, "", NULL);
+               sensitive_data.keys[4] = key_load_private_type(KEY_DSA,
+                   _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
+#ifdef OPENSSL_HAS_ECC
+               sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
+                   _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
+#endif
+               sensitive_data.keys[6] = key_load_private_type(KEY_RSA,
+                   _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
+               PRIV_END;
+
+               if (options.hostbased_authentication == 1 &&
+                   sensitive_data.keys[0] == NULL &&
+                   sensitive_data.keys[4] == NULL &&
+                   sensitive_data.keys[5] == NULL &&
+                   sensitive_data.keys[6] == NULL) {
+                       sensitive_data.keys[1] = key_load_cert(
+                           _PATH_HOST_DSA_KEY_FILE);
+#ifdef OPENSSL_HAS_ECC
+                       sensitive_data.keys[2] = key_load_cert(
+                           _PATH_HOST_ECDSA_KEY_FILE);
+#endif
+                       sensitive_data.keys[3] = key_load_cert(
+                           _PATH_HOST_RSA_KEY_FILE);
+                       sensitive_data.keys[4] = key_load_public(
+                           _PATH_HOST_DSA_KEY_FILE, NULL);
+#ifdef OPENSSL_HAS_ECC
+                       sensitive_data.keys[5] = key_load_public(
+                           _PATH_HOST_ECDSA_KEY_FILE, NULL);
+#endif
+                       sensitive_data.keys[6] = key_load_public(
+                           _PATH_HOST_RSA_KEY_FILE, NULL);
+                       sensitive_data.external_keysign = 1;
+               }
+       }
+       /*
+        * Get rid of any extra privileges that we may have.  We will no
+        * longer need them.  Also, extra privileges could make it very hard
+        * to read identity files and other non-world-readable files from the
+        * user's home directory if it happens to be on a NFS volume where
+        * root is mapped to nobody.
+        */
+       if (original_effective_uid == 0) {
+               PRIV_START;
+               permanently_set_uid(pw);
+       }
+
+       /*
+        * Now that we are back to our own permissions, create ~/.ssh
+        * directory if it doesn't already exist.
+        */
+       r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
+           strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
+       if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) {
+#ifdef WITH_SELINUX
+               ssh_selinux_setfscreatecon(buf);
+#endif
+               if (mkdir(buf, 0700) < 0)
+                       error("Could not create directory '%.200s'.", buf);
+#ifdef WITH_SELINUX
+               ssh_selinux_setfscreatecon(NULL);
+#endif
+       }
+       /* load options.identity_files */
+       load_public_identity_files();
+
+       /* Expand ~ in known host file names. */
+       tilde_expand_paths(options.system_hostfiles,
+           options.num_system_hostfiles);
+       tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
+
+       signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
+       signal(SIGCHLD, main_sigchld_handler);
+
+       /* Log into the remote system.  Never returns if the login fails. */
+       ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
+           options.port, pw, timeout_ms);
+
+       if (packet_connection_is_on_socket()) {
+               verbose("Authenticated to %s ([%s]:%d).", host,
+                   get_remote_ipaddr(), get_remote_port());
+       } else {
+               verbose("Authenticated to %s (via proxy).", host);
+       }
+
+       /* We no longer need the private host keys.  Clear them now. */
+       if (sensitive_data.nkeys != 0) {
+               for (i = 0; i < sensitive_data.nkeys; i++) {
+                       if (sensitive_data.keys[i] != NULL) {
+                               /* Destroys contents safely */
+                               debug3("clear hostkey %d", i);
+                               key_free(sensitive_data.keys[i]);
+                               sensitive_data.keys[i] = NULL;
+                       }
+               }
+               xfree(sensitive_data.keys);
+       }
+       for (i = 0; i < options.num_identity_files; i++) {
+               if (options.identity_files[i]) {
+                       xfree(options.identity_files[i]);
+                       options.identity_files[i] = NULL;
+               }
+               if (options.identity_keys[i]) {
+                       key_free(options.identity_keys[i]);
+                       options.identity_keys[i] = NULL;
+               }
+       }
+
+       exit_status = compat20 ? ssh_session2() : ssh_session();
+       packet_close();
+
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+
+       /* Kill ProxyCommand if it is running. */
+       ssh_kill_proxy_command();
+
+       return exit_status;
+}
+
+static void
+control_persist_detach(void)
+{
+       pid_t pid;
+       int devnull;
+
+       debug("%s: backgrounding master process", __func__);
+
+       /*
+        * master (current process) into the background, and make the
+        * foreground process a client of the backgrounded master.
+        */
+       switch ((pid = fork())) {
+       case -1:
+               fatal("%s: fork: %s", __func__, strerror(errno));
+       case 0:
+               /* Child: master process continues mainloop */
+               break;
+       default:
+               /* Parent: set up mux slave to connect to backgrounded master */
+               debug2("%s: background process is %ld", __func__, (long)pid);
+               stdin_null_flag = ostdin_null_flag;
+               options.request_tty = orequest_tty;
+               tty_flag = otty_flag;
+               close(muxserver_sock);
+               muxserver_sock = -1;
+               options.control_master = SSHCTL_MASTER_NO;
+               muxclient(options.control_path);
+               /* muxclient() doesn't return on success. */
+               fatal("Failed to connect to new control master");
+       }
+       if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+               error("%s: open(\"/dev/null\"): %s", __func__,
+                   strerror(errno));
+       } else {
+               if (dup2(devnull, STDIN_FILENO) == -1 ||
+                   dup2(devnull, STDOUT_FILENO) == -1)
+                       error("%s: dup2: %s", __func__, strerror(errno));
+               if (devnull > STDERR_FILENO)
+                       close(devnull);
+       }
+       setproctitle("%s [mux]", options.control_path);
+}
+
+/* Do fork() after authentication. Used by "ssh -f" */
+static void
+fork_postauth(void)
+{
+       if (need_controlpersist_detach)
+               control_persist_detach();
+       debug("forking to background");
+       fork_after_authentication_flag = 0;
+       if (daemon(1, 1) < 0)
+               fatal("daemon() failed: %.200s", strerror(errno));
+}
+
+/* Callback for remote forward global requests */
+static void
+ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
+{
+       Forward *rfwd = (Forward *)ctxt;
+
+       /* XXX verbose() on failure? */
+       debug("remote forward %s for: listen %d, connect %s:%d",
+           type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
+           rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
+       if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) {
+               rfwd->allocated_port = packet_get_int();
+               logit("Allocated port %u for remote forward to %s:%d",
+                   rfwd->allocated_port,
+                   rfwd->connect_host, rfwd->connect_port);
+       }
+       
+       if (type == SSH2_MSG_REQUEST_FAILURE) {
+               if (options.exit_on_forward_failure)
+                       fatal("Error: remote port forwarding failed for "
+                           "listen port %d", rfwd->listen_port);
+               else
+                       logit("Warning: remote port forwarding failed for "
+                           "listen port %d", rfwd->listen_port);
+       }
+       if (++remote_forward_confirms_received == options.num_remote_forwards) {
+               debug("All remote forwarding requests processed");
+               if (fork_after_authentication_flag)
+                       fork_postauth();
+       }
+}
+
+static void
+client_cleanup_stdio_fwd(int id, void *arg)
+{
+       debug("stdio forwarding: done");
+       cleanup_exit(0);
+}
+
+static int
+client_setup_stdio_fwd(const char *host_to_connect, u_short port_to_connect)
+{
+       Channel *c;
+       int in, out;
+
+       debug3("client_setup_stdio_fwd %s:%d", host_to_connect,
+           port_to_connect);
+
+       in = dup(STDIN_FILENO);
+       out = dup(STDOUT_FILENO);
+       if (in < 0 || out < 0)
+               fatal("channel_connect_stdio_fwd: dup() in/out failed");
+
+       if ((c = channel_connect_stdio_fwd(host_to_connect, port_to_connect,
+           in, out)) == NULL)
+               return 0;
+       channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
+       return 1;
+}
+
+static void
+ssh_init_forwarding(void)
+{
+       int success = 0;
+       int i;
+
+       if (stdio_forward_host != NULL) {
+               if (!compat20) {
+                       fatal("stdio forwarding require Protocol 2");
+               }
+               if (!client_setup_stdio_fwd(stdio_forward_host,
+                   stdio_forward_port))
+                       fatal("Failed to connect in stdio forward mode.");
+       }
+
+       /* Initiate local TCP/IP port forwardings. */
+       for (i = 0; i < options.num_local_forwards; i++) {
+               debug("Local connections to %.200s:%d forwarded to remote "
+                   "address %.200s:%d",
+                   (options.local_forwards[i].listen_host == NULL) ?
+                   (options.gateway_ports ? "*" : "LOCALHOST") :
+                   options.local_forwards[i].listen_host,
+                   options.local_forwards[i].listen_port,
+                   options.local_forwards[i].connect_host,
+                   options.local_forwards[i].connect_port);
+               success += channel_setup_local_fwd_listener(
+                   options.local_forwards[i].listen_host,
+                   options.local_forwards[i].listen_port,
+                   options.local_forwards[i].connect_host,
+                   options.local_forwards[i].connect_port,
+                   options.gateway_ports);
+       }
+       if (i > 0 && success != i && options.exit_on_forward_failure)
+               fatal("Could not request local forwarding.");
+       if (i > 0 && success == 0)
+               error("Could not request local forwarding.");
+
+       /* Initiate remote TCP/IP port forwardings. */
+       for (i = 0; i < options.num_remote_forwards; i++) {
+               debug("Remote connections from %.200s:%d forwarded to "
+                   "local address %.200s:%d",
+                   (options.remote_forwards[i].listen_host == NULL) ?
+                   "LOCALHOST" : options.remote_forwards[i].listen_host,
+                   options.remote_forwards[i].listen_port,
+                   options.remote_forwards[i].connect_host,
+                   options.remote_forwards[i].connect_port);
+               if (channel_request_remote_forwarding(
+                   options.remote_forwards[i].listen_host,
+                   options.remote_forwards[i].listen_port,
+                   options.remote_forwards[i].connect_host,
+                   options.remote_forwards[i].connect_port) < 0) {
+                       if (options.exit_on_forward_failure)
+                               fatal("Could not request remote forwarding.");
+                       else
+                               logit("Warning: Could not request remote "
+                                   "forwarding.");
+               }
+               client_register_global_confirm(ssh_confirm_remote_forward,
+                   &options.remote_forwards[i]);
+       }
+
+       /* Initiate tunnel forwarding. */
+       if (options.tun_open != SSH_TUNMODE_NO) {
+               if (client_request_tun_fwd(options.tun_open,
+                   options.tun_local, options.tun_remote) == -1) {
+                       if (options.exit_on_forward_failure)
+                               fatal("Could not request tunnel forwarding.");
+                       else
+                               error("Could not request tunnel forwarding.");
+               }
+       }                       
+}
+
+static void
+check_agent_present(void)
+{
+       if (options.forward_agent) {
+               /* Clear agent forwarding if we don't have an agent. */
+               if (!ssh_agent_present())
+                       options.forward_agent = 0;
+       }
+}
+
+static int
+ssh_session(void)
+{
+       int type;
+       int interactive = 0;
+       int have_tty = 0;
+       struct winsize ws;
+       char *cp;
+       const char *display;
+
+       /* Enable compression if requested. */
+       if (options.compression) {
+               debug("Requesting compression at level %d.",
+                   options.compression_level);
+
+               if (options.compression_level < 1 ||
+                   options.compression_level > 9)
+                       fatal("Compression level must be from 1 (fast) to "
+                           "9 (slow, best).");
+
+               /* Send the request. */
+               packet_start(SSH_CMSG_REQUEST_COMPRESSION);
+               packet_put_int(options.compression_level);
+               packet_send();
+               packet_write_wait();
+               type = packet_read();
+               if (type == SSH_SMSG_SUCCESS)
+                       packet_start_compression(options.compression_level);
+               else if (type == SSH_SMSG_FAILURE)
+                       logit("Warning: Remote host refused compression.");
+               else
+                       packet_disconnect("Protocol error waiting for "
+                           "compression response.");
+       }
+       /* Allocate a pseudo tty if appropriate. */
+       if (tty_flag) {
+               debug("Requesting pty.");
+
+               /* Start the packet. */
+               packet_start(SSH_CMSG_REQUEST_PTY);
+
+               /* Store TERM in the packet.  There is no limit on the
+                  length of the string. */
+               cp = getenv("TERM");
+               if (!cp)
+                       cp = "";
+               packet_put_cstring(cp);
+
+               /* Store window size in the packet. */
+               if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
+                       memset(&ws, 0, sizeof(ws));
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+
+               /* Store tty modes in the packet. */
+               tty_make_modes(fileno(stdin), NULL);
+
+               /* Send the packet, and wait for it to leave. */
+               packet_send();
+               packet_write_wait();
+
+               /* Read response from the server. */
+               type = packet_read();
+               if (type == SSH_SMSG_SUCCESS) {
+                       interactive = 1;
+                       have_tty = 1;
+               } else if (type == SSH_SMSG_FAILURE)
+                       logit("Warning: Remote host failed or refused to "
+                           "allocate a pseudo tty.");
+               else
+                       packet_disconnect("Protocol error waiting for pty "
+                           "request response.");
+       }
+       /* Request X11 forwarding if enabled and DISPLAY is set. */
+       display = getenv("DISPLAY");
+       if (options.forward_x11 && display != NULL) {
+               char *proto, *data;
+               /* Get reasonable local authentication information. */
+               client_x11_get_proto(display, options.xauth_location,
+                   options.forward_x11_trusted, 
+                   options.forward_x11_timeout,
+                   &proto, &data);
+               /* Request forwarding with authentication spoofing. */
+               debug("Requesting X11 forwarding with authentication "
+                   "spoofing.");
+               x11_request_forwarding_with_spoofing(0, display, proto,
+                   data, 0);
+               /* Read response from the server. */
+               type = packet_read();
+               if (type == SSH_SMSG_SUCCESS) {
+                       interactive = 1;
+               } else if (type == SSH_SMSG_FAILURE) {
+                       logit("Warning: Remote host denied X11 forwarding.");
+               } else {
+                       packet_disconnect("Protocol error waiting for X11 "
+                           "forwarding");
+               }
+       }
+       /* Tell the packet module whether this is an interactive session. */
+       packet_set_interactive(interactive,
+           options.ip_qos_interactive, options.ip_qos_bulk);
+
+       /* Request authentication agent forwarding if appropriate. */
+       check_agent_present();
+
+       if (options.forward_agent) {
+               debug("Requesting authentication agent forwarding.");
+               auth_request_forwarding();
+
+               /* Read response from the server. */
+               type = packet_read();
+               packet_check_eom();
+               if (type != SSH_SMSG_SUCCESS)
+                       logit("Warning: Remote host denied authentication agent forwarding.");
+       }
+
+       /* Initiate port forwardings. */
+       ssh_init_forwarding();
+
+       /* Execute a local command */
+       if (options.local_command != NULL &&
+           options.permit_local_command)
+               ssh_local_cmd(options.local_command);
+
+       /*
+        * If requested and we are not interested in replies to remote
+        * forwarding requests, then let ssh continue in the background.
+        */
+       if (fork_after_authentication_flag) {
+               if (options.exit_on_forward_failure &&
+                   options.num_remote_forwards > 0) {
+                       debug("deferring postauth fork until remote forward "
+                           "confirmation received");
+               } else
+                       fork_postauth();
+       }
+
+       /*
+        * If a command was specified on the command line, execute the
+        * command now. Otherwise request the server to start a shell.
+        */
+       if (buffer_len(&command) > 0) {
+               int len = buffer_len(&command);
+               if (len > 900)
+                       len = 900;
+               debug("Sending command: %.*s", len,
+                   (u_char *)buffer_ptr(&command));
+               packet_start(SSH_CMSG_EXEC_CMD);
+               packet_put_string(buffer_ptr(&command), buffer_len(&command));
+               packet_send();
+               packet_write_wait();
+       } else {
+               debug("Requesting shell.");
+               packet_start(SSH_CMSG_EXEC_SHELL);
+               packet_send();
+               packet_write_wait();
+       }
+
+       /* Enter the interactive session. */
+       return client_loop(have_tty, tty_flag ?
+           options.escape_char : SSH_ESCAPECHAR_NONE, 0);
+}
+
+/* request pty/x11/agent/tcpfwd/shell for channel */
+static void
+ssh_session2_setup(int id, int success, void *arg)
+{
+       extern char **environ;
+       const char *display;
+       int interactive = tty_flag;
+
+       if (!success)
+               return; /* No need for error message, channels code sens one */
+
+       display = getenv("DISPLAY");
+       if (options.forward_x11 && display != NULL) {
+               char *proto, *data;
+               /* Get reasonable local authentication information. */
+               client_x11_get_proto(display, options.xauth_location,
+                   options.forward_x11_trusted,
+                   options.forward_x11_timeout, &proto, &data);
+               /* Request forwarding with authentication spoofing. */
+               debug("Requesting X11 forwarding with authentication "
+                   "spoofing.");
+               x11_request_forwarding_with_spoofing(id, display, proto,
+                   data, 1);
+               client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
+               /* XXX exit_on_forward_failure */
+               interactive = 1;
+       }
+
+       check_agent_present();
+       if (options.forward_agent) {
+               debug("Requesting authentication agent forwarding.");
+               channel_request_start(id, "auth-agent-req@openssh.com", 0);
+               packet_send();
+       }
+
+       client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
+           NULL, fileno(stdin), &command, environ);
+}
+
+/* open new channel for a session */
+static int
+ssh_session2_open(void)
+{
+       Channel *c;
+       int window, packetmax, in, out, err;
+
+       if (stdin_null_flag) {
+               in = open(_PATH_DEVNULL, O_RDONLY);
+       } else {
+               in = dup(STDIN_FILENO);
+       }
+       out = dup(STDOUT_FILENO);
+       err = dup(STDERR_FILENO);
+
+       if (in < 0 || out < 0 || err < 0)
+               fatal("dup() in/out/err failed");
+
+       /* enable nonblocking unless tty */
+       if (!isatty(in))
+               set_nonblock(in);
+       if (!isatty(out))
+               set_nonblock(out);
+       if (!isatty(err))
+               set_nonblock(err);
+
+       window = CHAN_SES_WINDOW_DEFAULT;
+       packetmax = CHAN_SES_PACKET_DEFAULT;
+       if (tty_flag) {
+               window >>= 1;
+               packetmax >>= 1;
+       }
+       c = channel_new(
+           "session", SSH_CHANNEL_OPENING, in, out, err,
+           window, packetmax, CHAN_EXTENDED_WRITE,
+           "client-session", /*nonblock*/0);
+
+       debug3("ssh_session2_open: channel_new: %d", c->self);
+
+       channel_send_open(c->self);
+       if (!no_shell_flag)
+               channel_register_open_confirm(c->self,
+                   ssh_session2_setup, NULL);
+
+       return c->self;
+}
+
+static int
+ssh_session2(void)
+{
+       int id = -1;
+
+       /* XXX should be pre-session */
+       ssh_init_forwarding();
+
+       /* Start listening for multiplex clients */
+       muxserver_listen();
+
+       /*
+        * If we are in control persist mode, then prepare to background
+        * ourselves and have a foreground client attach as a control
+        * slave. NB. we must save copies of the flags that we override for
+        * the backgrounding, since we defer attachment of the slave until
+        * after the connection is fully established (in particular,
+        * async rfwd replies have been received for ExitOnForwardFailure).
+        */
+       if (options.control_persist && muxserver_sock != -1) {
+               ostdin_null_flag = stdin_null_flag;
+               ono_shell_flag = no_shell_flag;
+               orequest_tty = options.request_tty;
+               otty_flag = tty_flag;
+               stdin_null_flag = 1;
+               no_shell_flag = 1;
+               tty_flag = 0;
+               if (!fork_after_authentication_flag)
+                       need_controlpersist_detach = 1;
+               fork_after_authentication_flag = 1;
+       }
+
+       if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
+               id = ssh_session2_open();
+
+       /* If we don't expect to open a new session, then disallow it */
+       if (options.control_master == SSHCTL_MASTER_NO &&
+           (datafellows & SSH_NEW_OPENSSH)) {
+               debug("Requesting no-more-sessions@openssh.com");
+               packet_start(SSH2_MSG_GLOBAL_REQUEST);
+               packet_put_cstring("no-more-sessions@openssh.com");
+               packet_put_char(0);
+               packet_send();
+       }
+
+       /* Execute a local command */
+       if (options.local_command != NULL &&
+           options.permit_local_command)
+               ssh_local_cmd(options.local_command);
+
+       /*
+        * If requested and we are not interested in replies to remote
+        * forwarding requests, then let ssh continue in the background.
+        */
+       if (fork_after_authentication_flag) {
+               if (options.exit_on_forward_failure &&
+                   options.num_remote_forwards > 0) {
+                       debug("deferring postauth fork until remote forward "
+                           "confirmation received");
+               } else
+                       fork_postauth();
+       }
+
+       if (options.use_roaming)
+               request_roaming();
+
+       return client_loop(tty_flag, tty_flag ?
+           options.escape_char : SSH_ESCAPECHAR_NONE, id);
+}
+
+static void
+load_public_identity_files(void)
+{
+       char *filename, *cp, thishost[NI_MAXHOST];
+       char *pwdir = NULL, *pwname = NULL;
+       int i = 0;
+       Key *public;
+       struct passwd *pw;
+       u_int n_ids;
+       char *identity_files[SSH_MAX_IDENTITY_FILES];
+       Key *identity_keys[SSH_MAX_IDENTITY_FILES];
+#ifdef ENABLE_PKCS11
+       Key **keys;
+       int nkeys;
+#endif /* PKCS11 */
+
+       n_ids = 0;
+       bzero(identity_files, sizeof(identity_files));
+       bzero(identity_keys, sizeof(identity_keys));
+
+#ifdef ENABLE_PKCS11
+       if (options.pkcs11_provider != NULL &&
+           options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
+           (pkcs11_init(!options.batch_mode) == 0) &&
+           (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
+           &keys)) > 0) {
+               for (i = 0; i < nkeys; i++) {
+                       if (n_ids >= SSH_MAX_IDENTITY_FILES) {
+                               key_free(keys[i]);
+                               continue;
+                       }
+                       identity_keys[n_ids] = keys[i];
+                       identity_files[n_ids] =
+                           xstrdup(options.pkcs11_provider); /* XXX */
+                       n_ids++;
+               }
+               xfree(keys);
+       }
+#endif /* ENABLE_PKCS11 */
+       if ((pw = getpwuid(original_real_uid)) == NULL)
+               fatal("load_public_identity_files: getpwuid failed");
+       pwname = xstrdup(pw->pw_name);
+       pwdir = xstrdup(pw->pw_dir);
+       if (gethostname(thishost, sizeof(thishost)) == -1)
+               fatal("load_public_identity_files: gethostname: %s",
+                   strerror(errno));
+       for (i = 0; i < options.num_identity_files; i++) {
+               if (n_ids >= SSH_MAX_IDENTITY_FILES) {
+                       xfree(options.identity_files[i]);
+                       continue;
+               }
+               cp = tilde_expand_filename(options.identity_files[i],
+                   original_real_uid);
+               filename = percent_expand(cp, "d", pwdir,
+                   "u", pwname, "l", thishost, "h", host,
+                   "r", options.user, (char *)NULL);
+               xfree(cp);
+               public = key_load_public(filename, NULL);
+               debug("identity file %s type %d", filename,
+                   public ? public->type : -1);
+               xfree(options.identity_files[i]);
+               identity_files[n_ids] = filename;
+               identity_keys[n_ids] = public;
+
+               if (++n_ids >= SSH_MAX_IDENTITY_FILES)
+                       continue;
+
+               /* Try to add the certificate variant too */
+               xasprintf(&cp, "%s-cert", filename);
+               public = key_load_public(cp, NULL);
+               debug("identity file %s type %d", cp,
+                   public ? public->type : -1);
+               if (public == NULL) {
+                       xfree(cp);
+                       continue;
+               }
+               if (!key_is_cert(public)) {
+                       debug("%s: key %s type %s is not a certificate",
+                           __func__, cp, key_type(public));
+                       key_free(public);
+                       xfree(cp);
+                       continue;
+               }
+               identity_keys[n_ids] = public;
+               /* point to the original path, most likely the private key */
+               identity_files[n_ids] = xstrdup(filename);
+               n_ids++;
+       }
+       options.num_identity_files = n_ids;
+       memcpy(options.identity_files, identity_files, sizeof(identity_files));
+       memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
+
+       bzero(pwname, strlen(pwname));
+       xfree(pwname);
+       bzero(pwdir, strlen(pwdir));
+       xfree(pwdir);
+}
+
+static void
+main_sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+           (pid < 0 && errno == EINTR))
+               ;
+
+       signal(sig, main_sigchld_handler);
+       errno = save_errno;
+}
+
diff --git a/.pc/ssh-vulnkey.patch/ssh_config.5 b/.pc/ssh-vulnkey.patch/ssh_config.5
new file mode 100644 (file)
index 0000000..9e1e9a6
--- /dev/null
@@ -0,0 +1,1326 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Nm ~/.ssh/config
+.Nm /etc/ssh/ssh_config
+.Sh DESCRIPTION
+.Xr ssh 1
+obtains configuration data from the following sources in
+the following order:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+command-line options
+.It
+user's configuration file
+.Pq Pa ~/.ssh/config
+.It
+system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+.El
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections separated by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp ,
+and
+.Nm sftp
+.Fl o
+option.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+If more than one pattern is provided, they should be separated by whitespace.
+A single
+.Ql *
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e. the name is not converted to
+a canonicalized host name before matching).
+.Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm AddressFamily
+Specifies which address family to use when connecting.
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Use the specified address on the local machine as the source address of
+the connection.
+Only useful on systems with more than one address.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge-response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Xr ssh 1
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote, and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared.
+This option is primarily useful when used from the
+.Xr ssh 1
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout (in seconds) used when connecting to the
+SSH server, instead of using the default system TCP timeout.
+This value is used only when the target is down or really unreachable,
+not when it refuses the connection.
+.It Cm ControlMaster
+Enables the sharing of multiple sessions over a single network connection.
+When set to
+.Dq yes ,
+.Xr ssh 1
+will listen for connections on a control socket specified using the
+.Cm ControlPath
+argument.
+Additional sessions can connect to this socket using the same
+.Cm ControlPath
+with
+.Cm ControlMaster
+set to
+.Dq no
+(the default).
+These sessions will try to reuse the master instance's network connection
+rather than initiating new ones, but will fall back to connecting normally
+if the control socket does not exist, or is not listening.
+.Pp
+Setting this to
+.Dq ask
+will cause ssh
+to listen for control connections, but require confirmation using the
+.Ev SSH_ASKPASS
+program before they are accepted (see
+.Xr ssh-add 1
+for details).
+If the
+.Cm ControlPath
+cannot be opened,
+ssh will continue without connecting to a master instance.
+.Pp
+X11 and
+.Xr ssh-agent 1
+forwarding is supported over these multiplexed connections, however the
+display and agent forwarded will be the one belonging to the master
+connection i.e. it is not possible to forward multiple displays or agents.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
+.It Cm ControlPath
+Specify the path to the control socket used for connection sharing as described
+in the
+.Cm ControlMaster
+section above or the string
+.Dq none
+to disable connection sharing.
+In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
+.Ql %l
+will be substituted by the local host name (including any domain name),
+.Ql %h
+will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
+.Ql %p
+the port,
+.Ql %r
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+at least %h, %p, and %r.
+This ensures that shared connections are uniquely identified.
+.It Cm ControlPersist
+When used in conjunction with
+.Cm ControlMaster ,
+specifies that the master connection should remain open
+in the background (waiting for future client connections)
+after the initial client connection has been closed.
+If set to
+.Dq no ,
+then the master connection will not be placed into the background,
+and will close as soon as the initial client connection is closed.
+If set to
+.Dq yes ,
+then the master connection will remain in the background indefinitely
+(until killed or closed via a mechanism such as the
+.Xr ssh 1
+.Dq Fl O No exit
+option).
+If set to a time in seconds, or a time in any of the formats documented in
+.Xr sshd_config 5 ,
+then the backgrounded master connection will automatically terminate
+after it has remained idle (with no client connections) for the
+specified time.
+.It Cm DynamicForward
+Specifies that a TCP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+.Pp
+The argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port .
+.Sm on
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.Pp
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Xr ssh 1
+will act as a SOCKS server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm EnableSSHKeysign
+Setting this option to
+.Dq yes
+in the global client configuration file
+.Pa /etc/ssh/ssh_config
+enables the use of the helper program
+.Xr ssh-keysign 8
+during
+.Cm HostbasedAuthentication .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option should be placed in the non-hostspecific section.
+See
+.Xr ssh-keysign 8
+for more information.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ExitOnForwardFailure
+Specifies whether
+.Xr ssh 1
+should terminate the connection if it cannot set up all requested
+dynamic, tunnel, local, and remote port forwardings.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's Unix-domain socket)
+can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X11 authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring
+if the
+.Cm ForwardX11Trusted
+option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
+.It Cm ForwardX11Trusted
+If this option is set to
+.Dq yes ,
+remote X11 clients will have full access to the original X11 display.
+.Pp
+If this option is set to
+.Dq no ,
+remote X11 clients will be considered untrusted and prevented
+from stealing or tampering with data belonging to trusted X11
+clients.
+Furthermore, the
+.Xr xauth 1
+token used for the session will be set to expire after 20 minutes.
+Remote clients will be refused access after this time.
+.Pp
+The default is
+.Dq no .
+.Pp
+See the X11 SECURITY extension specification for full details on
+the restrictions imposed on untrusted clients.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Xr ssh 1
+binds local port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
+.It Cm GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when 
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
+.It Cm GSSAPIDelegateCredentials
+Forward (delegate) credentials to the server.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI.
+.It Cm HashKnownHosts
+Indicates that
+.Xr ssh 1
+should hash host names and addresses when they are added to
+.Pa ~/.ssh/known_hosts .
+These hashed names may be used normally by
+.Xr ssh 1
+and
+.Xr sshd 8 ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+The default is
+.Dq no .
+Note that existing names and addresses in known hosts files
+will not be converted automatically,
+but may be manually hashed using
+.Xr ssh-keygen 1 .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
+ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-rsa,ssh-dss
+.Ed
+.Pp
+If hostkeys are known for the destination host then this default is modified
+to prefer their algorithms.
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling SSH connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+If the hostname contains the character sequence
+.Ql %h ,
+then this will be replaced with the host name specified on the command line
+(this is useful for manipulating unqualified names).
+The default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentitiesOnly
+Specifies that
+.Xr ssh 1
+should only use the authentication identity files configured in the
+.Nm
+files,
+even if
+.Xr ssh-agent 1
+offers more identities.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option is intended for situations where ssh-agent
+offers many different identities.
+The default is
+.Dq no .
+.It Cm IdentityFile
+Specifies a file from which the user's DSA, ECDSA or DSA authentication
+identity is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+.Xr ssh 1
+will try to load certificate information from the filename obtained by
+appending
+.Pa -cert.pub
+to the path of a specified
+.Cm IdentityFile .
+.Pp
+The file name may use the tilde
+syntax to refer to a user's home directory or one of the following
+escape characters:
+.Ql %d
+(local user's home directory),
+.Ql %u
+(local user name),
+.Ql %l
+(local host name),
+.Ql %h
+(remote host name) or
+.Ql %r
+(remote user name).
+.Pp
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KbdInteractiveAuthentication
+Specifies whether to use keyboard-interactive authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm KbdInteractiveDevices
+Specifies the list of methods to use in keyboard-interactive authentication.
+Multiple method names must be comma-separated.
+The default is to use the server specified list.
+The methods available vary depending on what the server supports.
+For an OpenSSH server,
+it may be zero or more of:
+.Dq bsdauth ,
+.Dq pam ,
+and
+.Dq skey .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
+diffie-hellman-group-exchange-sha256,
+diffie-hellman-group-exchange-sha1,
+diffie-hellman-group14-sha1,
+diffie-hellman-group1-sha1
+.Ed
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+The following escape character substitutions will be performed:
+.Ql %d
+(local user's home directory),
+.Ql %h
+(remote host name),
+.Ql %l
+(local host name),
+.Ql %n
+(host name as provided on the command line),
+.Ql %p
+(remote port),
+.Ql %r
+(remote user name) or
+.Ql %u
+(local user name).
+.Pp
+The command is run synchronously and does not have access to the
+session of the
+.Xr ssh 1
+that spawned it.
+It should not be used for interactive commands.
+.Pp
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
+.It Cm LocalForward
+Specifies that a TCP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional forwardings can be
+given on the command line.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr ssh 1 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+The default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic !\& Ns Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm PKCS11Provider
+Specifies which PKCS#11 provider to use.
+The argument to this keyword is the PKCS#11 shared library
+.Xr ssh 1
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Cm Port
+Specifies the port number to connect on the remote host.
+The default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods.
+This allows a client to prefer one method (e.g.\&
+.Cm keyboard-interactive )
+over another method (e.g.\&
+.Cm password ) .
+The default is:
+.Bd -literal -offset indent
+gssapi-with-mic,hostbased,publickey,
+keyboard-interactive,password
+.Ed
+.It Cm Protocol
+Specifies the protocol versions
+.Xr ssh 1
+should support in order of preference.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+When this option is set to
+.Dq 2,1
+.Nm ssh
+will try version 2 and fall back to version 1
+if version 2 is not available.
+The default is
+.Sq 2 .
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+the user's shell.
+In the command string, any occurrence of
+.Ql %h
+will be substituted by the host name to
+connect,
+.Ql %p
+by the port, and
+.Ql %r
+by the remote user name.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Setting the command to
+.Dq none
+disables this option entirely.
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+This directive is useful in conjunction with
+.Xr nc 1
+and its proxy support.
+For example, the following directive would connect via an HTTP proxy at
+192.0.2.0:
+.Bd -literal -offset 3n
+ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
+.Ed
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RekeyLimit
+Specifies the maximum amount of data that may be transmitted before the
+session key is renegotiated.
+The argument is the number of bytes, with an optional suffix of
+.Sq K ,
+.Sq M ,
+or
+.Sq G
+to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
+The default is between
+.Sq 1G
+and
+.Sq 4G ,
+depending on the cipher.
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+.Pp
+If the
+.Ar bind_address
+is not specified, the default is to only bind to loopback addresses.
+If the
+.Ar bind_address
+is
+.Ql *
+or an empty string, then the forwarding is requested to listen on all
+interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Xr ssh 1
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SendEnv
+Specifies what variables from the local
+.Xr environ 7
+should be sent to the server.
+Note that environment passing is only supported for protocol 2.
+The server must also support it, and the server must be configured to
+accept these environment variables.
+Refer to
+.Cm AcceptEnv
+in
+.Xr sshd_config 5
+for how to configure the server.
+Variables are specified by name, which may contain wildcard characters.
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm SendEnv
+directives.
+The default is not to send any environment variables.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm ServerAliveCountMax
+Sets the number of server alive messages (see below) which may be
+sent without
+.Xr ssh 1
+receiving any messages back from the server.
+If this threshold is reached while server alive messages are being sent,
+ssh will disconnect from the server, terminating the session.
+It is important to note that the use of server alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The server alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The server alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If, for example,
+.Cm ServerAliveInterval
+(see below) is set to 15 and
+.Cm ServerAliveCountMax
+is left at the default, if the server becomes unresponsive,
+ssh will disconnect after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ServerAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the server,
+.Xr ssh 1
+will send a message through the encrypted
+channel to request a response from the server.
+The default
+is 0, indicating that these messages will not be sent to the server.
+This option applies to protocol version 2 only.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will never automatically add host keys to the
+.Pa ~/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+though it can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained or when connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+ssh will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+ssh will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm Tunnel
+Request
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2),
+or
+.Dq no .
+Specifying
+.Dq yes
+requests the default tunnel mode, which is
+.Dq point-to-point .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Specifies the
+.Xr tun 4
+devices to open on the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The argument must be
+.Sm off
+.Ar local_tun Op : Ar remote_tun .
+.Sm on
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+The default is
+.Dq any:any .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+If set to
+.Dq yes ,
+.Xr ssh 1
+must be setuid root.
+Note that this option must be set to
+.Dq yes
+for
+.Cm RhostsRSAAuthentication
+with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
+.It Cm VerifyHostKeyDNS
+Specifies whether to verify the remote key using DNS and SSHFP resource
+records.
+If this option is set to
+.Dq yes ,
+the client will implicitly trust keys that match a secure fingerprint
+from DNS.
+Insecure fingerprints will be handled as if this option was set to
+.Dq ask .
+If this option is set to
+.Dq ask ,
+information on fingerprint match will be displayed, but the user will still
+need to confirm new host keys according to the
+.Cm StrictHostKeyChecking
+option.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.Pp
+See also
+.Sx VERIFYING HOST KEYS
+in
+.Xr ssh 1 .
+.It Cm VisualHostKey
+If this flag is set to
+.Dq yes ,
+an ASCII art representation of the remote host key fingerprint is
+printed in addition to the hex fingerprint string at login and
+for unknown host keys.
+If this flag is set to
+.Dq no ,
+no fingerprint strings are printed at login and
+only the hex fingerprint string will be printed for unknown host keys.
+The default is
+.Dq no .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh PATTERNS
+A
+.Em pattern
+consists of zero or more non-whitespace characters,
+.Sq *
+(a wildcard that matches zero or more characters),
+or
+.Sq ?\&
+(a wildcard that matches exactly one character).
+For example, to specify a set of declarations for any host in the
+.Dq .co.uk
+set of domains,
+the following pattern could be used:
+.Pp
+.Dl Host *.co.uk
+.Pp
+The following pattern
+would match any host in the 192.168.0.[0-9] network range:
+.Pp
+.Dl Host 192.168.0.?
+.Pp
+A
+.Em pattern-list
+is a comma-separated list of patterns.
+Patterns within pattern-lists may be negated
+by preceding them with an exclamation mark
+.Pq Sq !\& .
+For example,
+to allow a key to be used from anywhere within an organisation
+except from the
+.Dq dialup
+pool,
+the following entry (in authorized_keys) could be used:
+.Pp
+.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the SSH client.
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh SEE ALSO
+.Xr ssh 1
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/ssh-vulnkey.patch/sshconnect2.c b/.pc/ssh-vulnkey.patch/sshconnect2.c
new file mode 100644 (file)
index 0000000..3ddef32
--- /dev/null
@@ -0,0 +1,2036 @@
+/* $OpenBSD: sshconnect2.c,v 1.188 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2008 Damien Miller.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
+#include <vis.h>
+#endif
+
+#include "openbsd-compat/sys-queue.h"
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh2.h"
+#include "buffer.h"
+#include "packet.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "myproposal.h"
+#include "sshconnect.h"
+#include "authfile.h"
+#include "dh.h"
+#include "authfd.h"
+#include "log.h"
+#include "readconf.h"
+#include "misc.h"
+#include "match.h"
+#include "dispatch.h"
+#include "canohost.h"
+#include "msg.h"
+#include "pathnames.h"
+#include "uidswap.h"
+#include "hostfile.h"
+#include "schnorr.h"
+#include "jpake.h"
+
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
+/* import */
+extern char *client_version_string;
+extern char *server_version_string;
+extern Options options;
+
+/*
+ * SSH2 key exchange
+ */
+
+u_char *session_id2 = NULL;
+u_int session_id2_len = 0;
+
+char *xxx_host;
+struct sockaddr *xxx_hostaddr;
+
+Kex *xxx_kex = NULL;
+
+static int
+verify_host_key_callback(Key *hostkey)
+{
+       if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
+               fatal("Host key verification failed.");
+       return 0;
+}
+
+static char *
+order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
+{
+       char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
+       size_t maxlen;
+       struct hostkeys *hostkeys;
+       int ktype;
+       u_int i;
+
+       /* Find all hostkeys for this hostname */
+       get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL);
+       hostkeys = init_hostkeys();
+       for (i = 0; i < options.num_user_hostfiles; i++)
+               load_hostkeys(hostkeys, hostname, options.user_hostfiles[i]);
+       for (i = 0; i < options.num_system_hostfiles; i++)
+               load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
+
+       oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
+       maxlen = strlen(avail) + 1;
+       first = xmalloc(maxlen);
+       last = xmalloc(maxlen);
+       *first = *last = '\0';
+
+#define ALG_APPEND(to, from) \
+       do { \
+               if (*to != '\0') \
+                       strlcat(to, ",", maxlen); \
+               strlcat(to, from, maxlen); \
+       } while (0)
+
+       while ((alg = strsep(&avail, ",")) && *alg != '\0') {
+               if ((ktype = key_type_from_name(alg)) == KEY_UNSPEC)
+                       fatal("%s: unknown alg %s", __func__, alg);
+               if (lookup_key_in_hostkeys_by_type(hostkeys,
+                   key_type_plain(ktype), NULL))
+                       ALG_APPEND(first, alg);
+               else
+                       ALG_APPEND(last, alg);
+       }
+#undef ALG_APPEND
+       xasprintf(&ret, "%s%s%s", first, *first == '\0' ? "" : ",", last);
+       if (*first != '\0')
+               debug3("%s: prefer hostkeyalgs: %s", __func__, first);
+
+       xfree(first);
+       xfree(last);
+       xfree(hostname);
+       xfree(oavail);
+       free_hostkeys(hostkeys);
+
+       return ret;
+}
+
+void
+ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
+{
+       Kex *kex;
+
+#ifdef GSSAPI
+       char *orig = NULL, *gss = NULL;
+       char *gss_host = NULL;
+#endif
+
+       xxx_host = host;
+       xxx_hostaddr = hostaddr;
+
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               /* Add the GSSAPI mechanisms currently supported on this 
+                * client to the key exchange algorithm proposal */
+               orig = myproposal[PROPOSAL_KEX_ALGS];
+
+               if (options.gss_trust_dns)
+                       gss_host = (char *)get_canonical_hostname(1);
+               else
+                       gss_host = host;
+
+               gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
+               if (gss) {
+                       debug("Offering GSSAPI proposal: %s", gss);
+                       xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
+                           "%s,%s", gss, orig);
+               }
+       }
+#endif
+
+       if (options.ciphers == (char *)-1) {
+               logit("No valid ciphers for protocol version 2 given, using defaults.");
+               options.ciphers = NULL;
+       }
+       if (options.ciphers != NULL) {
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       myproposal[PROPOSAL_ENC_ALGS_STOC] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
+       if (options.compression) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none";
+       } else {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib";
+       }
+       if (options.macs != NULL) {
+               myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+               myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+       }
+       if (options.hostkeyalgorithms != NULL)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
+                   options.hostkeyalgorithms;
+       else {
+               /* Prefer algorithms that we already have keys for */
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
+                   order_hostkeyalgs(host, hostaddr, port);
+       }
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+
+#ifdef GSSAPI
+       /* If we've got GSSAPI algorithms, then we also support the
+        * 'null' hostkey, as a last resort */
+       if (options.gss_keyex && gss) {
+               orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+               xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 
+                   "%s,null", orig);
+               xfree(gss);
+       }
+#endif
+
+       if (options.rekey_limit)
+               packet_set_rekey_limit((u_int32_t)options.rekey_limit);
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
+       }
+#endif
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->verify_host_key=&verify_host_key_callback;
+
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->gss_deleg_creds = options.gss_deleg_creds;
+               kex->gss_trust_dns = options.gss_trust_dns;
+               kex->gss_client = options.gss_client_identity;
+               if (options.gss_server_identity) {
+                       kex->gss_host = options.gss_server_identity;
+               } else {
+                       kex->gss_host = gss_host;
+        }
+       }
+#endif
+
+       xxx_kex = kex;
+
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+
+       if (options.use_roaming && !kex->roaming) {
+               debug("Roaming not allowed by server");
+               options.use_roaming = 0;
+       }
+
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
+
+#ifdef DEBUG_KEXDH
+       /* send 1st encrypted/maced/compressed message */
+       packet_start(SSH2_MSG_IGNORE);
+       packet_put_cstring("markus");
+       packet_send();
+       packet_write_wait();
+#endif
+}
+
+/*
+ * Authenticate user
+ */
+
+typedef struct Authctxt Authctxt;
+typedef struct Authmethod Authmethod;
+typedef struct identity Identity;
+typedef struct idlist Idlist;
+
+struct identity {
+       TAILQ_ENTRY(identity) next;
+       AuthenticationConnection *ac;   /* set if agent supports key */
+       Key     *key;                   /* public/private key */
+       char    *filename;              /* comment for agent-only keys */
+       int     tried;
+       int     isprivate;              /* key points to the private key */
+};
+TAILQ_HEAD(idlist, identity);
+
+struct Authctxt {
+       const char *server_user;
+       const char *local_user;
+       const char *host;
+       const char *service;
+       Authmethod *method;
+       sig_atomic_t success;
+       char *authlist;
+       /* pubkey */
+       Idlist keys;
+       AuthenticationConnection *agent;
+       /* hostbased */
+       Sensitive *sensitive;
+       /* kbd-interactive */
+       int info_req_seen;
+       /* generic */
+       void *methoddata;
+};
+struct Authmethod {
+       char    *name;          /* string to compare against server's list */
+       int     (*userauth)(Authctxt *authctxt);
+       void    (*cleanup)(Authctxt *authctxt);
+       int     *enabled;       /* flag in option struct that enables method */
+       int     *batch_flag;    /* flag in option struct that disables method */
+};
+
+void   input_userauth_success(int, u_int32_t, void *);
+void   input_userauth_success_unexpected(int, u_int32_t, void *);
+void   input_userauth_failure(int, u_int32_t, void *);
+void   input_userauth_banner(int, u_int32_t, void *);
+void   input_userauth_error(int, u_int32_t, void *);
+void   input_userauth_info_req(int, u_int32_t, void *);
+void   input_userauth_pk_ok(int, u_int32_t, void *);
+void   input_userauth_passwd_changereq(int, u_int32_t, void *);
+void   input_userauth_jpake_server_step1(int, u_int32_t, void *);
+void   input_userauth_jpake_server_step2(int, u_int32_t, void *);
+void   input_userauth_jpake_server_confirm(int, u_int32_t, void *);
+
+int    userauth_none(Authctxt *);
+int    userauth_pubkey(Authctxt *);
+int    userauth_passwd(Authctxt *);
+int    userauth_kbdint(Authctxt *);
+int    userauth_hostbased(Authctxt *);
+int    userauth_jpake(Authctxt *);
+
+void   userauth_jpake_cleanup(Authctxt *);
+
+#ifdef GSSAPI
+int    userauth_gssapi(Authctxt *authctxt);
+void   input_gssapi_response(int type, u_int32_t, void *);
+void   input_gssapi_token(int type, u_int32_t, void *);
+void   input_gssapi_hash(int type, u_int32_t, void *);
+void   input_gssapi_error(int, u_int32_t, void *);
+void   input_gssapi_errtok(int, u_int32_t, void *);
+int    userauth_gsskeyex(Authctxt *authctxt);
+#endif
+
+void   userauth(Authctxt *, char *);
+
+static int sign_and_send_pubkey(Authctxt *, Identity *);
+static void pubkey_prepare(Authctxt *);
+static void pubkey_cleanup(Authctxt *);
+static Key *load_identity_file(char *);
+
+static Authmethod *authmethod_get(char *authlist);
+static Authmethod *authmethod_lookup(const char *name);
+static char *authmethods_get(void);
+
+Authmethod authmethods[] = {
+#ifdef GSSAPI
+       {"gssapi-keyex",
+               userauth_gsskeyex,
+               NULL,
+               &options.gss_authentication,
+               NULL},
+       {"gssapi-with-mic",
+               userauth_gssapi,
+               NULL,
+               &options.gss_authentication,
+               NULL},
+#endif
+       {"hostbased",
+               userauth_hostbased,
+               NULL,
+               &options.hostbased_authentication,
+               NULL},
+       {"publickey",
+               userauth_pubkey,
+               NULL,
+               &options.pubkey_authentication,
+               NULL},
+#ifdef JPAKE
+       {"jpake-01@openssh.com",
+               userauth_jpake,
+               userauth_jpake_cleanup,
+               &options.zero_knowledge_password_authentication,
+               &options.batch_mode},
+#endif
+       {"keyboard-interactive",
+               userauth_kbdint,
+               NULL,
+               &options.kbd_interactive_authentication,
+               &options.batch_mode},
+       {"password",
+               userauth_passwd,
+               NULL,
+               &options.password_authentication,
+               &options.batch_mode},
+       {"none",
+               userauth_none,
+               NULL,
+               NULL,
+               NULL},
+       {NULL, NULL, NULL, NULL, NULL}
+};
+
+void
+ssh_userauth2(const char *local_user, const char *server_user, char *host,
+    Sensitive *sensitive)
+{
+       Authctxt authctxt;
+       int type;
+
+       if (options.challenge_response_authentication)
+               options.kbd_interactive_authentication = 1;
+
+       packet_start(SSH2_MSG_SERVICE_REQUEST);
+       packet_put_cstring("ssh-userauth");
+       packet_send();
+       debug("SSH2_MSG_SERVICE_REQUEST sent");
+       packet_write_wait();
+       type = packet_read();
+       if (type != SSH2_MSG_SERVICE_ACCEPT)
+               fatal("Server denied authentication request: %d", type);
+       if (packet_remaining() > 0) {
+               char *reply = packet_get_string(NULL);
+               debug2("service_accept: %s", reply);
+               xfree(reply);
+       } else {
+               debug2("buggy server: service_accept w/o service");
+       }
+       packet_check_eom();
+       debug("SSH2_MSG_SERVICE_ACCEPT received");
+
+       if (options.preferred_authentications == NULL)
+               options.preferred_authentications = authmethods_get();
+
+       /* setup authentication context */
+       memset(&authctxt, 0, sizeof(authctxt));
+       pubkey_prepare(&authctxt);
+       authctxt.server_user = server_user;
+       authctxt.local_user = local_user;
+       authctxt.host = host;
+       authctxt.service = "ssh-connection";            /* service name */
+       authctxt.success = 0;
+       authctxt.method = authmethod_lookup("none");
+       authctxt.authlist = NULL;
+       authctxt.methoddata = NULL;
+       authctxt.sensitive = sensitive;
+       authctxt.info_req_seen = 0;
+       if (authctxt.method == NULL)
+               fatal("ssh_userauth2: internal error: cannot send userauth none request");
+
+       /* initial userauth request */
+       userauth_none(&authctxt);
+
+       dispatch_init(&input_userauth_error);
+       dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
+       dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
+       dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
+       dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt);     /* loop until success */
+
+       pubkey_cleanup(&authctxt);
+       dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
+
+       debug("Authentication succeeded (%s).", authctxt.method->name);
+}
+
+void
+userauth(Authctxt *authctxt, char *authlist)
+{
+       if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
+               authctxt->method->cleanup(authctxt);
+
+       if (authctxt->methoddata) {
+               xfree(authctxt->methoddata);
+               authctxt->methoddata = NULL;
+       }
+       if (authlist == NULL) {
+               authlist = authctxt->authlist;
+       } else {
+               if (authctxt->authlist)
+                       xfree(authctxt->authlist);
+               authctxt->authlist = authlist;
+       }
+       for (;;) {
+               Authmethod *method = authmethod_get(authlist);
+               if (method == NULL)
+                       fatal("Permission denied (%s).", authlist);
+               authctxt->method = method;
+
+               /* reset the per method handler */
+               dispatch_range(SSH2_MSG_USERAUTH_PER_METHOD_MIN,
+                   SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL);
+
+               /* and try new method */
+               if (method->userauth(authctxt) != 0) {
+                       debug2("we sent a %s packet, wait for reply", method->name);
+                       break;
+               } else {
+                       debug2("we did not send a packet, disable method");
+                       method->enabled = NULL;
+               }
+       }
+}
+
+/* ARGSUSED */
+void
+input_userauth_error(int type, u_int32_t seq, void *ctxt)
+{
+       fatal("input_userauth_error: bad message during authentication: "
+           "type %d", type);
+}
+
+/* ARGSUSED */
+void
+input_userauth_banner(int type, u_int32_t seq, void *ctxt)
+{
+       char *msg, *raw, *lang;
+       u_int len;
+
+       debug3("input_userauth_banner");
+       raw = packet_get_string(&len);
+       lang = packet_get_string(NULL);
+       if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) {
+               if (len > 65536)
+                       len = 65536;
+               msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */
+               strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL|VIS_NOSLASH);
+               fprintf(stderr, "%s", msg);
+               xfree(msg);
+       }
+       xfree(raw);
+       xfree(lang);
+}
+
+/* ARGSUSED */
+void
+input_userauth_success(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_success: no authentication context");
+       if (authctxt->authlist) {
+               xfree(authctxt->authlist);
+               authctxt->authlist = NULL;
+       }
+       if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
+               authctxt->method->cleanup(authctxt);
+       if (authctxt->methoddata) {
+               xfree(authctxt->methoddata);
+               authctxt->methoddata = NULL;
+       }
+       authctxt->success = 1;                  /* break out */
+}
+
+void
+input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+
+       if (authctxt == NULL)
+               fatal("%s: no authentication context", __func__);
+
+       fatal("Unexpected authentication success during %s.",
+           authctxt->method->name);
+}
+
+/* ARGSUSED */
+void
+input_userauth_failure(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       char *authlist = NULL;
+       int partial;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_failure: no authentication context");
+
+       authlist = packet_get_string(NULL);
+       partial = packet_get_char();
+       packet_check_eom();
+
+       if (partial != 0)
+               logit("Authenticated with partial success.");
+       debug("Authentications that can continue: %s", authlist);
+
+       userauth(authctxt, authlist);
+}
+
+/* ARGSUSED */
+void
+input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Key *key = NULL;
+       Identity *id = NULL;
+       Buffer b;
+       int pktype, sent = 0;
+       u_int alen, blen;
+       char *pkalg, *fp;
+       u_char *pkblob;
+
+       if (authctxt == NULL)
+               fatal("input_userauth_pk_ok: no authentication context");
+       if (datafellows & SSH_BUG_PKOK) {
+               /* this is similar to SSH_BUG_PKAUTH */
+               debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
+               pkblob = packet_get_string(&blen);
+               buffer_init(&b);
+               buffer_append(&b, pkblob, blen);
+               pkalg = buffer_get_string(&b, &alen);
+               buffer_free(&b);
+       } else {
+               pkalg = packet_get_string(&alen);
+               pkblob = packet_get_string(&blen);
+       }
+       packet_check_eom();
+
+       debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
+
+       if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
+               debug("unknown pkalg %s", pkalg);
+               goto done;
+       }
+       if ((key = key_from_blob(pkblob, blen)) == NULL) {
+               debug("no key from blob. pkalg %s", pkalg);
+               goto done;
+       }
+       if (key->type != pktype) {
+               error("input_userauth_pk_ok: type mismatch "
+                   "for decoded key (received %d, expected %d)",
+                   key->type, pktype);
+               goto done;
+       }
+       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+       debug2("input_userauth_pk_ok: fp %s", fp);
+       xfree(fp);
+
+       /*
+        * search keys in the reverse order, because last candidate has been
+        * moved to the end of the queue.  this also avoids confusion by
+        * duplicate keys
+        */
+       TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) {
+               if (key_equal(key, id->key)) {
+                       sent = sign_and_send_pubkey(authctxt, id);
+                       break;
+               }
+       }
+done:
+       if (key != NULL)
+               key_free(key);
+       xfree(pkalg);
+       xfree(pkblob);
+
+       /* try another method if we did not send a packet */
+       if (sent == 0)
+               userauth(authctxt, NULL);
+}
+
+#ifdef GSSAPI
+int
+userauth_gssapi(Authctxt *authctxt)
+{
+       Gssctxt *gssctxt = NULL;
+       static gss_OID_set gss_supported = NULL;
+       static u_int mech = 0;
+       OM_uint32 min;
+       int ok = 0;
+       const char *gss_host;
+
+       if (options.gss_server_identity)
+               gss_host = options.gss_server_identity;
+       else if (options.gss_trust_dns)
+               gss_host = get_canonical_hostname(1);
+       else
+               gss_host = authctxt->host;
+
+       /* Try one GSSAPI method at a time, rather than sending them all at
+        * once. */
+
+       if (gss_supported == NULL)
+               if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
+                       gss_supported = NULL;
+                       return 0;
+               }
+
+       /* Check to see if the mechanism is usable before we offer it */
+       while (mech < gss_supported->count && !ok) {
+               /* My DER encoding requires length<128 */
+               if (gss_supported->elements[mech].length < 128 &&
+                   ssh_gssapi_check_mechanism(&gssctxt, 
+                   &gss_supported->elements[mech], gss_host, 
+                    options.gss_client_identity)) {
+                       ok = 1; /* Mechanism works */
+               } else {
+                       mech++;
+               }
+       }
+
+       if (!ok)
+               return 0;
+
+       authctxt->methoddata=(void *)gssctxt;
+
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+
+       packet_put_int(1);
+
+       packet_put_int((gss_supported->elements[mech].length) + 2);
+       packet_put_char(SSH_GSS_OIDTYPE);
+       packet_put_char(gss_supported->elements[mech].length);
+       packet_put_raw(gss_supported->elements[mech].elements,
+           gss_supported->elements[mech].length);
+
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
+
+       mech++; /* Move along to next candidate */
+
+       return 1;
+}
+
+static OM_uint32
+process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt = authctxt->methoddata;
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc gssbuf;
+       OM_uint32 status, ms, flags;
+       Buffer b;
+
+       status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+           recv_tok, &send_tok, &flags);
+
+       if (send_tok.length > 0) {
+               if (GSS_ERROR(status))
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+               else
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+
+               packet_put_string(send_tok.value, send_tok.length);
+               packet_send();
+               gss_release_buffer(&ms, &send_tok);
+       }
+
+       if (status == GSS_S_COMPLETE) {
+               /* send either complete or MIC, depending on mechanism */
+               if (!(flags & GSS_C_INTEG_FLAG)) {
+                       packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
+                       packet_send();
+               } else {
+                       ssh_gssapi_buildmic(&b, authctxt->server_user,
+                           authctxt->service, "gssapi-with-mic");
+
+                       gssbuf.value = buffer_ptr(&b);
+                       gssbuf.length = buffer_len(&b);
+
+                       status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
+
+                       if (!GSS_ERROR(status)) {
+                               packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC);
+                               packet_put_string(mic.value, mic.length);
+
+                               packet_send();
+                       }
+
+                       buffer_free(&b);
+                       gss_release_buffer(&ms, &mic);
+               }
+       }
+
+       return status;
+}
+
+/* ARGSUSED */
+void
+input_gssapi_response(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       u_int oidlen;
+       u_char *oidv;
+
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+       gssctxt = authctxt->methoddata;
+
+       /* Setup our OID */
+       oidv = packet_get_string(&oidlen);
+
+       if (oidlen <= 2 ||
+           oidv[0] != SSH_GSS_OIDTYPE ||
+           oidv[1] != oidlen - 2) {
+               xfree(oidv);
+               debug("Badly encoded mechanism OID received");
+               userauth(authctxt, NULL);
+               return;
+       }
+
+       if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2))
+               fatal("Server returned different OID than expected");
+
+       packet_check_eom();
+
+       xfree(oidv);
+
+       if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
+               /* Start again with next method on list */
+               debug("Trying to start again");
+               userauth(authctxt, NULL);
+               return;
+       }
+}
+
+/* ARGSUSED */
+void
+input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       gss_buffer_desc recv_tok;
+       OM_uint32 status;
+       u_int slen;
+
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+
+       recv_tok.value = packet_get_string(&slen);
+       recv_tok.length = slen; /* safe typecast */
+
+       packet_check_eom();
+
+       status = process_gssapi_token(ctxt, &recv_tok);
+
+       xfree(recv_tok.value);
+
+       if (GSS_ERROR(status)) {
+               /* Start again with the next method in the list */
+               userauth(authctxt, NULL);
+               return;
+       }
+}
+
+/* ARGSUSED */
+void
+input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc recv_tok;
+       OM_uint32 status, ms;
+       u_int len;
+
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+       gssctxt = authctxt->methoddata;
+
+       recv_tok.value = packet_get_string(&len);
+       recv_tok.length = len;
+
+       packet_check_eom();
+
+       /* Stick it into GSSAPI and see what it says */
+       status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+           &recv_tok, &send_tok, NULL);
+
+       xfree(recv_tok.value);
+       gss_release_buffer(&ms, &send_tok);
+
+       /* Server will be returning a failed packet after this one */
+}
+
+/* ARGSUSED */
+void
+input_gssapi_error(int type, u_int32_t plen, void *ctxt)
+{
+       OM_uint32 maj, min;
+       char *msg;
+       char *lang;
+
+       maj=packet_get_int();
+       min=packet_get_int();
+       msg=packet_get_string(NULL);
+       lang=packet_get_string(NULL);
+
+       packet_check_eom();
+
+       debug("Server GSSAPI Error:\n%s", msg);
+       xfree(msg);
+       xfree(lang);
+}
+
+int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+       Buffer b;
+       gss_buffer_desc gssbuf;
+       gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
+       OM_uint32 ms;
+
+       static int attempt = 0;
+       if (attempt++ >= 1)
+               return (0);
+
+       if (gss_kex_context == NULL) {
+               debug("No valid Key exchange context"); 
+               return (0);
+       }
+
+       ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
+           "gssapi-keyex");
+
+       gssbuf.value = buffer_ptr(&b);
+       gssbuf.length = buffer_len(&b);
+
+       if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
+               buffer_free(&b);
+               return (0);
+       }
+
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_string(mic.value, mic.length);
+       packet_send();
+
+       buffer_free(&b);
+       gss_release_buffer(&ms, &mic);
+
+       return (1);
+}
+
+#endif /* GSSAPI */
+
+int
+userauth_none(Authctxt *authctxt)
+{
+       /* initial userauth request */
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_send();
+       return 1;
+}
+
+int
+userauth_passwd(Authctxt *authctxt)
+{
+       static int attempt = 0;
+       char prompt[150];
+       char *password;
+       const char *host = options.host_key_alias ?  options.host_key_alias :
+           authctxt->host;
+
+       if (attempt++ >= options.number_of_password_prompts)
+               return 0;
+
+       if (attempt != 1)
+               error("Permission denied, please try again.");
+
+       snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
+           authctxt->server_user, host);
+       password = read_passphrase(prompt, 0);
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_char(0);
+       packet_put_cstring(password);
+       memset(password, 0, strlen(password));
+       xfree(password);
+       packet_add_padding(64);
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+           &input_userauth_passwd_changereq);
+
+       return 1;
+}
+
+/*
+ * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
+ */
+/* ARGSUSED */
+void
+input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       char *info, *lang, *password = NULL, *retype = NULL;
+       char prompt[150];
+       const char *host = options.host_key_alias ? options.host_key_alias :
+           authctxt->host;
+
+       debug2("input_userauth_passwd_changereq");
+
+       if (authctxt == NULL)
+               fatal("input_userauth_passwd_changereq: "
+                   "no authentication context");
+
+       info = packet_get_string(NULL);
+       lang = packet_get_string(NULL);
+       if (strlen(info) > 0)
+               logit("%s", info);
+       xfree(info);
+       xfree(lang);
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_char(1);                     /* additional info */
+       snprintf(prompt, sizeof(prompt),
+           "Enter %.30s@%.128s's old password: ",
+           authctxt->server_user, host);
+       password = read_passphrase(prompt, 0);
+       packet_put_cstring(password);
+       memset(password, 0, strlen(password));
+       xfree(password);
+       password = NULL;
+       while (password == NULL) {
+               snprintf(prompt, sizeof(prompt),
+                   "Enter %.30s@%.128s's new password: ",
+                   authctxt->server_user, host);
+               password = read_passphrase(prompt, RP_ALLOW_EOF);
+               if (password == NULL) {
+                       /* bail out */
+                       return;
+               }
+               snprintf(prompt, sizeof(prompt),
+                   "Retype %.30s@%.128s's new password: ",
+                   authctxt->server_user, host);
+               retype = read_passphrase(prompt, 0);
+               if (strcmp(password, retype) != 0) {
+                       memset(password, 0, strlen(password));
+                       xfree(password);
+                       logit("Mismatch; try again, EOF to quit.");
+                       password = NULL;
+               }
+               memset(retype, 0, strlen(retype));
+               xfree(retype);
+       }
+       packet_put_cstring(password);
+       memset(password, 0, strlen(password));
+       xfree(password);
+       packet_add_padding(64);
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
+           &input_userauth_passwd_changereq);
+}
+
+#ifdef JPAKE
+static char *
+pw_encrypt(const char *password, const char *crypt_scheme, const char *salt)
+{
+       /* OpenBSD crypt(3) handles all of these */
+       if (strcmp(crypt_scheme, "crypt") == 0 ||
+           strcmp(crypt_scheme, "bcrypt") == 0 ||
+           strcmp(crypt_scheme, "md5crypt") == 0 ||
+           strcmp(crypt_scheme, "crypt-extended") == 0)
+               return xstrdup(crypt(password, salt));
+       error("%s: unsupported password encryption scheme \"%.100s\"",
+           __func__, crypt_scheme);
+       return NULL;
+}
+
+static BIGNUM *
+jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme,
+    const char *salt)
+{
+       char prompt[256], *password, *crypted;
+       u_char *secret;
+       u_int secret_len;
+       BIGNUM *ret;
+
+       snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ",
+           authctxt->server_user, authctxt->host);
+       password = read_passphrase(prompt, 0);
+
+       if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) {
+               logit("Disabling %s authentication", authctxt->method->name);
+               authctxt->method->enabled = NULL;
+               /* Continue with an empty password to fail gracefully */
+               crypted = xstrdup("");
+       }
+
+#ifdef JPAKE_DEBUG
+       debug3("%s: salt = %s", __func__, salt);
+       debug3("%s: scheme = %s", __func__, crypt_scheme);
+       debug3("%s: crypted = %s", __func__, crypted);
+#endif
+
+       if (hash_buffer(crypted, strlen(crypted), EVP_sha256(),
+           &secret, &secret_len) != 0)
+               fatal("%s: hash_buffer", __func__);
+
+       bzero(password, strlen(password));
+       bzero(crypted, strlen(crypted));
+       xfree(password);
+       xfree(crypted);
+
+       if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL)
+               fatal("%s: BN_bin2bn (secret)", __func__);
+       bzero(secret, secret_len);
+       xfree(secret);
+
+       return ret;
+}
+
+/* ARGSUSED */
+void
+input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       struct jpake_ctx *pctx = authctxt->methoddata;
+       u_char *x3_proof, *x4_proof, *x2_s_proof;
+       u_int x3_proof_len, x4_proof_len, x2_s_proof_len;
+       char *crypt_scheme, *salt;
+
+       /* Disable this message */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL);
+
+       if ((pctx->g_x3 = BN_new()) == NULL ||
+           (pctx->g_x4 = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       /* Fetch step 1 values */
+       crypt_scheme = packet_get_string(NULL);
+       salt = packet_get_string(NULL);
+       pctx->server_id = packet_get_string(&pctx->server_id_len);
+       packet_get_bignum2(pctx->g_x3);
+       packet_get_bignum2(pctx->g_x4);
+       x3_proof = packet_get_string(&x3_proof_len);
+       x4_proof = packet_get_string(&x4_proof_len);
+       packet_check_eom();
+
+       JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
+
+       /* Obtain password and derive secret */
+       pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt);
+       bzero(crypt_scheme, strlen(crypt_scheme));
+       bzero(salt, strlen(salt));
+       xfree(crypt_scheme);
+       xfree(salt);
+       JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__));
+
+       /* Calculate step 2 values */
+       jpake_step2(pctx->grp, pctx->s, pctx->g_x1,
+           pctx->g_x3, pctx->g_x4, pctx->x2,
+           pctx->server_id, pctx->server_id_len,
+           pctx->client_id, pctx->client_id_len,
+           x3_proof, x3_proof_len,
+           x4_proof, x4_proof_len,
+           &pctx->a,
+           &x2_s_proof, &x2_s_proof_len);
+
+       bzero(x3_proof, x3_proof_len);
+       bzero(x4_proof, x4_proof_len);
+       xfree(x3_proof);
+       xfree(x4_proof);
+
+       JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
+
+       /* Send values for step 2 */
+       packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2);
+       packet_put_bignum2(pctx->a);
+       packet_put_string(x2_s_proof, x2_s_proof_len);
+       packet_send();
+
+       bzero(x2_s_proof, x2_s_proof_len);
+       xfree(x2_s_proof);
+
+       /* Expect step 2 packet from peer */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2,
+           input_userauth_jpake_server_step2);
+}
+
+/* ARGSUSED */
+void
+input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       struct jpake_ctx *pctx = authctxt->methoddata;
+       u_char *x4_s_proof;
+       u_int x4_s_proof_len;
+
+       /* Disable this message */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL);
+
+       if ((pctx->b = BN_new()) == NULL)
+               fatal("%s: BN_new", __func__);
+
+       /* Fetch step 2 values */
+       packet_get_bignum2(pctx->b);
+       x4_s_proof = packet_get_string(&x4_s_proof_len);
+       packet_check_eom();
+
+       JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
+
+       /* Derive shared key and calculate confirmation hash */
+       jpake_key_confirm(pctx->grp, pctx->s, pctx->b,
+           pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4,
+           pctx->client_id, pctx->client_id_len,
+           pctx->server_id, pctx->server_id_len,
+           session_id2, session_id2_len,
+           x4_s_proof, x4_s_proof_len,
+           &pctx->k,
+           &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len);
+
+       bzero(x4_s_proof, x4_s_proof_len);
+       xfree(x4_s_proof);
+
+       JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
+
+       /* Send key confirmation proof */
+       packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM);
+       packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
+       packet_send();
+
+       /* Expect confirmation from peer */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM,
+           input_userauth_jpake_server_confirm);
+}
+
+/* ARGSUSED */
+void
+input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       struct jpake_ctx *pctx = authctxt->methoddata;
+
+       /* Disable this message */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL);
+
+       pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len);
+       packet_check_eom();
+
+       JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
+
+       /* Verify expected confirmation hash */
+       if (jpake_check_confirm(pctx->k,
+           pctx->server_id, pctx->server_id_len,
+           session_id2, session_id2_len,
+           pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1)
+               debug("%s: %s success", __func__, authctxt->method->name);
+       else {
+               debug("%s: confirmation mismatch", __func__);
+               /* XXX stash this so if auth succeeds then we can warn/kill */
+       }
+
+       userauth_jpake_cleanup(authctxt);
+}
+#endif /* JPAKE */
+
+static int
+identity_sign(Identity *id, u_char **sigp, u_int *lenp,
+    u_char *data, u_int datalen)
+{
+       Key *prv;
+       int ret;
+
+       /* the agent supports this key */
+       if (id->ac)
+               return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
+                   data, datalen));
+       /*
+        * we have already loaded the private key or
+        * the private key is stored in external hardware
+        */
+       if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
+               return (key_sign(id->key, sigp, lenp, data, datalen));
+       /* load the private key from the file */
+       if ((prv = load_identity_file(id->filename)) == NULL)
+               return (-1);
+       ret = key_sign(prv, sigp, lenp, data, datalen);
+       key_free(prv);
+       return (ret);
+}
+
+static int
+sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
+{
+       Buffer b;
+       u_char *blob, *signature;
+       u_int bloblen, slen;
+       u_int skip = 0;
+       int ret = -1;
+       int have_sig = 1;
+       char *fp;
+
+       fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+       debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
+       xfree(fp);
+
+       if (key_to_blob(id->key, &blob, &bloblen) == 0) {
+               /* we cannot handle this key */
+               debug3("sign_and_send_pubkey: cannot handle key");
+               return 0;
+       }
+       /* data to be signed */
+       buffer_init(&b);
+       if (datafellows & SSH_OLD_SESSIONID) {
+               buffer_append(&b, session_id2, session_id2_len);
+               skip = session_id2_len;
+       } else {
+               buffer_put_string(&b, session_id2, session_id2_len);
+               skip = buffer_len(&b);
+       }
+       buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+       buffer_put_cstring(&b, authctxt->server_user);
+       buffer_put_cstring(&b,
+           datafellows & SSH_BUG_PKSERVICE ?
+           "ssh-userauth" :
+           authctxt->service);
+       if (datafellows & SSH_BUG_PKAUTH) {
+               buffer_put_char(&b, have_sig);
+       } else {
+               buffer_put_cstring(&b, authctxt->method->name);
+               buffer_put_char(&b, have_sig);
+               buffer_put_cstring(&b, key_ssh_name(id->key));
+       }
+       buffer_put_string(&b, blob, bloblen);
+
+       /* generate signature */
+       ret = identity_sign(id, &signature, &slen,
+           buffer_ptr(&b), buffer_len(&b));
+       if (ret == -1) {
+               xfree(blob);
+               buffer_free(&b);
+               return 0;
+       }
+#ifdef DEBUG_PK
+       buffer_dump(&b);
+#endif
+       if (datafellows & SSH_BUG_PKSERVICE) {
+               buffer_clear(&b);
+               buffer_append(&b, session_id2, session_id2_len);
+               skip = session_id2_len;
+               buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+               buffer_put_cstring(&b, authctxt->server_user);
+               buffer_put_cstring(&b, authctxt->service);
+               buffer_put_cstring(&b, authctxt->method->name);
+               buffer_put_char(&b, have_sig);
+               if (!(datafellows & SSH_BUG_PKAUTH))
+                       buffer_put_cstring(&b, key_ssh_name(id->key));
+               buffer_put_string(&b, blob, bloblen);
+       }
+       xfree(blob);
+
+       /* append signature */
+       buffer_put_string(&b, signature, slen);
+       xfree(signature);
+
+       /* skip session id and packet type */
+       if (buffer_len(&b) < skip + 1)
+               fatal("userauth_pubkey: internal error");
+       buffer_consume(&b, skip + 1);
+
+       /* put remaining data from buffer into packet */
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_raw(buffer_ptr(&b), buffer_len(&b));
+       buffer_free(&b);
+       packet_send();
+
+       return 1;
+}
+
+static int
+send_pubkey_test(Authctxt *authctxt, Identity *id)
+{
+       u_char *blob;
+       u_int bloblen, have_sig = 0;
+
+       debug3("send_pubkey_test");
+
+       if (key_to_blob(id->key, &blob, &bloblen) == 0) {
+               /* we cannot handle this key */
+               debug3("send_pubkey_test: cannot handle key");
+               return 0;
+       }
+       /* register callback for USERAUTH_PK_OK message */
+       dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
+
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_char(have_sig);
+       if (!(datafellows & SSH_BUG_PKAUTH))
+               packet_put_cstring(key_ssh_name(id->key));
+       packet_put_string(blob, bloblen);
+       xfree(blob);
+       packet_send();
+       return 1;
+}
+
+static Key *
+load_identity_file(char *filename)
+{
+       Key *private;
+       char prompt[300], *passphrase;
+       int perm_ok = 0, quit, i;
+       struct stat st;
+
+       if (stat(filename, &st) < 0) {
+               debug3("no such identity: %s", filename);
+               return NULL;
+       }
+       private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok);
+       if (!perm_ok)
+               return NULL;
+       if (private == NULL) {
+               if (options.batch_mode)
+                       return NULL;
+               snprintf(prompt, sizeof prompt,
+                   "Enter passphrase for key '%.100s': ", filename);
+               for (i = 0; i < options.number_of_password_prompts; i++) {
+                       passphrase = read_passphrase(prompt, 0);
+                       if (strcmp(passphrase, "") != 0) {
+                               private = key_load_private_type(KEY_UNSPEC,
+                                   filename, passphrase, NULL, NULL);
+                               quit = 0;
+                       } else {
+                               debug2("no passphrase given, try next key");
+                               quit = 1;
+                       }
+                       memset(passphrase, 0, strlen(passphrase));
+                       xfree(passphrase);
+                       if (private != NULL || quit)
+                               break;
+                       debug2("bad passphrase given, try again...");
+               }
+       }
+       return private;
+}
+
+/*
+ * try keys in the following order:
+ *     1. agent keys that are found in the config file
+ *     2. other agent keys
+ *     3. keys that are only listed in the config file
+ */
+static void
+pubkey_prepare(Authctxt *authctxt)
+{
+       Identity *id;
+       Idlist agent, files, *preferred;
+       Key *key;
+       AuthenticationConnection *ac;
+       char *comment;
+       int i, found;
+
+       TAILQ_INIT(&agent);     /* keys from the agent */
+       TAILQ_INIT(&files);     /* keys from the config file */
+       preferred = &authctxt->keys;
+       TAILQ_INIT(preferred);  /* preferred order of keys */
+
+       /* list of keys stored in the filesystem */
+       for (i = 0; i < options.num_identity_files; i++) {
+               key = options.identity_keys[i];
+               if (key && key->type == KEY_RSA1)
+                       continue;
+               if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER)
+                       continue;
+               options.identity_keys[i] = NULL;
+               id = xcalloc(1, sizeof(*id));
+               id->key = key;
+               id->filename = xstrdup(options.identity_files[i]);
+               TAILQ_INSERT_TAIL(&files, id, next);
+       }
+       /* list of keys supported by the agent */
+       if ((ac = ssh_get_authentication_connection())) {
+               for (key = ssh_get_first_identity(ac, &comment, 2);
+                   key != NULL;
+                   key = ssh_get_next_identity(ac, &comment, 2)) {
+                       found = 0;
+                       TAILQ_FOREACH(id, &files, next) {
+                               /* agent keys from the config file are preferred */
+                               if (key_equal(key, id->key)) {
+                                       key_free(key);
+                                       xfree(comment);
+                                       TAILQ_REMOVE(&files, id, next);
+                                       TAILQ_INSERT_TAIL(preferred, id, next);
+                                       id->ac = ac;
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       if (!found && !options.identities_only) {
+                               id = xcalloc(1, sizeof(*id));
+                               id->key = key;
+                               id->filename = comment;
+                               id->ac = ac;
+                               TAILQ_INSERT_TAIL(&agent, id, next);
+                       }
+               }
+               /* append remaining agent keys */
+               for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
+                       TAILQ_REMOVE(&agent, id, next);
+                       TAILQ_INSERT_TAIL(preferred, id, next);
+               }
+               authctxt->agent = ac;
+       }
+       /* append remaining keys from the config file */
+       for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
+               TAILQ_REMOVE(&files, id, next);
+               TAILQ_INSERT_TAIL(preferred, id, next);
+       }
+       TAILQ_FOREACH(id, preferred, next) {
+               debug2("key: %s (%p)", id->filename, id->key);
+       }
+}
+
+static void
+pubkey_cleanup(Authctxt *authctxt)
+{
+       Identity *id;
+
+       if (authctxt->agent != NULL)
+               ssh_close_authentication_connection(authctxt->agent);
+       for (id = TAILQ_FIRST(&authctxt->keys); id;
+           id = TAILQ_FIRST(&authctxt->keys)) {
+               TAILQ_REMOVE(&authctxt->keys, id, next);
+               if (id->key)
+                       key_free(id->key);
+               if (id->filename)
+                       xfree(id->filename);
+               xfree(id);
+       }
+}
+
+int
+userauth_pubkey(Authctxt *authctxt)
+{
+       Identity *id;
+       int sent = 0;
+
+       while ((id = TAILQ_FIRST(&authctxt->keys))) {
+               if (id->tried++)
+                       return (0);
+               /* move key to the end of the queue */
+               TAILQ_REMOVE(&authctxt->keys, id, next);
+               TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
+               /*
+                * send a test message if we have the public key. for
+                * encrypted keys we cannot do this and have to load the
+                * private key instead
+                */
+               if (id->key && id->key->type != KEY_RSA1) {
+                       debug("Offering %s public key: %s", key_type(id->key),
+                           id->filename);
+                       sent = send_pubkey_test(authctxt, id);
+               } else if (id->key == NULL) {
+                       debug("Trying private key: %s", id->filename);
+                       id->key = load_identity_file(id->filename);
+                       if (id->key != NULL) {
+                               id->isprivate = 1;
+                               sent = sign_and_send_pubkey(authctxt, id);
+                               key_free(id->key);
+                               id->key = NULL;
+                       }
+               }
+               if (sent)
+                       return (sent);
+       }
+       return (0);
+}
+
+/*
+ * Send userauth request message specifying keyboard-interactive method.
+ */
+int
+userauth_kbdint(Authctxt *authctxt)
+{
+       static int attempt = 0;
+
+       if (attempt++ >= options.number_of_password_prompts)
+               return 0;
+       /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
+       if (attempt > 1 && !authctxt->info_req_seen) {
+               debug3("userauth_kbdint: disable: no info_req_seen");
+               dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
+               return 0;
+       }
+
+       debug2("userauth_kbdint");
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_cstring("");                                 /* lang */
+       packet_put_cstring(options.kbd_interactive_devices ?
+           options.kbd_interactive_devices : "");
+       packet_send();
+
+       dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
+       return 1;
+}
+
+/*
+ * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
+ */
+void
+input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
+{
+       Authctxt *authctxt = ctxt;
+       char *name, *inst, *lang, *prompt, *response;
+       u_int num_prompts, i;
+       int echo = 0;
+
+       debug2("input_userauth_info_req");
+
+       if (authctxt == NULL)
+               fatal("input_userauth_info_req: no authentication context");
+
+       authctxt->info_req_seen = 1;
+
+       name = packet_get_string(NULL);
+       inst = packet_get_string(NULL);
+       lang = packet_get_string(NULL);
+       if (strlen(name) > 0)
+               logit("%s", name);
+       if (strlen(inst) > 0)
+               logit("%s", inst);
+       xfree(name);
+       xfree(inst);
+       xfree(lang);
+
+       num_prompts = packet_get_int();
+       /*
+        * Begin to build info response packet based on prompts requested.
+        * We commit to providing the correct number of responses, so if
+        * further on we run into a problem that prevents this, we have to
+        * be sure and clean this up and send a correct error response.
+        */
+       packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
+       packet_put_int(num_prompts);
+
+       debug2("input_userauth_info_req: num_prompts %d", num_prompts);
+       for (i = 0; i < num_prompts; i++) {
+               prompt = packet_get_string(NULL);
+               echo = packet_get_char();
+
+               response = read_passphrase(prompt, echo ? RP_ECHO : 0);
+
+               packet_put_cstring(response);
+               memset(response, 0, strlen(response));
+               xfree(response);
+               xfree(prompt);
+       }
+       packet_check_eom(); /* done with parsing incoming message. */
+
+       packet_add_padding(64);
+       packet_send();
+}
+
+static int
+ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
+    u_char *data, u_int datalen)
+{
+       Buffer b;
+       struct stat st;
+       pid_t pid;
+       int to[2], from[2], status, version = 2;
+
+       debug2("ssh_keysign called");
+
+       if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
+               error("ssh_keysign: not installed: %s", strerror(errno));
+               return -1;
+       }
+       if (fflush(stdout) != 0)
+               error("ssh_keysign: fflush: %s", strerror(errno));
+       if (pipe(to) < 0) {
+               error("ssh_keysign: pipe: %s", strerror(errno));
+               return -1;
+       }
+       if (pipe(from) < 0) {
+               error("ssh_keysign: pipe: %s", strerror(errno));
+               return -1;
+       }
+       if ((pid = fork()) < 0) {
+               error("ssh_keysign: fork: %s", strerror(errno));
+               return -1;
+       }
+       if (pid == 0) {
+               /* keep the socket on exec */
+               fcntl(packet_get_connection_in(), F_SETFD, 0);
+               permanently_drop_suid(getuid());
+               close(from[0]);
+               if (dup2(from[1], STDOUT_FILENO) < 0)
+                       fatal("ssh_keysign: dup2: %s", strerror(errno));
+               close(to[1]);
+               if (dup2(to[0], STDIN_FILENO) < 0)
+                       fatal("ssh_keysign: dup2: %s", strerror(errno));
+               close(from[1]);
+               close(to[0]);
+               execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
+               fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
+                   strerror(errno));
+       }
+       close(from[1]);
+       close(to[0]);
+
+       buffer_init(&b);
+       buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
+       buffer_put_string(&b, data, datalen);
+       if (ssh_msg_send(to[1], version, &b) == -1)
+               fatal("ssh_keysign: couldn't send request");
+
+       if (ssh_msg_recv(from[0], &b) < 0) {
+               error("ssh_keysign: no reply");
+               buffer_free(&b);
+               return -1;
+       }
+       close(from[0]);
+       close(to[1]);
+
+       while (waitpid(pid, &status, 0) < 0)
+               if (errno != EINTR)
+                       break;
+
+       if (buffer_get_char(&b) != version) {
+               error("ssh_keysign: bad version");
+               buffer_free(&b);
+               return -1;
+       }
+       *sigp = buffer_get_string(&b, lenp);
+       buffer_free(&b);
+
+       return 0;
+}
+
+int
+userauth_hostbased(Authctxt *authctxt)
+{
+       Key *private = NULL;
+       Sensitive *sensitive = authctxt->sensitive;
+       Buffer b;
+       u_char *signature, *blob;
+       char *chost, *pkalg, *p;
+       const char *service;
+       u_int blen, slen;
+       int ok, i, found = 0;
+
+       /* check for a useful key */
+       for (i = 0; i < sensitive->nkeys; i++) {
+               private = sensitive->keys[i];
+               if (private && private->type != KEY_RSA1) {
+                       found = 1;
+                       /* we take and free the key */
+                       sensitive->keys[i] = NULL;
+                       break;
+               }
+       }
+       if (!found) {
+               debug("No more client hostkeys for hostbased authentication.");
+               return 0;
+       }
+       if (key_to_blob(private, &blob, &blen) == 0) {
+               key_free(private);
+               return 0;
+       }
+       /* figure out a name for the client host */
+       p = get_local_name(packet_get_connection_in());
+       if (p == NULL) {
+               error("userauth_hostbased: cannot get local ipaddr/name");
+               key_free(private);
+               xfree(blob);
+               return 0;
+       }
+       xasprintf(&chost, "%s.", p);
+       debug2("userauth_hostbased: chost %s", chost);
+       xfree(p);
+
+       service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
+           authctxt->service;
+       pkalg = xstrdup(key_ssh_name(private));
+       buffer_init(&b);
+       /* construct data */
+       buffer_put_string(&b, session_id2, session_id2_len);
+       buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+       buffer_put_cstring(&b, authctxt->server_user);
+       buffer_put_cstring(&b, service);
+       buffer_put_cstring(&b, authctxt->method->name);
+       buffer_put_cstring(&b, pkalg);
+       buffer_put_string(&b, blob, blen);
+       buffer_put_cstring(&b, chost);
+       buffer_put_cstring(&b, authctxt->local_user);
+#ifdef DEBUG_PK
+       buffer_dump(&b);
+#endif
+       if (sensitive->external_keysign)
+               ok = ssh_keysign(private, &signature, &slen,
+                   buffer_ptr(&b), buffer_len(&b));
+       else
+               ok = key_sign(private, &signature, &slen,
+                   buffer_ptr(&b), buffer_len(&b));
+       key_free(private);
+       buffer_free(&b);
+       if (ok != 0) {
+               error("key_sign failed");
+               xfree(chost);
+               xfree(pkalg);
+               xfree(blob);
+               return 0;
+       }
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_cstring(pkalg);
+       packet_put_string(blob, blen);
+       packet_put_cstring(chost);
+       packet_put_cstring(authctxt->local_user);
+       packet_put_string(signature, slen);
+       memset(signature, 's', slen);
+       xfree(signature);
+       xfree(chost);
+       xfree(pkalg);
+       xfree(blob);
+
+       packet_send();
+       return 1;
+}
+
+#ifdef JPAKE
+int
+userauth_jpake(Authctxt *authctxt)
+{
+       struct jpake_ctx *pctx;
+       u_char *x1_proof, *x2_proof;
+       u_int x1_proof_len, x2_proof_len;
+       static int attempt = 0; /* XXX share with userauth_password's? */
+
+       if (attempt++ >= options.number_of_password_prompts)
+               return 0;
+       if (attempt != 1)
+               error("Permission denied, please try again.");
+
+       if (authctxt->methoddata != NULL)
+               fatal("%s: authctxt->methoddata already set (%p)",
+                   __func__, authctxt->methoddata);
+
+       authctxt->methoddata = pctx = jpake_new();
+
+       /*
+        * Send request immediately, to get the protocol going while
+        * we do the initial computations.
+        */
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_send();
+       packet_write_wait();
+
+       jpake_step1(pctx->grp,
+           &pctx->client_id, &pctx->client_id_len,
+           &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2,
+           &x1_proof, &x1_proof_len,
+           &x2_proof, &x2_proof_len);
+
+       JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
+
+       packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1);
+       packet_put_string(pctx->client_id, pctx->client_id_len);
+       packet_put_bignum2(pctx->g_x1);
+       packet_put_bignum2(pctx->g_x2);
+       packet_put_string(x1_proof, x1_proof_len);
+       packet_put_string(x2_proof, x2_proof_len);
+       packet_send();
+
+       bzero(x1_proof, x1_proof_len);
+       bzero(x2_proof, x2_proof_len);
+       xfree(x1_proof);
+       xfree(x2_proof);
+
+       /* Expect step 1 packet from peer */
+       dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1,
+           input_userauth_jpake_server_step1);
+       dispatch_set(SSH2_MSG_USERAUTH_SUCCESS,
+           &input_userauth_success_unexpected);
+
+       return 1;
+}
+
+void
+userauth_jpake_cleanup(Authctxt *authctxt)
+{
+       debug3("%s: clean up", __func__);
+       if (authctxt->methoddata != NULL) {
+               jpake_free(authctxt->methoddata);
+               authctxt->methoddata = NULL;
+       }
+       dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
+}
+#endif /* JPAKE */
+
+/* find auth method */
+
+/*
+ * given auth method name, if configurable options permit this method fill
+ * in auth_ident field and return true, otherwise return false.
+ */
+static int
+authmethod_is_enabled(Authmethod *method)
+{
+       if (method == NULL)
+               return 0;
+       /* return false if options indicate this method is disabled */
+       if  (method->enabled == NULL || *method->enabled == 0)
+               return 0;
+       /* return false if batch mode is enabled but method needs interactive mode */
+       if  (method->batch_flag != NULL && *method->batch_flag != 0)
+               return 0;
+       return 1;
+}
+
+static Authmethod *
+authmethod_lookup(const char *name)
+{
+       Authmethod *method = NULL;
+       if (name != NULL)
+               for (method = authmethods; method->name != NULL; method++)
+                       if (strcmp(name, method->name) == 0)
+                               return method;
+       debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
+       return NULL;
+}
+
+/* XXX internal state */
+static Authmethod *current = NULL;
+static char *supported = NULL;
+static char *preferred = NULL;
+
+/*
+ * Given the authentication method list sent by the server, return the
+ * next method we should try.  If the server initially sends a nil list,
+ * use a built-in default list.
+ */
+static Authmethod *
+authmethod_get(char *authlist)
+{
+       char *name = NULL;
+       u_int next;
+
+       /* Use a suitable default if we're passed a nil list.  */
+       if (authlist == NULL || strlen(authlist) == 0)
+               authlist = options.preferred_authentications;
+
+       if (supported == NULL || strcmp(authlist, supported) != 0) {
+               debug3("start over, passed a different list %s", authlist);
+               if (supported != NULL)
+                       xfree(supported);
+               supported = xstrdup(authlist);
+               preferred = options.preferred_authentications;
+               debug3("preferred %s", preferred);
+               current = NULL;
+       } else if (current != NULL && authmethod_is_enabled(current))
+               return current;
+
+       for (;;) {
+               if ((name = match_list(preferred, supported, &next)) == NULL) {
+                       debug("No more authentication methods to try.");
+                       current = NULL;
+                       return NULL;
+               }
+               preferred += next;
+               debug3("authmethod_lookup %s", name);
+               debug3("remaining preferred: %s", preferred);
+               if ((current = authmethod_lookup(name)) != NULL &&
+                   authmethod_is_enabled(current)) {
+                       debug3("authmethod_is_enabled %s", name);
+                       debug("Next authentication method: %s", name);
+                       xfree(name);
+                       return current;
+               }
+       }
+       if (name != NULL)
+               xfree(name);
+}
+
+static char *
+authmethods_get(void)
+{
+       Authmethod *method = NULL;
+       Buffer b;
+       char *list;
+
+       buffer_init(&b);
+       for (method = authmethods; method->name != NULL; method++) {
+               if (authmethod_is_enabled(method)) {
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       buffer_append(&b, method->name, strlen(method->name));
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       list = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       return list;
+}
+
diff --git a/.pc/ssh-vulnkey.patch/sshd.8 b/.pc/ssh-vulnkey.patch/sshd.8
new file mode 100644 (file)
index 0000000..a91be0f
--- /dev/null
@@ -0,0 +1,979 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd.8,v 1.263 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD 8
+.Os
+.Sh NAME
+.Nm sshd
+.Nd OpenSSH SSH daemon
+.Sh SYNOPSIS
+.Nm sshd
+.Bk -words
+.Op Fl 46DdeiqTt
+.Op Fl b Ar bits
+.Op Fl C Ar connection_spec
+.Op Fl c Ar host_certificate_file
+.Op Fl f Ar config_file
+.Op Fl g Ar login_grace_time
+.Op Fl h Ar host_key_file
+.Op Fl k Ar key_gen_time
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Op Fl u Ar len
+.Ek
+.Sh DESCRIPTION
+.Nm
+(OpenSSH Daemon) is the daemon program for
+.Xr ssh 1 .
+Together these programs replace
+.Xr rlogin 1
+and
+.Xr rsh 1 ,
+and provide secure encrypted communications between two untrusted hosts
+over an insecure network.
+.Pp
+.Nm
+listens for connections from clients.
+It is normally started at boot from
+.Pa /etc/rc .
+It forks a new
+daemon for each incoming connection.
+The forked daemons handle
+key exchange, encryption, authentication, command execution,
+and data exchange.
+.Pp
+.Nm
+can be configured using command-line options or a configuration file
+(by default
+.Xr sshd_config 5 ) ;
+command-line options override values specified in the
+configuration file.
+.Nm
+rereads its configuration file when it receives a hangup signal,
+.Dv SIGHUP ,
+by executing itself with the name and options it was started with, e.g.\&
+.Pa /usr/sbin/sshd .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl b Ar bits
+Specifies the number of bits in the ephemeral protocol version 1
+server key (default 1024).
+.It Fl C Ar connection_spec
+Specify the connection parameters to use for the
+.Fl T
+extended test mode.
+If provided, any
+.Cm Match
+directives in the configuration file
+that would apply to the specified user, host, and address will be set before
+the configuration is written to standard output.
+The connection parameters are supplied as keyword=value pairs.
+The keywords are
+.Dq user ,
+.Dq host ,
+and
+.Dq addr .
+All are required and may be supplied in any order, either with multiple
+.Fl C
+options or as a comma-separated list.
+.It Fl c Ar host_certificate_file
+Specifies a path to a certificate file to identify
+.Nm
+during key exchange.
+The certificate file must match a host key file specified using the
+.Fl h
+option or the
+.Cm HostKey
+configuration directive.
+.It Fl D
+When this option is specified,
+.Nm
+will not detach and does not become a daemon.
+This allows easy monitoring of
+.Nm sshd .
+.It Fl d
+Debug mode.
+The server sends verbose debug output to standard error,
+and does not put itself in the background.
+The server also will not fork and will only process one connection.
+This option is only intended for debugging for the server.
+Multiple
+.Fl d
+options increase the debugging level.
+Maximum is 3.
+.It Fl e
+When this option is specified,
+.Nm
+will send the output to the standard error instead of the system log.
+.It Fl f Ar config_file
+Specifies the name of the configuration file.
+The default is
+.Pa /etc/ssh/sshd_config .
+.Nm
+refuses to start if there is no configuration file.
+.It Fl g Ar login_grace_time
+Gives the grace time for clients to authenticate themselves (default
+120 seconds).
+If the client fails to authenticate the user within
+this many seconds, the server disconnects and exits.
+A value of zero indicates no limit.
+.It Fl h Ar host_key_file
+Specifies a file from which a host key is read.
+This option must be given if
+.Nm
+is not run as root (as the normal
+host key files are normally not readable by anyone but root).
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+It is possible to have multiple host key files for
+the different protocol versions and host key algorithms.
+.It Fl i
+Specifies that
+.Nm
+is being run from
+.Xr inetd 8 .
+.Nm
+is normally not run
+from inetd because it needs to generate the server key before it can
+respond to the client, and this may take tens of seconds.
+Clients would have to wait too long if the key was regenerated every time.
+However, with small key sizes (e.g. 512) using
+.Nm
+from inetd may
+be feasible.
+.It Fl k Ar key_gen_time
+Specifies how often the ephemeral protocol version 1 server key is
+regenerated (default 3600 seconds, or one hour).
+The motivation for regenerating the key fairly
+often is that the key is not stored anywhere, and after about an hour
+it becomes impossible to recover the key for decrypting intercepted
+communications even if the machine is cracked into or physically
+seized.
+A value of zero indicates that the key will never be regenerated.
+.It Fl o Ar option
+Can be used to give options in the format used in the configuration file.
+This is useful for specifying options for which there is no separate
+command-line flag.
+For full details of the options, and their values, see
+.Xr sshd_config 5 .
+.It Fl p Ar port
+Specifies the port on which the server listens for connections
+(default 22).
+Multiple port options are permitted.
+Ports specified in the configuration file with the
+.Cm Port
+option are ignored when a command-line port is specified.
+Ports specified using the
+.Cm ListenAddress
+option override command-line ports.
+.It Fl q
+Quiet mode.
+Nothing is sent to the system log.
+Normally the beginning,
+authentication, and termination of each connection is logged.
+.It Fl T
+Extended test mode.
+Check the validity of the configuration file, output the effective configuration
+to stdout and then exit.
+Optionally,
+.Cm Match
+rules may be applied by specifying the connection parameters using one or more
+.Fl C
+options.
+.It Fl t
+Test mode.
+Only check the validity of the configuration file and sanity of the keys.
+This is useful for updating
+.Nm
+reliably as configuration options may change.
+.It Fl u Ar len
+This option is used to specify the size of the field
+in the
+.Li utmp
+structure that holds the remote host name.
+If the resolved host name is longer than
+.Ar len ,
+the dotted decimal value will be used instead.
+This allows hosts with very long host names that
+overflow this field to still be uniquely identified.
+Specifying
+.Fl u0
+indicates that only dotted decimal addresses
+should be put into the
+.Pa utmp
+file.
+.Fl u0
+may also be used to prevent
+.Nm
+from making DNS requests unless the authentication
+mechanism or configuration requires it.
+Authentication mechanisms that may require DNS include
+.Cm RhostsRSAAuthentication ,
+.Cm HostbasedAuthentication ,
+and using a
+.Cm from="pattern-list"
+option in a key file.
+Configuration options that require DNS include using a
+USER@HOST pattern in
+.Cm AllowUsers
+or
+.Cm DenyUsers .
+.El
+.Sh AUTHENTICATION
+The OpenSSH SSH daemon supports SSH protocols 1 and 2.
+The default is to use protocol 2 only,
+though this can be changed via the
+.Cm Protocol
+option in
+.Xr sshd_config 5 .
+Protocol 2 supports DSA, ECDSA and RSA keys;
+protocol 1 only supports RSA keys.
+For both protocols,
+each host has a host-specific key,
+normally 2048 bits,
+used to identify the host.
+.Pp
+Forward security for protocol 1 is provided through
+an additional server key,
+normally 768 bits,
+generated when the server starts.
+This key is normally regenerated every hour if it has been used, and
+is never stored on disk.
+Whenever a client connects, the daemon responds with its public
+host and server keys.
+The client compares the
+RSA host key against its own database to verify that it has not changed.
+The client then generates a 256-bit random number.
+It encrypts this
+random number using both the host key and the server key, and sends
+the encrypted number to the server.
+Both sides then use this
+random number as a session key which is used to encrypt all further
+communications in the session.
+The rest of the session is encrypted
+using a conventional cipher, currently Blowfish or 3DES, with 3DES
+being used by default.
+The client selects the encryption algorithm
+to use from those offered by the server.
+.Pp
+For protocol 2,
+forward security is provided through a Diffie-Hellman key agreement.
+This key agreement results in a shared session key.
+The rest of the session is encrypted using a symmetric cipher, currently
+128-bit AES, Blowfish, 3DES, CAST128, Arcfour, 192-bit AES, or 256-bit AES.
+The client selects the encryption algorithm
+to use from those offered by the server.
+Additionally, session integrity is provided
+through a cryptographic message authentication code
+(hmac-md5, hmac-sha1, umac-64, hmac-ripemd160,
+hmac-sha2-256 or hmac-sha2-512).
+.Pp
+Finally, the server and the client enter an authentication dialog.
+The client tries to authenticate itself using
+host-based authentication,
+public key authentication,
+challenge-response authentication,
+or password authentication.
+.Pp
+Regardless of the authentication type, the account is checked to
+ensure that it is accessible.  An account is not accessible if it is
+locked, listed in
+.Cm DenyUsers
+or its group is listed in
+.Cm DenyGroups
+\&.  The definition of a locked account is system dependant. Some platforms
+have their own account database (eg AIX) and some modify the passwd field (
+.Ql \&*LK\&*
+on Solaris and UnixWare,
+.Ql \&*
+on HP-UX, containing
+.Ql Nologin
+on Tru64,
+a leading
+.Ql \&*LOCKED\&*
+on FreeBSD and a leading
+.Ql \&!
+on most Linuxes).
+If there is a requirement to disable password authentication
+for the account while allowing still public-key, then the passwd field
+should be set to something other than these values (eg
+.Ql NP
+or
+.Ql \&*NP\&*
+).
+.Pp
+If the client successfully authenticates itself, a dialog for
+preparing the session is entered.
+At this time the client may request
+things like allocating a pseudo-tty, forwarding X11 connections,
+forwarding TCP connections, or forwarding the authentication agent
+connection over the secure channel.
+.Pp
+After this, the client either requests a shell or execution of a command.
+The sides then enter session mode.
+In this mode, either side may send
+data at any time, and such data is forwarded to/from the shell or
+command on the server side, and the user terminal in the client side.
+.Pp
+When the user program terminates and all forwarded X11 and other
+connections have been closed, the server sends command exit status to
+the client, and both sides exit.
+.Sh LOGIN PROCESS
+When a user successfully logs in,
+.Nm
+does the following:
+.Bl -enum -offset indent
+.It
+If the login is on a tty, and no command has been specified,
+prints last login time and
+.Pa /etc/motd
+(unless prevented in the configuration file or by
+.Pa ~/.hushlogin ;
+see the
+.Sx FILES
+section).
+.It
+If the login is on a tty, records login time.
+.It
+Checks
+.Pa /etc/nologin ;
+if it exists, prints contents and quits
+(unless root).
+.It
+Changes to run with normal user privileges.
+.It
+Sets up basic environment.
+.It
+Reads the file
+.Pa ~/.ssh/environment ,
+if it exists, and users are allowed to change their environment.
+See the
+.Cm PermitUserEnvironment
+option in
+.Xr sshd_config 5 .
+.It
+Changes to user's home directory.
+.It
+If
+.Pa ~/.ssh/rc
+exists, runs it; else if
+.Pa /etc/ssh/sshrc
+exists, runs
+it; otherwise runs xauth.
+The
+.Dq rc
+files are given the X11
+authentication protocol and cookie in standard input.
+See
+.Sx SSHRC ,
+below.
+.It
+Runs user's shell or command.
+.El
+.Sh SSHRC
+If the file
+.Pa ~/.ssh/rc
+exists,
+.Xr sh 1
+runs it after reading the
+environment files but before starting the user's shell or command.
+It must not produce any output on stdout; stderr must be used
+instead.
+If X11 forwarding is in use, it will receive the "proto cookie" pair in
+its standard input (and
+.Ev DISPLAY
+in its environment).
+The script must call
+.Xr xauth 1
+because
+.Nm
+will not run xauth automatically to add X11 cookies.
+.Pp
+The primary purpose of this file is to run any initialization routines
+which may be needed before the user's home directory becomes
+accessible; AFS is a particular example of such an environment.
+.Pp
+This file will probably contain some initialization code followed by
+something similar to:
+.Bd -literal -offset 3n
+if read proto cookie && [ -n "$DISPLAY" ]; then
+       if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then
+               # X11UseLocalhost=yes
+               echo add unix:`echo $DISPLAY |
+                   cut -c11-` $proto $cookie
+       else
+               # X11UseLocalhost=no
+               echo add $DISPLAY $proto $cookie
+       fi | xauth -q -
+fi
+.Ed
+.Pp
+If this file does not exist,
+.Pa /etc/ssh/sshrc
+is run, and if that
+does not exist either, xauth is used to add the cookie.
+.Sh AUTHORIZED_KEYS FILE FORMAT
+.Cm AuthorizedKeysFile
+specifies the files containing public keys for
+public key authentication;
+if none is specified, the default is
+.Pa ~/.ssh/authorized_keys
+and
+.Pa ~/.ssh/authorized_keys2 .
+Each line of the file contains one
+key (empty lines and lines starting with a
+.Ql #
+are ignored as
+comments).
+Protocol 1 public keys consist of the following space-separated fields:
+options, bits, exponent, modulus, comment.
+Protocol 2 public key consist of:
+options, keytype, base64-encoded key, comment.
+The options field is optional;
+its presence is determined by whether the line starts
+with a number or not (the options field never starts with a number).
+The bits, exponent, modulus, and comment fields give the RSA key for
+protocol version 1; the
+comment field is not used for anything (but may be convenient for the
+user to identify the key).
+For protocol version 2 the keytype is
+.Dq ecdsa-sha2-nistp256 ,
+.Dq ecdsa-sha2-nistp384 ,
+.Dq ecdsa-sha2-nistp521 ,
+.Dq ssh-dss
+or
+.Dq ssh-rsa .
+.Pp
+Note that lines in this file are usually several hundred bytes long
+(because of the size of the public key encoding) up to a limit of
+8 kilobytes, which permits DSA keys up to 8 kilobits and RSA
+keys up to 16 kilobits.
+You don't want to type them in; instead, copy the
+.Pa identity.pub ,
+.Pa id_dsa.pub ,
+.Pa id_ecdsa.pub ,
+or the
+.Pa id_rsa.pub
+file and edit it.
+.Pp
+.Nm
+enforces a minimum RSA key modulus size for protocol 1
+and protocol 2 keys of 768 bits.
+.Pp
+The options (if present) consist of comma-separated option
+specifications.
+No spaces are permitted, except within double quotes.
+The following option specifications are supported (note
+that option keywords are case-insensitive):
+.Bl -tag -width Ds
+.It Cm cert-authority
+Specifies that the listed key is a certification authority (CA) that is
+trusted to validate signed certificates for user authentication.
+.Pp
+Certificates may encode access restrictions similar to these key options.
+If both certificate restrictions and key options are present, the most
+restrictive union of the two is applied.
+.It Cm command="command"
+Specifies that the command is executed whenever this key is used for
+authentication.
+The command supplied by the user (if any) is ignored.
+The command is run on a pty if the client requests a pty;
+otherwise it is run without a tty.
+If an 8-bit clean channel is required,
+one must not request a pty or should specify
+.Cm no-pty .
+A quote may be included in the command by quoting it with a backslash.
+This option might be useful
+to restrict certain public keys to perform just a specific operation.
+An example might be a key that permits remote backups but nothing else.
+Note that the client may specify TCP and/or X11
+forwarding unless they are explicitly prohibited.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Note that this option applies to shell, command or subsystem execution.
+Also note that this command may be superseded by either a
+.Xr sshd_config 5
+.Cm ForceCommand
+directive or a command embedded in a certificate.
+.It Cm environment="NAME=value"
+Specifies that the string is to be added to the environment when
+logging in using this key.
+Environment variables set this way
+override other default environment values.
+Multiple options of this type are permitted.
+Environment processing is disabled by default and is
+controlled via the
+.Cm PermitUserEnvironment
+option.
+This option is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm from="pattern-list"
+Specifies that in addition to public key authentication, either the canonical
+name of the remote host or its IP address must be present in the
+comma-separated list of patterns.
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.Pp
+In addition to the wildcard matching that may be applied to hostnames or
+addresses, a
+.Cm from
+stanza may match IP addresses using CIDR address/masklen notation.
+.Pp
+The purpose of this option is to optionally increase security: public key
+authentication by itself does not trust the network or name servers or
+anything (but the key); however, if somebody somehow steals the key, the key
+permits an intruder to log in from anywhere in the world.
+This additional option makes using a stolen key more difficult (name
+servers and/or routers would have to be compromised in addition to
+just the key).
+.It Cm no-agent-forwarding
+Forbids authentication agent forwarding when this key is used for
+authentication.
+.It Cm no-port-forwarding
+Forbids TCP forwarding when this key is used for authentication.
+Any port forward requests by the client will return an error.
+This might be used, e.g. in connection with the
+.Cm command
+option.
+.It Cm no-pty
+Prevents tty allocation (a request to allocate a pty will fail).
+.It Cm no-user-rc
+Disables execution of
+.Pa ~/.ssh/rc .
+.It Cm no-X11-forwarding
+Forbids X11 forwarding when this key is used for authentication.
+Any X11 forward requests by the client will return an error.
+.It Cm permitopen="host:port"
+Limit local
+.Li ``ssh -L''
+port forwarding such that it may only connect to the specified host and
+port.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Multiple
+.Cm permitopen
+options may be applied separated by commas.
+No pattern matching is performed on the specified hostnames,
+they must be literal domains or addresses.
+.It Cm principals="principals"
+On a
+.Cm cert-authority
+line, specifies allowed principals for certificate authentication as a
+comma-separated list.
+At least one name from the list must appear in the certificate's
+list of principals for the certificate to be accepted.
+This option is ignored for keys that are not marked as trusted certificate
+signers using the
+.Cm cert-authority
+option.
+.It Cm tunnel="n"
+Force a
+.Xr tun 4
+device on the server.
+Without this option, the next available device will be used if
+the client requests a tunnel.
+.El
+.Pp
+An example authorized_keys file:
+.Bd -literal -offset 3n
+# Comments allowed at start of line
+ssh-rsa AAAAB3Nza...LiPk== user@example.net
+from="*.sales.example.net,!pc.sales.example.net" ssh-rsa
+AAAAB2...19Q== john@example.net
+command="dump /home",no-pty,no-port-forwarding ssh-dss
+AAAAC3...51R== example.net
+permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss
+AAAAB5...21S==
+tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...==
+jane@example.net
+.Ed
+.Sh SSH_KNOWN_HOSTS FILE FORMAT
+The
+.Pa /etc/ssh/ssh_known_hosts
+and
+.Pa ~/.ssh/known_hosts
+files contain host public keys for all known hosts.
+The global file should
+be prepared by the administrator (optional), and the per-user file is
+maintained automatically: whenever the user connects from an unknown host,
+its key is added to the per-user file.
+.Pp
+Each line in these files contains the following fields: markers (optional),
+hostnames, bits, exponent, modulus, comment.
+The fields are separated by spaces.
+.Pp
+The marker is optional, but if it is present then it must be one of
+.Dq @cert-authority ,
+to indicate that the line contains a certification authority (CA) key,
+or
+.Dq @revoked ,
+to indicate that the key contained on the line is revoked and must not ever
+be accepted.
+Only one marker should be used on a key line.
+.Pp
+Hostnames is a comma-separated list of patterns
+.Pf ( Ql *
+and
+.Ql \&?
+act as
+wildcards); each pattern in turn is matched against the canonical host
+name (when authenticating a client) or against the user-supplied
+name (when authenticating a server).
+A pattern may also be preceded by
+.Ql \&!
+to indicate negation: if the host name matches a negated
+pattern, it is not accepted (by that line) even if it matched another
+pattern on the line.
+A hostname or address may optionally be enclosed within
+.Ql \&[
+and
+.Ql \&]
+brackets then followed by
+.Ql \&:
+and a non-standard port number.
+.Pp
+Alternately, hostnames may be stored in a hashed form which hides host names
+and addresses should the file's contents be disclosed.
+Hashed hostnames start with a
+.Ql |
+character.
+Only one hashed hostname may appear on a single line and none of the above
+negation or wildcard operators may be applied.
+.Pp
+Bits, exponent, and modulus are taken directly from the RSA host key; they
+can be obtained, for example, from
+.Pa /etc/ssh/ssh_host_key.pub .
+The optional comment field continues to the end of the line, and is not used.
+.Pp
+Lines starting with
+.Ql #
+and empty lines are ignored as comments.
+.Pp
+When performing host authentication, authentication is accepted if any
+matching line has the proper key; either one that matches exactly or,
+if the server has presented a certificate for authentication, the key
+of the certification authority that signed the certificate.
+For a key to be trusted as a certification authority, it must use the
+.Dq @cert-authority
+marker described above.
+.Pp
+The known hosts file also provides a facility to mark keys as revoked,
+for example when it is known that the associated private key has been
+stolen.
+Revoked keys are specified by including the
+.Dq @revoked
+marker at the beginning of the key line, and are never accepted for
+authentication or as certification authorities, but instead will
+produce a warning from
+.Xr ssh 1
+when they are encountered.
+.Pp
+It is permissible (but not
+recommended) to have several lines or different host keys for the same
+names.
+This will inevitably happen when short forms of host names
+from different domains are put in the file.
+It is possible
+that the files contain conflicting information; authentication is
+accepted if valid information can be found from either file.
+.Pp
+Note that the lines in these files are typically hundreds of characters
+long, and you definitely don't want to type in the host keys by hand.
+Rather, generate them by a script,
+.Xr ssh-keyscan 1
+or by taking
+.Pa /etc/ssh/ssh_host_key.pub
+and adding the host names at the front.
+.Xr ssh-keygen 1
+also offers some basic automated editing for
+.Pa ~/.ssh/known_hosts
+including removing hosts matching a host name and converting all host
+names to their hashed representations.
+.Pp
+An example ssh_known_hosts file:
+.Bd -literal -offset 3n
+# Comments allowed at start of line
+closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net
+cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=
+# A hashed hostname
+|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa
+AAAA1234.....=
+# A revoked key
+@revoked * ssh-rsa AAAAB5W...
+# A CA key, accepted for any host in *.mydomain.com or *.mydomain.org
+@cert-authority *.mydomain.org,*.mydomain.com ssh-rsa AAAAB5W...
+.Ed
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.hushlogin
+This file is used to suppress printing the last login time and
+.Pa /etc/motd ,
+if
+.Cm PrintLastLog
+and
+.Cm PrintMotd ,
+respectively,
+are enabled.
+It does not suppress printing of the banner specified by
+.Cm Banner .
+.Pp
+.It Pa ~/.rhosts
+This file is used for host-based authentication (see
+.Xr ssh 1
+for more information).
+On some machines this file may need to be
+world-readable if the user's home directory is on an NFS partition,
+because
+.Nm
+reads it as root.
+Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else.
+The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.Pp
+.It Pa ~/.shosts
+This file is used in exactly the same way as
+.Pa .rhosts ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa ~/.ssh/
+This directory is the default location for all user-specific configuration
+and authentication information.
+There is no general requirement to keep the entire contents of this directory
+secret, but the recommended permissions are read/write/execute for the user,
+and not accessible by others.
+.Pp
+.It Pa ~/.ssh/authorized_keys
+Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in
+as this user.
+The format of this file is described above.
+The content of the file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.Pp
+If this file, the
+.Pa ~/.ssh
+directory, or the user's home directory are writable
+by other users, then the file could be modified or replaced by unauthorized
+users.
+In this case,
+.Nm
+will not allow it to be used unless the
+.Cm StrictModes
+option has been set to
+.Dq no .
+.Pp
+.It Pa ~/.ssh/environment
+This file is read into the environment at login (if it exists).
+It can only contain empty lines, comment lines (that start with
+.Ql # ) ,
+and assignment lines of the form name=value.
+The file should be writable
+only by the user; it need not be readable by anyone else.
+Environment processing is disabled by default and is
+controlled via the
+.Cm PermitUserEnvironment
+option.
+.Pp
+.It Pa ~/.ssh/known_hosts
+Contains a list of host keys for all hosts the user has logged into
+that are not already in the systemwide list of known host keys.
+The format of this file is described above.
+This file should be writable only by root/the owner and
+can, but need not be, world-readable.
+.Pp
+.It Pa ~/.ssh/rc
+Contains initialization routines to be run before
+the user's home directory becomes accessible.
+This file should be writable only by the user, and need not be
+readable by anyone else.
+.Pp
+.It Pa /etc/hosts.allow
+.It Pa /etc/hosts.deny
+Access controls that should be enforced by tcp-wrappers are defined here.
+Further details are described in
+.Xr hosts_access 5 .
+.Pp
+.It Pa /etc/hosts.equiv
+This file is for host-based authentication (see
+.Xr ssh 1 ) .
+It should only be writable by root.
+.Pp
+.It Pa /etc/moduli
+Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange".
+The file format is described in
+.Xr moduli 5 .
+.Pp
+.It Pa /etc/motd
+See
+.Xr motd 5 .
+.Pp
+.It Pa /etc/nologin
+If this file exists,
+.Nm
+refuses to let anyone except root log in.
+The contents of the file
+are displayed to anyone trying to log in, and non-root connections are
+refused.
+The file should be world-readable.
+.Pp
+.It Pa /etc/shosts.equiv
+This file is used in exactly the same way as
+.Pa hosts.equiv ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa /etc/ssh/ssh_host_key
+.It Pa /etc/ssh/ssh_host_dsa_key
+.It Pa /etc/ssh/ssh_host_ecdsa_key
+.It Pa /etc/ssh/ssh_host_rsa_key
+These three files contain the private parts of the host keys.
+These files should only be owned by root, readable only by root, and not
+accessible to others.
+Note that
+.Nm
+does not start if these files are group/world-accessible.
+.Pp
+.It Pa /etc/ssh/ssh_host_key.pub
+.It Pa /etc/ssh/ssh_host_dsa_key.pub
+.It Pa /etc/ssh/ssh_host_ecdsa_key.pub
+.It Pa /etc/ssh/ssh_host_rsa_key.pub
+These three files contain the public parts of the host keys.
+These files should be world-readable but writable only by
+root.
+Their contents should match the respective private parts.
+These files are not
+really used for anything; they are provided for the convenience of
+the user so their contents can be copied to known hosts files.
+These files are created using
+.Xr ssh-keygen 1 .
+.Pp
+.It Pa /etc/ssh/ssh_known_hosts
+Systemwide list of known host keys.
+This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization.
+The format of this file is described above.
+This file should be writable only by root/the owner and
+should be world-readable.
+.Pp
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Nm sshd .
+The file format and configuration options are described in
+.Xr sshd_config 5 .
+.Pp
+.It Pa /etc/ssh/sshrc
+Similar to
+.Pa ~/.ssh/rc ,
+it can be used to specify
+machine-specific login-time initializations globally.
+This file should be writable only by root, and should be world-readable.
+.Pp
+.It Pa /var/empty
+.Xr chroot 2
+directory used by
+.Nm
+during privilege separation in the pre-authentication phase.
+The directory should not contain any files and must be owned by root
+and not group or world-writable.
+.Pp
+.It Pa /var/run/sshd.pid
+Contains the process ID of the
+.Nm
+listening for connections (if there are several daemons running
+concurrently for different ports, this contains the process ID of the one
+started last).
+The content of this file is not sensitive; it can be world-readable.
+.El
+.Sh SEE ALSO
+.Xr scp 1 ,
+.Xr sftp 1 ,
+.Xr ssh 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-keygen 1 ,
+.Xr ssh-keyscan 1 ,
+.Xr chroot 2 ,
+.Xr hosts_access 5 ,
+.Xr login.conf 5 ,
+.Xr moduli 5 ,
+.Xr sshd_config 5 ,
+.Xr inetd 8 ,
+.Xr sftp-server 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
+.Sh CAVEATS
+System security is not improved unless
+.Nm rshd ,
+.Nm rlogind ,
+and
+.Nm rexecd
+are disabled (thus completely disabling
+.Xr rlogin
+and
+.Xr rsh
+into the machine).
diff --git a/.pc/ssh-vulnkey.patch/sshd.c b/.pc/ssh-vulnkey.patch/sshd.c
new file mode 100644 (file)
index 0000000..5907597
--- /dev/null
@@ -0,0 +1,2481 @@
+/* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * This program is the ssh daemon.  It listens for connections from clients,
+ * and performs authentication, executes use commands or shell, and forwards
+ * information to/from the application to the user client over an encrypted
+ * connection.  This can also handle forwarding of X11, TCP/IP, and
+ * authentication agent connections.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * SSH2 implementation:
+ * Privilege Separation:
+ *
+ * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2002 Niels Provos.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include "openbsd-compat/sys-tree.h"
+#include "openbsd-compat/sys-queue.h"
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/md5.h>
+#include <openssl/rand.h>
+#include "openbsd-compat/openssl-compat.h"
+
+#ifdef HAVE_SECUREWARE
+#include <sys/security.h>
+#include <prot.h>
+#endif
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "rsa.h"
+#include "sshpty.h"
+#include "packet.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "uidswap.h"
+#include "compat.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include "dh.h"
+#include "myproposal.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "atomicio.h"
+#include "canohost.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "misc.h"
+#include "msg.h"
+#include "dispatch.h"
+#include "channels.h"
+#include "session.h"
+#include "monitor_mm.h"
+#include "monitor.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "monitor_wrap.h"
+#include "roaming.h"
+#include "ssh-sandbox.h"
+#include "version.h"
+
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
+
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int allow_severity;
+int deny_severity;
+#endif /* LIBWRAP */
+
+#ifndef O_NOCTTY
+#define O_NOCTTY       0
+#endif
+
+/* Re-exec fds */
+#define REEXEC_DEVCRYPTO_RESERVED_FD   (STDERR_FILENO + 1)
+#define REEXEC_STARTUP_PIPE_FD         (STDERR_FILENO + 2)
+#define REEXEC_CONFIG_PASS_FD          (STDERR_FILENO + 3)
+#define REEXEC_MIN_FREE_FD             (STDERR_FILENO + 4)
+
+extern char *__progname;
+
+/* Server configuration options. */
+ServerOptions options;
+
+/* Name of the server configuration file. */
+char *config_file_name = _PATH_SERVER_CONFIG_FILE;
+
+/*
+ * Debug mode flag.  This can be set on the command line.  If debug
+ * mode is enabled, extra debugging output will be sent to the system
+ * log, the daemon will not go to background, and will exit after processing
+ * the first connection.
+ */
+int debug_flag = 0;
+
+/* Flag indicating that the daemon should only test the configuration and keys. */
+int test_flag = 0;
+
+/* Flag indicating that the daemon is being started from inetd. */
+int inetd_flag = 0;
+
+/* Flag indicating that sshd should not detach and become a daemon. */
+int no_daemon_flag = 0;
+
+/* debug goes to stderr unless inetd_flag is set */
+int log_stderr = 0;
+
+/* Saved arguments to main(). */
+char **saved_argv;
+int saved_argc;
+
+/* re-exec */
+int rexeced_flag = 0;
+int rexec_flag = 1;
+int rexec_argc = 0;
+char **rexec_argv;
+
+/*
+ * The sockets that the server is listening; this is used in the SIGHUP
+ * signal handler.
+ */
+#define        MAX_LISTEN_SOCKS        16
+int listen_socks[MAX_LISTEN_SOCKS];
+int num_listen_socks = 0;
+
+/*
+ * the client's version string, passed by sshd2 in compat mode. if != NULL,
+ * sshd will skip the version-number exchange
+ */
+char *client_version_string = NULL;
+char *server_version_string = NULL;
+
+/* for rekeying XXX fixme */
+Kex *xxx_kex;
+
+/*
+ * Any really sensitive data in the application is contained in this
+ * structure. The idea is that this structure could be locked into memory so
+ * that the pages do not get written into swap.  However, there are some
+ * problems. The private key contains BIGNUMs, and we do not (in principle)
+ * have access to the internals of them, and locking just the structure is
+ * not very useful.  Currently, memory locking is not implemented.
+ */
+struct {
+       Key     *server_key;            /* ephemeral server key */
+       Key     *ssh1_host_key;         /* ssh1 host key */
+       Key     **host_keys;            /* all private host keys */
+       Key     **host_certificates;    /* all public host certificates */
+       int     have_ssh1_key;
+       int     have_ssh2_key;
+       u_char  ssh1_cookie[SSH_SESSION_KEY_LENGTH];
+} sensitive_data;
+
+/*
+ * Flag indicating whether the RSA server key needs to be regenerated.
+ * Is set in the SIGALRM handler and cleared when the key is regenerated.
+ */
+static volatile sig_atomic_t key_do_regen = 0;
+
+/* This is set to true when a signal is received. */
+static volatile sig_atomic_t received_sighup = 0;
+static volatile sig_atomic_t received_sigterm = 0;
+
+/* session identifier, used by RSA-auth */
+u_char session_id[16];
+
+/* same for ssh2 */
+u_char *session_id2 = NULL;
+u_int session_id2_len = 0;
+
+/* record remote hostname or ip */
+u_int utmp_len = MAXHOSTNAMELEN;
+
+/* options.max_startup sized array of fd ints */
+int *startup_pipes = NULL;
+int startup_pipe;              /* in child */
+
+/* variables used for privilege separation */
+int use_privsep = -1;
+struct monitor *pmonitor = NULL;
+
+/* global authentication context */
+Authctxt *the_authctxt = NULL;
+
+/* sshd_config buffer */
+Buffer cfg;
+
+/* message to be displayed after login */
+Buffer loginmsg;
+
+/* Unprivileged user */
+struct passwd *privsep_pw = NULL;
+
+/* Prototypes for various functions defined later in this file. */
+void destroy_sensitive_data(void);
+void demote_sensitive_data(void);
+
+static void do_ssh1_kex(void);
+static void do_ssh2_kex(void);
+
+/*
+ * Close all listening sockets
+ */
+static void
+close_listen_socks(void)
+{
+       int i;
+
+       for (i = 0; i < num_listen_socks; i++)
+               close(listen_socks[i]);
+       num_listen_socks = -1;
+}
+
+static void
+close_startup_pipes(void)
+{
+       int i;
+
+       if (startup_pipes)
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               close(startup_pipes[i]);
+}
+
+/*
+ * Signal handler for SIGHUP.  Sshd execs itself when it receives SIGHUP;
+ * the effect is to reread the configuration file (and to regenerate
+ * the server key).
+ */
+
+/*ARGSUSED*/
+static void
+sighup_handler(int sig)
+{
+       int save_errno = errno;
+
+       received_sighup = 1;
+       signal(SIGHUP, sighup_handler);
+       errno = save_errno;
+}
+
+/*
+ * Called from the main program after receiving SIGHUP.
+ * Restarts the server.
+ */
+static void
+sighup_restart(void)
+{
+       logit("Received SIGHUP; restarting.");
+       close_listen_socks();
+       close_startup_pipes();
+       alarm(0);  /* alarm timer persists across exec */
+       signal(SIGHUP, SIG_IGN); /* will be restored after exec */
+       execv(saved_argv[0], saved_argv);
+       logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
+           strerror(errno));
+       exit(1);
+}
+
+/*
+ * Generic signal handler for terminating signals in the master daemon.
+ */
+/*ARGSUSED*/
+static void
+sigterm_handler(int sig)
+{
+       received_sigterm = sig;
+}
+
+/*
+ * SIGCHLD handler.  This is called whenever a child dies.  This will then
+ * reap any zombies left by exited children.
+ */
+/*ARGSUSED*/
+static void
+main_sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+           (pid < 0 && errno == EINTR))
+               ;
+
+       signal(SIGCHLD, main_sigchld_handler);
+       errno = save_errno;
+}
+
+/*
+ * Signal handler for the alarm after the login grace period has expired.
+ */
+/*ARGSUSED*/
+static void
+grace_alarm_handler(int sig)
+{
+       if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
+               kill(pmonitor->m_pid, SIGALRM);
+
+       /* Log error and exit. */
+       sigdie("Timeout before authentication for %s", get_remote_ipaddr());
+}
+
+/*
+ * Signal handler for the key regeneration alarm.  Note that this
+ * alarm only occurs in the daemon waiting for connections, and it does not
+ * do anything with the private key or random state before forking.
+ * Thus there should be no concurrency control/asynchronous execution
+ * problems.
+ */
+static void
+generate_ephemeral_server_key(void)
+{
+       verbose("Generating %s%d bit RSA key.",
+           sensitive_data.server_key ? "new " : "", options.server_key_bits);
+       if (sensitive_data.server_key != NULL)
+               key_free(sensitive_data.server_key);
+       sensitive_data.server_key = key_generate(KEY_RSA1,
+           options.server_key_bits);
+       verbose("RSA key generation complete.");
+
+       arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+       arc4random_stir();
+}
+
+/*ARGSUSED*/
+static void
+key_regeneration_alarm(int sig)
+{
+       int save_errno = errno;
+
+       signal(SIGALRM, SIG_DFL);
+       errno = save_errno;
+       key_do_regen = 1;
+}
+
+static void
+sshd_exchange_identification(int sock_in, int sock_out)
+{
+       u_int i;
+       int mismatch;
+       int remote_major, remote_minor;
+       int major, minor;
+       char *s, *newline = "\n";
+       char buf[256];                  /* Must not be larger than remote_version. */
+       char remote_version[256];       /* Must be at least as big as buf. */
+
+       if ((options.protocol & SSH_PROTO_1) &&
+           (options.protocol & SSH_PROTO_2)) {
+               major = PROTOCOL_MAJOR_1;
+               minor = 99;
+       } else if (options.protocol & SSH_PROTO_2) {
+               major = PROTOCOL_MAJOR_2;
+               minor = PROTOCOL_MINOR_2;
+               newline = "\r\n";
+       } else {
+               major = PROTOCOL_MAJOR_1;
+               minor = PROTOCOL_MINOR_1;
+       }
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+           SSH_VERSION, newline);
+       server_version_string = xstrdup(buf);
+
+       /* Send our protocol version identification. */
+       if (roaming_atomicio(vwrite, sock_out, server_version_string,
+           strlen(server_version_string))
+           != strlen(server_version_string)) {
+               logit("Could not write ident string to %s", get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+
+       /* Read other sides version identification. */
+       memset(buf, 0, sizeof(buf));
+       for (i = 0; i < sizeof(buf) - 1; i++) {
+               if (roaming_atomicio(read, sock_in, &buf[i], 1) != 1) {
+                       logit("Did not receive identification string from %s",
+                           get_remote_ipaddr());
+                       cleanup_exit(255);
+               }
+               if (buf[i] == '\r') {
+                       buf[i] = 0;
+                       /* Kludge for F-Secure Macintosh < 1.0.2 */
+                       if (i == 12 &&
+                           strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
+                               break;
+                       continue;
+               }
+               if (buf[i] == '\n') {
+                       buf[i] = 0;
+                       break;
+               }
+       }
+       buf[sizeof(buf) - 1] = 0;
+       client_version_string = xstrdup(buf);
+
+       /*
+        * Check that the versions match.  In future this might accept
+        * several versions and set appropriate flags to handle them.
+        */
+       if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
+           &remote_major, &remote_minor, remote_version) != 3) {
+               s = "Protocol mismatch.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Bad protocol version identification '%.100s' from %s",
+                   client_version_string, get_remote_ipaddr());
+               cleanup_exit(255);
+       }
+       debug("Client protocol version %d.%d; client software version %.100s",
+           remote_major, remote_minor, remote_version);
+
+       compat_datafellows(remote_version);
+
+       if (datafellows & SSH_BUG_PROBE) {
+               logit("probed from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       if (datafellows & SSH_BUG_SCANNER) {
+               logit("scanned from %s with %s.  Don't panic.",
+                   get_remote_ipaddr(), client_version_string);
+               cleanup_exit(255);
+       }
+
+       mismatch = 0;
+       switch (remote_major) {
+       case 1:
+               if (remote_minor == 99) {
+                       if (options.protocol & SSH_PROTO_2)
+                               enable_compat20();
+                       else
+                               mismatch = 1;
+                       break;
+               }
+               if (!(options.protocol & SSH_PROTO_1)) {
+                       mismatch = 1;
+                       break;
+               }
+               if (remote_minor < 3) {
+                       packet_disconnect("Your ssh version is too old and "
+                           "is no longer supported.  Please install a newer version.");
+               } else if (remote_minor == 3) {
+                       /* note that this disables agent-forwarding */
+                       enable_compat13();
+               }
+               break;
+       case 2:
+               if (options.protocol & SSH_PROTO_2) {
+                       enable_compat20();
+                       break;
+               }
+               /* FALLTHROUGH */
+       default:
+               mismatch = 1;
+               break;
+       }
+       chop(server_version_string);
+       debug("Local version string %.200s", server_version_string);
+
+       if (mismatch) {
+               s = "Protocol major versions differ.\n";
+               (void) atomicio(vwrite, sock_out, s, strlen(s));
+               close(sock_in);
+               close(sock_out);
+               logit("Protocol major versions differ for %s: %.200s vs. %.200s",
+                   get_remote_ipaddr(),
+                   server_version_string, client_version_string);
+               cleanup_exit(255);
+       }
+}
+
+/* Destroy the host and server keys.  They will no longer be needed. */
+void
+destroy_sensitive_data(void)
+{
+       int i;
+
+       if (sensitive_data.server_key) {
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = NULL;
+       }
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = NULL;
+               }
+               if (sensitive_data.host_certificates[i]) {
+                       key_free(sensitive_data.host_certificates[i]);
+                       sensitive_data.host_certificates[i] = NULL;
+               }
+       }
+       sensitive_data.ssh1_host_key = NULL;
+       memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH);
+}
+
+/* Demote private to public keys for network child */
+void
+demote_sensitive_data(void)
+{
+       Key *tmp;
+       int i;
+
+       if (sensitive_data.server_key) {
+               tmp = key_demote(sensitive_data.server_key);
+               key_free(sensitive_data.server_key);
+               sensitive_data.server_key = tmp;
+       }
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (sensitive_data.host_keys[i]) {
+                       tmp = key_demote(sensitive_data.host_keys[i]);
+                       key_free(sensitive_data.host_keys[i]);
+                       sensitive_data.host_keys[i] = tmp;
+                       if (tmp->type == KEY_RSA1)
+                               sensitive_data.ssh1_host_key = tmp;
+               }
+               /* Certs do not need demotion */
+       }
+
+       /* We do not clear ssh1_host key and cookie.  XXX - Okay Niels? */
+}
+
+static void
+privsep_preauth_child(void)
+{
+       u_int32_t rnd[256];
+       gid_t gidset[1];
+
+       /* Enable challenge-response authentication for privilege separation */
+       privsep_challenge_enable();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       /* Change our root directory */
+       if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
+               fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
+                   strerror(errno));
+       if (chdir("/") == -1)
+               fatal("chdir(\"/\"): %s", strerror(errno));
+
+       /* Drop our privileges */
+       debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
+           (u_int)privsep_pw->pw_gid);
+#if 0
+       /* XXX not ready, too heavy after chroot */
+       do_setusercontext(privsep_pw);
+#else
+       gidset[0] = privsep_pw->pw_gid;
+       if (setgroups(1, gidset) < 0)
+               fatal("setgroups: %.100s", strerror(errno));
+       permanently_set_uid(privsep_pw);
+#endif
+}
+
+static int
+privsep_preauth(Authctxt *authctxt)
+{
+       int status;
+       pid_t pid;
+       struct ssh_sandbox *box = NULL;
+
+       /* Set up unprivileged child process to deal with network data */
+       pmonitor = monitor_init();
+       /* Store a pointer to the kex for later rekeying */
+       pmonitor->m_pkex = &xxx_kex;
+
+       if (use_privsep == PRIVSEP_SANDBOX)
+               box = ssh_sandbox_init();
+       pid = fork();
+       if (pid == -1) {
+               fatal("fork of unprivileged child failed");
+       } else if (pid != 0) {
+               debug2("Network child is on pid %ld", (long)pid);
+
+               if (box != NULL)
+                       ssh_sandbox_parent_preauth(box, pid);
+               pmonitor->m_pid = pid;
+               monitor_child_preauth(authctxt, pmonitor);
+
+               /* Sync memory */
+               monitor_sync(pmonitor);
+
+               /* Wait for the child's exit status */
+               while (waitpid(pid, &status, 0) < 0) {
+                       if (errno != EINTR)
+                               fatal("%s: waitpid: %s", __func__,
+                                   strerror(errno));
+               }
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status) != 0)
+                               fatal("%s: preauth child exited with status %d",
+                                   __func__, WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status))
+                       fatal("%s: preauth child terminated by signal %d",
+                           __func__, WTERMSIG(status));
+               if (box != NULL)
+                       ssh_sandbox_parent_finish(box);
+               return 1;
+       } else {
+               /* child */
+               close(pmonitor->m_sendfd);
+               close(pmonitor->m_log_recvfd);
+
+               /* Arrange for logging to be sent to the monitor */
+               set_log_handler(mm_log_handler, pmonitor);
+
+               /* Demote the child */
+               if (getuid() == 0 || geteuid() == 0)
+                       privsep_preauth_child();
+               setproctitle("%s", "[net]");
+               if (box != NULL)
+                       ssh_sandbox_child(box);
+
+               return 0;
+       }
+}
+
+static void
+privsep_postauth(Authctxt *authctxt)
+{
+       u_int32_t rnd[256];
+
+#ifdef DISABLE_FD_PASSING
+       if (1) {
+#else
+       if (authctxt->pw->pw_uid == 0 || options.use_login) {
+#endif
+               /* File descriptor passing is broken or root login */
+               use_privsep = 0;
+               goto skip;
+       }
+
+       /* New socket pair */
+       monitor_reinit(pmonitor);
+
+       pmonitor->m_pid = fork();
+       if (pmonitor->m_pid == -1)
+               fatal("fork of unprivileged child failed");
+       else if (pmonitor->m_pid != 0) {
+               verbose("User child is on pid %ld", (long)pmonitor->m_pid);
+               buffer_clear(&loginmsg);
+               monitor_child_postauth(pmonitor);
+
+               /* NEVERREACHED */
+               exit(0);
+       }
+
+       /* child */
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
+
+       /* Demote the private keys to public keys. */
+       demote_sensitive_data();
+
+       arc4random_stir();
+       arc4random_buf(rnd, sizeof(rnd));
+       RAND_seed(rnd, sizeof(rnd));
+
+       /* Drop privileges */
+       do_setusercontext(authctxt->pw, authctxt->role);
+
+ skip:
+       /* It is safe now to apply the key state */
+       monitor_apply_keystate(pmonitor);
+
+       /*
+        * Tell the packet layer that authentication was successful, since
+        * this information is not part of the key state.
+        */
+       packet_set_authenticated();
+}
+
+static char *
+list_hostkey_types(void)
+{
+       Buffer b;
+       const char *p;
+       char *ret;
+       int i;
+       Key *key;
+
+       buffer_init(&b);
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = sensitive_data.host_keys[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+               /* If the private key has a cert peer, then list that too */
+               key = sensitive_data.host_certificates[i];
+               if (key == NULL)
+                       continue;
+               switch (key->type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       p = key_ssh_name(key);
+                       buffer_append(&b, p, strlen(p));
+                       break;
+               }
+       }
+       buffer_append(&b, "\0", 1);
+       ret = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
+       debug("list_hostkey_types: %s", ret);
+       return ret;
+}
+
+static Key *
+get_hostkey_by_type(int type, int need_private)
+{
+       int i;
+       Key *key;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               switch (type) {
+               case KEY_RSA_CERT_V00:
+               case KEY_DSA_CERT_V00:
+               case KEY_RSA_CERT:
+               case KEY_DSA_CERT:
+               case KEY_ECDSA_CERT:
+                       key = sensitive_data.host_certificates[i];
+                       break;
+               default:
+                       key = sensitive_data.host_keys[i];
+                       break;
+               }
+               if (key != NULL && key->type == type)
+                       return need_private ?
+                           sensitive_data.host_keys[i] : key;
+       }
+       return NULL;
+}
+
+Key *
+get_hostkey_public_by_type(int type)
+{
+       return get_hostkey_by_type(type, 0);
+}
+
+Key *
+get_hostkey_private_by_type(int type)
+{
+       return get_hostkey_by_type(type, 1);
+}
+
+Key *
+get_hostkey_by_index(int ind)
+{
+       if (ind < 0 || ind >= options.num_host_key_files)
+               return (NULL);
+       return (sensitive_data.host_keys[ind]);
+}
+
+int
+get_hostkey_index(Key *key)
+{
+       int i;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               if (key_is_cert(key)) {
+                       if (key == sensitive_data.host_certificates[i])
+                               return (i);
+               } else {
+                       if (key == sensitive_data.host_keys[i])
+                               return (i);
+               }
+       }
+       return (-1);
+}
+
+/*
+ * returns 1 if connection should be dropped, 0 otherwise.
+ * dropping starts at connection #max_startups_begin with a probability
+ * of (max_startups_rate/100). the probability increases linearly until
+ * all connections are dropped for startups > max_startups
+ */
+static int
+drop_connection(int startups)
+{
+       int p, r;
+
+       if (startups < options.max_startups_begin)
+               return 0;
+       if (startups >= options.max_startups)
+               return 1;
+       if (options.max_startups_rate == 100)
+               return 1;
+
+       p  = 100 - options.max_startups_rate;
+       p *= startups - options.max_startups_begin;
+       p /= options.max_startups - options.max_startups_begin;
+       p += options.max_startups_rate;
+       r = arc4random_uniform(100);
+
+       debug("drop_connection: p %d, r %d", p, r);
+       return (r < p) ? 1 : 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "%s, %s\n",
+           SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+       fprintf(stderr,
+"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
+"            [-f config_file] [-g login_grace_time] [-h host_key_file]\n"
+"            [-k key_gen_time] [-o option] [-p port] [-u len]\n"
+       );
+       exit(1);
+}
+
+static void
+send_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+
+       debug3("%s: entering fd = %d config len %d", __func__, fd,
+           buffer_len(conf));
+
+       /*
+        * Protocol from reexec master to child:
+        *      string  configuration
+        *      u_int   ephemeral_key_follows
+        *      bignum  e               (only if ephemeral_key_follows == 1)
+        *      bignum  n                       "
+        *      bignum  d                       "
+        *      bignum  iqmp                    "
+        *      bignum  p                       "
+        *      bignum  q                       "
+        *      string rngseed          (only if OpenSSL is not self-seeded)
+        */
+       buffer_init(&m);
+       buffer_put_cstring(&m, buffer_ptr(conf));
+
+       if (sensitive_data.server_key != NULL &&
+           sensitive_data.server_key->type == KEY_RSA1) {
+               buffer_put_int(&m, 1);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
+       } else
+               buffer_put_int(&m, 0);
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_send_rng_seed(&m);
+#endif
+
+       if (ssh_msg_send(fd, 0, &m) == -1)
+               fatal("%s: ssh_msg_send failed", __func__);
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+static void
+recv_rexec_state(int fd, Buffer *conf)
+{
+       Buffer m;
+       char *cp;
+       u_int len;
+
+       debug3("%s: entering fd = %d", __func__, fd);
+
+       buffer_init(&m);
+
+       if (ssh_msg_recv(fd, &m) == -1)
+               fatal("%s: ssh_msg_recv failed", __func__);
+       if (buffer_get_char(&m) != 0)
+               fatal("%s: rexec version mismatch", __func__);
+
+       cp = buffer_get_string(&m, &len);
+       if (conf != NULL)
+               buffer_append(conf, cp, len + 1);
+       xfree(cp);
+
+       if (buffer_get_int(&m)) {
+               if (sensitive_data.server_key != NULL)
+                       key_free(sensitive_data.server_key);
+               sensitive_data.server_key = key_new_private(KEY_RSA1);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->e);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->n);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->d);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
+               buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
+               rsa_generate_additional_parameters(
+                   sensitive_data.server_key->rsa);
+       }
+
+#ifndef OPENSSL_PRNG_ONLY
+       rexec_recv_rng_seed(&m);
+#endif
+
+       buffer_free(&m);
+
+       debug3("%s: done", __func__);
+}
+
+/* Accept a connection from inetd */
+static void
+server_accept_inetd(int *sock_in, int *sock_out)
+{
+       int fd;
+
+       startup_pipe = -1;
+       if (rexeced_flag) {
+               close(REEXEC_CONFIG_PASS_FD);
+               *sock_in = *sock_out = dup(STDIN_FILENO);
+               if (!debug_flag) {
+                       startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+                       close(REEXEC_STARTUP_PIPE_FD);
+               }
+       } else {
+               *sock_in = dup(STDIN_FILENO);
+               *sock_out = dup(STDOUT_FILENO);
+       }
+       /*
+        * We intentionally do not close the descriptors 0, 1, and 2
+        * as our code for setting the descriptors won't work if
+        * ttyfd happens to be one of those.
+        */
+       if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+               dup2(fd, STDIN_FILENO);
+               dup2(fd, STDOUT_FILENO);
+               if (fd > STDOUT_FILENO)
+                       close(fd);
+       }
+       debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
+}
+
+/*
+ * Listen for TCP connections
+ */
+static void
+server_listen(void)
+{
+       int ret, listen_sock, on = 1;
+       struct addrinfo *ai;
+       char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+
+       for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
+               if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                       continue;
+               if (num_listen_socks >= MAX_LISTEN_SOCKS)
+                       fatal("Too many listen sockets. "
+                           "Enlarge MAX_LISTEN_SOCKS");
+               if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
+                   ntop, sizeof(ntop), strport, sizeof(strport),
+                   NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
+                       error("getnameinfo failed: %.100s",
+                           ssh_gai_strerror(ret));
+                       continue;
+               }
+               /* Create socket for listening. */
+               listen_sock = socket(ai->ai_family, ai->ai_socktype,
+                   ai->ai_protocol);
+               if (listen_sock < 0) {
+                       /* kernel may not support ipv6 */
+                       verbose("socket: %.100s", strerror(errno));
+                       continue;
+               }
+               if (set_nonblock(listen_sock) == -1) {
+                       close(listen_sock);
+                       continue;
+               }
+               /*
+                * Set socket options.
+                * Allow local port reuse in TIME_WAIT.
+                */
+               if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
+                   &on, sizeof(on)) == -1)
+                       error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+
+               /* Only communicate in IPv6 over AF_INET6 sockets. */
+               if (ai->ai_family == AF_INET6)
+                       sock_set_v6only(listen_sock);
+
+               debug("Bind to port %s on %s.", strport, ntop);
+
+               /* Bind the socket to the desired port. */
+               if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+                       error("Bind to port %s on %s failed: %.200s.",
+                           strport, ntop, strerror(errno));
+                       close(listen_sock);
+                       continue;
+               }
+               listen_socks[num_listen_socks] = listen_sock;
+               num_listen_socks++;
+
+               /* Start listening on the port. */
+               if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
+                       fatal("listen on [%s]:%s: %.100s",
+                           ntop, strport, strerror(errno));
+               logit("Server listening on %s port %s.", ntop, strport);
+       }
+       freeaddrinfo(options.listen_addrs);
+
+       if (!num_listen_socks)
+               fatal("Cannot bind any address.");
+}
+
+/*
+ * The main TCP accept loop. Note that, for the non-debug case, returns
+ * from this function are in a forked subprocess.
+ */
+static void
+server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
+{
+       fd_set *fdset;
+       int i, j, ret, maxfd;
+       int key_used = 0, startups = 0;
+       int startup_p[2] = { -1 , -1 };
+       struct sockaddr_storage from;
+       socklen_t fromlen;
+       pid_t pid;
+
+       /* setup fd set for accept */
+       fdset = NULL;
+       maxfd = 0;
+       for (i = 0; i < num_listen_socks; i++)
+               if (listen_socks[i] > maxfd)
+                       maxfd = listen_socks[i];
+       /* pipes connected to unauthenticated childs */
+       startup_pipes = xcalloc(options.max_startups, sizeof(int));
+       for (i = 0; i < options.max_startups; i++)
+               startup_pipes[i] = -1;
+
+       /*
+        * Stay listening for connections until the system crashes or
+        * the daemon is killed with a signal.
+        */
+       for (;;) {
+               if (received_sighup)
+                       sighup_restart();
+               if (fdset != NULL)
+                       xfree(fdset);
+               fdset = (fd_set *)xcalloc(howmany(maxfd + 1, NFDBITS),
+                   sizeof(fd_mask));
+
+               for (i = 0; i < num_listen_socks; i++)
+                       FD_SET(listen_socks[i], fdset);
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1)
+                               FD_SET(startup_pipes[i], fdset);
+
+               /* Wait in select until there is a connection. */
+               ret = select(maxfd+1, fdset, NULL, NULL, NULL);
+               if (ret < 0 && errno != EINTR)
+                       error("select: %.100s", strerror(errno));
+               if (received_sigterm) {
+                       logit("Received signal %d; terminating.",
+                           (int) received_sigterm);
+                       close_listen_socks();
+                       unlink(options.pid_file);
+                       exit(received_sigterm == SIGTERM ? 0 : 255);
+               }
+               if (key_used && key_do_regen) {
+                       generate_ephemeral_server_key();
+                       key_used = 0;
+                       key_do_regen = 0;
+               }
+               if (ret < 0)
+                       continue;
+
+               for (i = 0; i < options.max_startups; i++)
+                       if (startup_pipes[i] != -1 &&
+                           FD_ISSET(startup_pipes[i], fdset)) {
+                               /*
+                                * the read end of the pipe is ready
+                                * if the child has closed the pipe
+                                * after successful authentication
+                                * or if the child has died
+                                */
+                               close(startup_pipes[i]);
+                               startup_pipes[i] = -1;
+                               startups--;
+                       }
+               for (i = 0; i < num_listen_socks; i++) {
+                       if (!FD_ISSET(listen_socks[i], fdset))
+                               continue;
+                       fromlen = sizeof(from);
+                       *newsock = accept(listen_socks[i],
+                           (struct sockaddr *)&from, &fromlen);
+                       if (*newsock < 0) {
+                               if (errno != EINTR && errno != EAGAIN &&
+                                   errno != EWOULDBLOCK)
+                                       error("accept: %.100s", strerror(errno));
+                               continue;
+                       }
+                       if (unset_nonblock(*newsock) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+                       if (drop_connection(startups) == 1) {
+                               debug("drop connection #%d", startups);
+                               close(*newsock);
+                               continue;
+                       }
+                       if (pipe(startup_p) == -1) {
+                               close(*newsock);
+                               continue;
+                       }
+
+                       if (rexec_flag && socketpair(AF_UNIX,
+                           SOCK_STREAM, 0, config_s) == -1) {
+                               error("reexec socketpair: %s",
+                                   strerror(errno));
+                               close(*newsock);
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               continue;
+                       }
+
+                       for (j = 0; j < options.max_startups; j++)
+                               if (startup_pipes[j] == -1) {
+                                       startup_pipes[j] = startup_p[0];
+                                       if (maxfd < startup_p[0])
+                                               maxfd = startup_p[0];
+                                       startups++;
+                                       break;
+                               }
+
+                       /*
+                        * Got connection.  Fork a child to handle it, unless
+                        * we are in debugging mode.
+                        */
+                       if (debug_flag) {
+                               /*
+                                * In debugging mode.  Close the listening
+                                * socket, and start processing the
+                                * connection without forking.
+                                */
+                               debug("Server will not fork when running in debugging mode.");
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               close(startup_p[0]);
+                               close(startup_p[1]);
+                               startup_pipe = -1;
+                               pid = getpid();
+                               if (rexec_flag) {
+                                       send_rexec_state(config_s[0],
+                                           &cfg);
+                                       close(config_s[0]);
+                               }
+                               break;
+                       }
+
+                       /*
+                        * Normal production daemon.  Fork, and have
+                        * the child process the connection. The
+                        * parent continues listening.
+                        */
+                       platform_pre_fork();
+                       if ((pid = fork()) == 0) {
+                               /*
+                                * Child.  Close the listening and
+                                * max_startup sockets.  Start using
+                                * the accepted socket. Reinitialize
+                                * logging (since our pid has changed).
+                                * We break out of the loop to handle
+                                * the connection.
+                                */
+                               platform_post_fork_child();
+                               startup_pipe = startup_p[1];
+                               close_startup_pipes();
+                               close_listen_socks();
+                               *sock_in = *newsock;
+                               *sock_out = *newsock;
+                               log_init(__progname,
+                                   options.log_level,
+                                   options.log_facility,
+                                   log_stderr);
+                               if (rexec_flag)
+                                       close(config_s[0]);
+                               break;
+                       }
+
+                       /* Parent.  Stay in the loop. */
+                       platform_post_fork_parent(pid);
+                       if (pid < 0)
+                               error("fork: %.100s", strerror(errno));
+                       else
+                               debug("Forked child %ld.", (long)pid);
+
+                       close(startup_p[1]);
+
+                       if (rexec_flag) {
+                               send_rexec_state(config_s[0], &cfg);
+                               close(config_s[0]);
+                               close(config_s[1]);
+                       }
+
+                       /*
+                        * Mark that the key has been used (it
+                        * was "given" to the child).
+                        */
+                       if ((options.protocol & SSH_PROTO_1) &&
+                           key_used == 0) {
+                               /* Schedule server key regeneration alarm. */
+                               signal(SIGALRM, key_regeneration_alarm);
+                               alarm(options.key_regeneration_time);
+                               key_used = 1;
+                       }
+
+                       close(*newsock);
+
+                       /*
+                        * Ensure that our random state differs
+                        * from that of the child
+                        */
+                       arc4random_stir();
+               }
+
+               /* child process check (or debug mode) */
+               if (num_listen_socks < 0)
+                       break;
+       }
+}
+
+
+/*
+ * Main program for the daemon.
+ */
+int
+main(int ac, char **av)
+{
+       extern char *optarg;
+       extern int optind;
+       int opt, i, j, on = 1;
+       int sock_in = -1, sock_out = -1, newsock = -1;
+       const char *remote_ip;
+       char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
+       int remote_port;
+       char *line, *p, *cp;
+       int config_s[2] = { -1 , -1 };
+       u_int64_t ibytes, obytes;
+       mode_t new_umask;
+       Key *key;
+       Authctxt *authctxt;
+
+#ifdef HAVE_SECUREWARE
+       (void)set_auth_parameters(ac, av);
+#endif
+       __progname = ssh_get_progname(av[0]);
+
+       /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
+       saved_argc = ac;
+       rexec_argc = ac;
+       saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
+       for (i = 0; i < ac; i++)
+               saved_argv[i] = xstrdup(av[i]);
+       saved_argv[i] = NULL;
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       compat_init_setproctitle(ac, av);
+       av = saved_argv;
+#endif
+
+       if (geteuid() == 0 && setgroups(0, NULL) == -1)
+               debug("setgroups(): %.200s", strerror(errno));
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       /* Initialize configuration options to their default values. */
+       initialize_server_options(&options);
+
+       /* Parse command-line arguments. */
+       while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) {
+               switch (opt) {
+               case '4':
+                       options.address_family = AF_INET;
+                       break;
+               case '6':
+                       options.address_family = AF_INET6;
+                       break;
+               case 'f':
+                       config_file_name = optarg;
+                       break;
+               case 'c':
+                       if (options.num_host_cert_files >= MAX_HOSTCERTS) {
+                               fprintf(stderr, "too many host certificates.\n");
+                               exit(1);
+                       }
+                       options.host_cert_files[options.num_host_cert_files++] =
+                          derelativise_path(optarg);
+                       break;
+               case 'd':
+                       if (debug_flag == 0) {
+                               debug_flag = 1;
+                               options.log_level = SYSLOG_LEVEL_DEBUG1;
+                       } else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                               options.log_level++;
+                       break;
+               case 'D':
+                       no_daemon_flag = 1;
+                       break;
+               case 'e':
+                       log_stderr = 1;
+                       break;
+               case 'i':
+                       inetd_flag = 1;
+                       break;
+               case 'r':
+                       rexec_flag = 0;
+                       break;
+               case 'R':
+                       rexeced_flag = 1;
+                       inetd_flag = 1;
+                       break;
+               case 'Q':
+                       /* ignored */
+                       break;
+               case 'q':
+                       options.log_level = SYSLOG_LEVEL_QUIET;
+                       break;
+               case 'b':
+                       options.server_key_bits = (int)strtonum(optarg, 256,
+                           32768, NULL);
+                       break;
+               case 'p':
+                       options.ports_from_cmdline = 1;
+                       if (options.num_ports >= MAX_PORTS) {
+                               fprintf(stderr, "too many ports.\n");
+                               exit(1);
+                       }
+                       options.ports[options.num_ports++] = a2port(optarg);
+                       if (options.ports[options.num_ports-1] <= 0) {
+                               fprintf(stderr, "Bad port number.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'g':
+                       if ((options.login_grace_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid login grace time.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'k':
+                       if ((options.key_regeneration_time = convtime(optarg)) == -1) {
+                               fprintf(stderr, "Invalid key regeneration interval.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'h':
+                       if (options.num_host_key_files >= MAX_HOSTKEYS) {
+                               fprintf(stderr, "too many host keys.\n");
+                               exit(1);
+                       }
+                       options.host_key_files[options.num_host_key_files++] = 
+                          derelativise_path(optarg);
+                       break;
+               case 't':
+                       test_flag = 1;
+                       break;
+               case 'T':
+                       test_flag = 2;
+                       break;
+               case 'C':
+                       cp = optarg;
+                       while ((p = strsep(&cp, ",")) && *p != '\0') {
+                               if (strncmp(p, "addr=", 5) == 0)
+                                       test_addr = xstrdup(p + 5);
+                               else if (strncmp(p, "host=", 5) == 0)
+                                       test_host = xstrdup(p + 5);
+                               else if (strncmp(p, "user=", 5) == 0)
+                                       test_user = xstrdup(p + 5);
+                               else {
+                                       fprintf(stderr, "Invalid test "
+                                           "mode specification %s\n", p);
+                                       exit(1);
+                               }
+                       }
+                       break;
+               case 'u':
+                       utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
+                       if (utmp_len > MAXHOSTNAMELEN) {
+                               fprintf(stderr, "Invalid utmp length.\n");
+                               exit(1);
+                       }
+                       break;
+               case 'o':
+                       line = xstrdup(optarg);
+                       if (process_server_config_line(&options, line,
+                           "command-line", 0, NULL, NULL, NULL, NULL) != 0)
+                               exit(1);
+                       xfree(line);
+                       break;
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+       }
+       if (rexeced_flag || inetd_flag)
+               rexec_flag = 0;
+       if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
+               fatal("sshd re-exec requires execution with an absolute path");
+       if (rexeced_flag)
+               closefrom(REEXEC_MIN_FREE_FD);
+       else
+               closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
+
+       OpenSSL_add_all_algorithms();
+
+       /*
+        * Force logging to stderr until we have loaded the private host
+        * key (unless started from inetd)
+        */
+       log_init(__progname,
+           options.log_level == SYSLOG_LEVEL_NOT_SET ?
+           SYSLOG_LEVEL_INFO : options.log_level,
+           options.log_facility == SYSLOG_FACILITY_NOT_SET ?
+           SYSLOG_FACILITY_AUTH : options.log_facility,
+           log_stderr || !inetd_flag);
+
+       /*
+        * Unset KRB5CCNAME, otherwise the user's session may inherit it from
+        * root's environment
+        */
+       if (getenv("KRB5CCNAME") != NULL)
+               unsetenv("KRB5CCNAME");
+
+#ifdef _UNICOS
+       /* Cray can define user privs drop all privs now!
+        * Not needed on PRIV_SU systems!
+        */
+       drop_cray_privs();
+#endif
+
+       sensitive_data.server_key = NULL;
+       sensitive_data.ssh1_host_key = NULL;
+       sensitive_data.have_ssh1_key = 0;
+       sensitive_data.have_ssh2_key = 0;
+
+       /*
+        * If we're doing an extended config test, make sure we have all of
+        * the parameters we need.  If we're not doing an extended test,
+        * do not silently ignore connection test params.
+        */
+       if (test_flag >= 2 &&
+          (test_user != NULL || test_host != NULL || test_addr != NULL)
+           && (test_user == NULL || test_host == NULL || test_addr == NULL))
+               fatal("user, host and addr are all required when testing "
+                  "Match configs");
+       if (test_flag < 2 && (test_user != NULL || test_host != NULL ||
+           test_addr != NULL))
+               fatal("Config test connection parameter (-C) provided without "
+                  "test mode (-T)");
+
+       /* Fetch our configuration */
+       buffer_init(&cfg);
+       if (rexeced_flag)
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
+       else
+               load_server_config(config_file_name, &cfg);
+
+       parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
+           &cfg, NULL, NULL, NULL);
+
+       seed_rng();
+
+       /* Fill in default values for those options not explicitly set. */
+       fill_default_server_options(&options);
+
+       /* challenge-response is implemented via keyboard interactive */
+       if (options.challenge_response_authentication)
+               options.kbd_interactive_authentication = 1;
+
+       /* set default channel AF */
+       channel_set_af(options.address_family);
+
+       /* Check that there are no remaining arguments. */
+       if (optind < ac) {
+               fprintf(stderr, "Extra argument %s.\n", av[optind]);
+               exit(1);
+       }
+
+       debug("sshd version %.100s", SSH_RELEASE);
+
+       /* Store privilege separation user for later use if required. */
+       if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
+               if (use_privsep || options.kerberos_authentication)
+                       fatal("Privilege separation user %s does not exist",
+                           SSH_PRIVSEP_USER);
+       } else {
+               memset(privsep_pw->pw_passwd, 0, strlen(privsep_pw->pw_passwd));
+               privsep_pw = pwcopy(privsep_pw);
+               xfree(privsep_pw->pw_passwd);
+               privsep_pw->pw_passwd = xstrdup("*");
+       }
+       endpwent();
+
+       /* load private host keys */
+       sensitive_data.host_keys = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_keys[i] = NULL;
+
+       for (i = 0; i < options.num_host_key_files; i++) {
+               key = key_load_private(options.host_key_files[i], "", NULL);
+               sensitive_data.host_keys[i] = key;
+               if (key == NULL) {
+                       error("Could not load host key: %s",
+                           options.host_key_files[i]);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
+               switch (key->type) {
+               case KEY_RSA1:
+                       sensitive_data.ssh1_host_key = key;
+                       sensitive_data.have_ssh1_key = 1;
+                       break;
+               case KEY_RSA:
+               case KEY_DSA:
+               case KEY_ECDSA:
+                       sensitive_data.have_ssh2_key = 1;
+                       break;
+               }
+               debug("private host key: #%d type %d %s", i, key->type,
+                   key_type(key));
+       }
+       if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
+               logit("Disabling protocol version 1. Could not load host key");
+               options.protocol &= ~SSH_PROTO_1;
+       }
+#ifndef GSSAPI
+       /* The GSSAPI key exchange can run without a host key */
+       if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
+               logit("Disabling protocol version 2. Could not load host key");
+               options.protocol &= ~SSH_PROTO_2;
+       }
+#endif
+       if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+               logit("sshd: no hostkeys available -- exiting.");
+               exit(1);
+       }
+
+       /*
+        * Load certificates. They are stored in an array at identical
+        * indices to the public keys that they relate to.
+        */
+       sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
+           sizeof(Key *));
+       for (i = 0; i < options.num_host_key_files; i++)
+               sensitive_data.host_certificates[i] = NULL;
+
+       for (i = 0; i < options.num_host_cert_files; i++) {
+               key = key_load_public(options.host_cert_files[i], NULL);
+               if (key == NULL) {
+                       error("Could not load host certificate: %s",
+                           options.host_cert_files[i]);
+                       continue;
+               }
+               if (!key_is_cert(key)) {
+                       error("Certificate file is not a certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               /* Find matching private key */
+               for (j = 0; j < options.num_host_key_files; j++) {
+                       if (key_equal_public(key,
+                           sensitive_data.host_keys[j])) {
+                               sensitive_data.host_certificates[j] = key;
+                               break;
+                       }
+               }
+               if (j >= options.num_host_key_files) {
+                       error("No matching private key for certificate: %s",
+                           options.host_cert_files[i]);
+                       key_free(key);
+                       continue;
+               }
+               sensitive_data.host_certificates[j] = key;
+               debug("host certificate: #%d type %d %s", j, key->type,
+                   key_type(key));
+       }
+       /* Check certain values for sanity. */
+       if (options.protocol & SSH_PROTO_1) {
+               if (options.server_key_bits < 512 ||
+                   options.server_key_bits > 32768) {
+                       fprintf(stderr, "Bad server key size.\n");
+                       exit(1);
+               }
+               /*
+                * Check that server and host key lengths differ sufficiently. This
+                * is necessary to make double encryption work with rsaref. Oh, I
+                * hate software patents. I dont know if this can go? Niels
+                */
+               if (options.server_key_bits >
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -
+                   SSH_KEY_BITS_RESERVED && options.server_key_bits <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       options.server_key_bits =
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                           SSH_KEY_BITS_RESERVED;
+                       debug("Forcing server key to %d bits to make it differ from host key.",
+                           options.server_key_bits);
+               }
+       }
+
+       if (use_privsep) {
+               struct stat st;
+
+               if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
+                   (S_ISDIR(st.st_mode) == 0))
+                       fatal("Missing privilege separation directory: %s",
+                           _PATH_PRIVSEP_CHROOT_DIR);
+
+#ifdef HAVE_CYGWIN
+               if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) &&
+                   (st.st_uid != getuid () ||
+                   (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
+#else
+               if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
+#endif
+                       fatal("%s must be owned by root and not group or "
+                           "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
+       }
+
+       if (test_flag > 1) {
+               if (test_user != NULL && test_addr != NULL && test_host != NULL)
+                       parse_server_match_config(&options, test_user,
+                           test_host, test_addr);
+               dump_config(&options);
+       }
+
+       /* Configuration looks good, so exit if in test mode. */
+       if (test_flag)
+               exit(0);
+
+       /*
+        * Clear out any supplemental groups we may have inherited.  This
+        * prevents inadvertent creation of files with bad modes (in the
+        * portable version at least, it's certainly possible for PAM
+        * to create a file, and we can't control the code in every
+        * module which might be used).
+        */
+       if (setgroups(0, NULL) < 0)
+               debug("setgroups() failed: %.200s", strerror(errno));
+
+       if (rexec_flag) {
+               rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *));
+               for (i = 0; i < rexec_argc; i++) {
+                       debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
+                       rexec_argv[i] = saved_argv[i];
+               }
+               rexec_argv[rexec_argc] = "-R";
+               rexec_argv[rexec_argc + 1] = NULL;
+       }
+
+       /* Ensure that umask disallows at least group and world write */
+       new_umask = umask(0077) | 0022;
+       (void) umask(new_umask);
+
+       /* Initialize the log (it is reinitialized below in case we forked). */
+       if (debug_flag && (!inetd_flag || rexeced_flag))
+               log_stderr = 1;
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /*
+        * If not in debugging mode, and not started from inetd, disconnect
+        * from the controlling terminal, and fork.  The original process
+        * exits.
+        */
+       if (!(debug_flag || inetd_flag || no_daemon_flag)) {
+#ifdef TIOCNOTTY
+               int fd;
+#endif /* TIOCNOTTY */
+               if (daemon(0, 0) < 0)
+                       fatal("daemon() failed: %.200s", strerror(errno));
+
+               /* Disconnect from the controlling tty. */
+#ifdef TIOCNOTTY
+               fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
+               if (fd >= 0) {
+                       (void) ioctl(fd, TIOCNOTTY, NULL);
+                       close(fd);
+               }
+#endif /* TIOCNOTTY */
+       }
+       /* Reinitialize the log (because of the fork above). */
+       log_init(__progname, options.log_level, options.log_facility, log_stderr);
+
+       /* Initialize the random number generator. */
+       arc4random_stir();
+
+       /* Chdir to the root directory so that the current disk can be
+          unmounted if desired. */
+       chdir("/");
+
+       /* ignore SIGPIPE */
+       signal(SIGPIPE, SIG_IGN);
+
+       /* Get a connection, either from inetd or a listening TCP socket */
+       if (inetd_flag) {
+               server_accept_inetd(&sock_in, &sock_out);
+       } else {
+               platform_pre_listen();
+               server_listen();
+
+               if (options.protocol & SSH_PROTO_1)
+                       generate_ephemeral_server_key();
+
+               signal(SIGHUP, sighup_handler);
+               signal(SIGCHLD, main_sigchld_handler);
+               signal(SIGTERM, sigterm_handler);
+               signal(SIGQUIT, sigterm_handler);
+
+               /*
+                * Write out the pid file after the sigterm handler
+                * is setup and the listen sockets are bound
+                */
+               if (!debug_flag) {
+                       FILE *f = fopen(options.pid_file, "w");
+
+                       if (f == NULL) {
+                               error("Couldn't create pid file \"%s\": %s",
+                                   options.pid_file, strerror(errno));
+                       } else {
+                               fprintf(f, "%ld\n", (long) getpid());
+                               fclose(f);
+                       }
+               }
+
+               /* Accept a connection and return in a forked child */
+               server_accept_loop(&sock_in, &sock_out,
+                   &newsock, config_s);
+       }
+
+       /* This is the child processing a new connection. */
+       setproctitle("%s", "[accepted]");
+
+       /*
+        * Create a new session and process group since the 4.4BSD
+        * setlogin() affects the entire process group.  We don't
+        * want the child to be able to affect the parent.
+        */
+#if !defined(SSHD_ACQUIRES_CTTY)
+       /*
+        * If setsid is called, on some platforms sshd will later acquire a
+        * controlling terminal which will result in "could not set
+        * controlling tty" errors.
+        */
+       if (!debug_flag && !inetd_flag && setsid() < 0)
+               error("setsid: %.100s", strerror(errno));
+#endif
+
+       if (rexec_flag) {
+               int fd;
+
+               debug("rexec start in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+               dup2(newsock, STDIN_FILENO);
+               dup2(STDIN_FILENO, STDOUT_FILENO);
+               if (startup_pipe == -1)
+                       close(REEXEC_STARTUP_PIPE_FD);
+               else
+                       dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
+
+               dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
+               close(config_s[1]);
+               if (startup_pipe != -1)
+                       close(startup_pipe);
+
+               execv(rexec_argv[0], rexec_argv);
+
+               /* Reexec has failed, fall back and continue */
+               error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
+               recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
+               log_init(__progname, options.log_level,
+                   options.log_facility, log_stderr);
+
+               /* Clean up fds */
+               startup_pipe = REEXEC_STARTUP_PIPE_FD;
+               close(config_s[1]);
+               close(REEXEC_CONFIG_PASS_FD);
+               newsock = sock_out = sock_in = dup(STDIN_FILENO);
+               if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       if (fd > STDERR_FILENO)
+                               close(fd);
+               }
+               debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
+                   sock_in, sock_out, newsock, startup_pipe, config_s[0]);
+       }
+
+       /* Executed child processes don't need these. */
+       fcntl(sock_out, F_SETFD, FD_CLOEXEC);
+       fcntl(sock_in, F_SETFD, FD_CLOEXEC);
+
+       /*
+        * Disable the key regeneration alarm.  We will not regenerate the
+        * key since we are no longer in a position to give it to anyone. We
+        * will not restart on SIGHUP since it no longer makes sense.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       signal(SIGHUP, SIG_DFL);
+       signal(SIGTERM, SIG_DFL);
+       signal(SIGQUIT, SIG_DFL);
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGINT, SIG_DFL);
+
+       /*
+        * Register our connection.  This turns encryption off because we do
+        * not have a key.
+        */
+       packet_set_connection(sock_in, sock_out);
+       packet_set_server();
+
+       /* Set SO_KEEPALIVE if requested. */
+       if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
+           setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
+               error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+
+       if ((remote_port = get_remote_port()) < 0) {
+               debug("get_remote_port failed");
+               cleanup_exit(255);
+       }
+
+       /*
+        * We use get_canonical_hostname with usedns = 0 instead of
+        * get_remote_ipaddr here so IP options will be checked.
+        */
+       (void) get_canonical_hostname(0);
+       /*
+        * The rest of the code depends on the fact that
+        * get_remote_ipaddr() caches the remote ip, even if
+        * the socket goes away.
+        */
+       remote_ip = get_remote_ipaddr();
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_connection_from(remote_ip, remote_port);
+#endif
+#ifdef LIBWRAP
+       allow_severity = options.log_facility|LOG_INFO;
+       deny_severity = options.log_facility|LOG_WARNING;
+       /* Check whether logins are denied from this host. */
+       if (packet_connection_is_on_socket()) {
+               struct request_info req;
+
+               request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
+               fromhost(&req);
+
+               if (!hosts_access(&req)) {
+                       debug("Connection refused by tcp wrapper");
+                       refuse(&req);
+                       /* NOTREACHED */
+                       fatal("libwrap refuse returns");
+               }
+       }
+#endif /* LIBWRAP */
+
+       /* Log the connection. */
+       verbose("Connection from %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_SECURITY_SESSION_API
+       /*
+        * Create a new security session for use by the new user login if
+        * the current session is the root session or we are not launched
+        * by inetd (eg: debugging mode or server mode).  We do not
+        * necessarily need to create a session if we are launched from
+        * inetd because Panther xinetd will create a session for us.
+        *
+        * The only case where this logic will fail is if there is an
+        * inetd running in a non-root session which is not creating
+        * new sessions for us.  Then all the users will end up in the
+        * same session (bad).
+        *
+        * When the client exits, the session will be destroyed for us
+        * automatically.
+        *
+        * We must create the session before any credentials are stored
+        * (including AFS pags, which happens a few lines below).
+        */
+       {
+               OSStatus err = 0;
+               SecuritySessionId sid = 0;
+               SessionAttributeBits sattrs = 0;
+
+               err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+               if (err)
+                       error("SessionGetInfo() failed with error %.8X",
+                           (unsigned) err);
+               else
+                       debug("Current Session ID is %.8X / Session Attributes are %.8X",
+                           (unsigned) sid, (unsigned) sattrs);
+
+               if (inetd_flag && !(sattrs & sessionIsRoot))
+                       debug("Running in inetd mode in a non-root session... "
+                           "assuming inetd created the session for us.");
+               else {
+                       debug("Creating new security session...");
+                       err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+                       if (err)
+                               error("SessionCreate() failed with error %.8X",
+                                   (unsigned) err);
+
+                       err = SessionGetInfo(callerSecuritySession, &sid, 
+                           &sattrs);
+                       if (err)
+                               error("SessionGetInfo() failed with error %.8X",
+                                   (unsigned) err);
+                       else
+                               debug("New Session ID is %.8X / Session Attributes are %.8X",
+                                   (unsigned) sid, (unsigned) sattrs);
+               }
+       }
+#endif
+
+       /*
+        * We don't want to listen forever unless the other side
+        * successfully authenticates itself.  So we set up an alarm which is
+        * cleared after successful authentication.  A limit of zero
+        * indicates no limit. Note that we don't set the alarm in debugging
+        * mode; it is just annoying to have the server exit just when you
+        * are about to discover the bug.
+        */
+       signal(SIGALRM, grace_alarm_handler);
+       if (!debug_flag)
+               alarm(options.login_grace_time);
+
+       sshd_exchange_identification(sock_in, sock_out);
+
+       /* In inetd mode, generate ephemeral key only for proto 1 connections */
+       if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
+               generate_ephemeral_server_key();
+
+       packet_set_nonblocking();
+
+       /* allocate authentication context */
+       authctxt = xcalloc(1, sizeof(*authctxt));
+
+       authctxt->loginmsg = &loginmsg;
+
+       /* XXX global for cleanup, access from other modules */
+       the_authctxt = authctxt;
+
+       /* prepare buffer to collect messages to display to user after login */
+       buffer_init(&loginmsg);
+       auth_debug_reset();
+
+       if (use_privsep)
+               if (privsep_preauth(authctxt) == 1)
+                       goto authenticated;
+
+       /* perform the key exchange */
+       /* authenticate user and start session */
+       if (compat20) {
+               do_ssh2_kex();
+               do_authentication2(authctxt);
+       } else {
+               do_ssh1_kex();
+               do_authentication(authctxt);
+       }
+       /*
+        * If we use privilege separation, the unprivileged child transfers
+        * the current keystate and exits
+        */
+       if (use_privsep) {
+               mm_send_keystate(pmonitor);
+               exit(0);
+       }
+
+ authenticated:
+       /*
+        * Cancel the alarm we set to limit the time taken for
+        * authentication.
+        */
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       authctxt->authenticated = 1;
+       if (startup_pipe != -1) {
+               close(startup_pipe);
+               startup_pipe = -1;
+       }
+
+#ifdef SSH_AUDIT_EVENTS
+       audit_event(SSH_AUTH_SUCCESS);
+#endif
+
+#ifdef GSSAPI
+       if (options.gss_authentication) {
+               temporarily_use_uid(authctxt->pw);
+               ssh_gssapi_storecreds();
+               restore_uid();
+       }
+#endif
+#ifdef USE_PAM
+       if (options.use_pam) {
+               do_pam_setcred(1);
+               do_pam_session();
+       }
+#endif
+
+       /*
+        * In privilege separation, we fork another child and prepare
+        * file descriptor passing.
+        */
+       if (use_privsep) {
+               privsep_postauth(authctxt);
+               /* the monitor process [priv] will not return */
+               if (!compat20)
+                       destroy_sensitive_data();
+       }
+
+       packet_set_timeout(options.client_alive_interval,
+           options.client_alive_count_max);
+
+       /* Start session. */
+       do_authenticated(authctxt);
+
+       /* The connection has been terminated. */
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes",
+           (unsigned long long)obytes, (unsigned long long)ibytes);
+
+       verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
+
+#ifdef USE_PAM
+       if (options.use_pam)
+               finish_pam();
+#endif /* USE_PAM */
+
+#ifdef SSH_AUDIT_EVENTS
+       PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));
+#endif
+
+       packet_close();
+
+       if (use_privsep)
+               mm_terminate();
+
+       exit(0);
+}
+
+/*
+ * Decrypt session_key_int using our private server key and private host key
+ * (key with larger modulus first).
+ */
+int
+ssh1_session_key(BIGNUM *session_key_int)
+{
+       int rsafail = 0;
+
+       if (BN_cmp(sensitive_data.server_key->rsa->n,
+           sensitive_data.ssh1_host_key->rsa->n) > 0) {
+               /* Server key has bigger modulus. */
+               if (BN_num_bits(sensitive_data.server_key->rsa->n) <
+                   BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) <= 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) <= 0)
+                       rsafail++;
+       } else {
+               /* Host key has bigger modulus (or they are equal). */
+               if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
+                   BN_num_bits(sensitive_data.server_key->rsa->n) +
+                   SSH_KEY_BITS_RESERVED) {
+                       fatal("do_connection: %s: "
+                           "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
+                           get_remote_ipaddr(),
+                           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
+                           BN_num_bits(sensitive_data.server_key->rsa->n),
+                           SSH_KEY_BITS_RESERVED);
+               }
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.ssh1_host_key->rsa) < 0)
+                       rsafail++;
+               if (rsa_private_decrypt(session_key_int, session_key_int,
+                   sensitive_data.server_key->rsa) < 0)
+                       rsafail++;
+       }
+       return (rsafail);
+}
+/*
+ * SSH1 key exchange
+ */
+static void
+do_ssh1_kex(void)
+{
+       int i, len;
+       int rsafail = 0;
+       BIGNUM *session_key_int;
+       u_char session_key[SSH_SESSION_KEY_LENGTH];
+       u_char cookie[8];
+       u_int cipher_type, auth_mask, protocol_flags;
+
+       /*
+        * Generate check bytes that the client must send back in the user
+        * packet in order for it to be accepted; this is used to defy ip
+        * spoofing attacks.  Note that this only works against somebody
+        * doing IP spoofing from a remote machine; any machine on the local
+        * network can still see outgoing packets and catch the random
+        * cookie.  This only affects rhosts authentication, and this is one
+        * of the reasons why it is inherently insecure.
+        */
+       arc4random_buf(cookie, sizeof(cookie));
+
+       /*
+        * Send our public key.  We include in the packet 64 bits of random
+        * data that must be matched in the reply in order to prevent IP
+        * spoofing.
+        */
+       packet_start(SSH_SMSG_PUBLIC_KEY);
+       for (i = 0; i < 8; i++)
+               packet_put_char(cookie[i]);
+
+       /* Store our public server RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
+       packet_put_bignum(sensitive_data.server_key->rsa->e);
+       packet_put_bignum(sensitive_data.server_key->rsa->n);
+
+       /* Store our public host RSA key. */
+       packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
+       packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
+
+       /* Put protocol flags. */
+       packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
+
+       /* Declare which ciphers we support. */
+       packet_put_int(cipher_mask_ssh1(0));
+
+       /* Declare supported authentication types. */
+       auth_mask = 0;
+       if (options.rhosts_rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
+       if (options.rsa_authentication)
+               auth_mask |= 1 << SSH_AUTH_RSA;
+       if (options.challenge_response_authentication == 1)
+               auth_mask |= 1 << SSH_AUTH_TIS;
+       if (options.password_authentication)
+               auth_mask |= 1 << SSH_AUTH_PASSWORD;
+       packet_put_int(auth_mask);
+
+       /* Send the packet and wait for it to be sent. */
+       packet_send();
+       packet_write_wait();
+
+       debug("Sent %d bit server key and %d bit host key.",
+           BN_num_bits(sensitive_data.server_key->rsa->n),
+           BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
+
+       /* Read clients reply (cipher type and session key). */
+       packet_read_expect(SSH_CMSG_SESSION_KEY);
+
+       /* Get cipher type and check whether we accept this. */
+       cipher_type = packet_get_char();
+
+       if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))
+               packet_disconnect("Warning: client selects unsupported cipher.");
+
+       /* Get check bytes from the packet.  These must match those we
+          sent earlier with the public key packet. */
+       for (i = 0; i < 8; i++)
+               if (cookie[i] != packet_get_char())
+                       packet_disconnect("IP Spoofing check bytes do not match.");
+
+       debug("Encryption type: %.200s", cipher_name(cipher_type));
+
+       /* Get the encrypted integer. */
+       if ((session_key_int = BN_new()) == NULL)
+               fatal("do_ssh1_kex: BN_new failed");
+       packet_get_bignum(session_key_int);
+
+       protocol_flags = packet_get_int();
+       packet_set_protocol_flags(protocol_flags);
+       packet_check_eom();
+
+       /* Decrypt session_key_int using host/server keys */
+       rsafail = PRIVSEP(ssh1_session_key(session_key_int));
+
+       /*
+        * Extract session key from the decrypted integer.  The key is in the
+        * least significant 256 bits of the integer; the first byte of the
+        * key is in the highest bits.
+        */
+       if (!rsafail) {
+               (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
+               len = BN_num_bytes(session_key_int);
+               if (len < 0 || (u_int)len > sizeof(session_key)) {
+                       error("do_ssh1_kex: bad session key len from %s: "
+                           "session_key_int %d > sizeof(session_key) %lu",
+                           get_remote_ipaddr(), len, (u_long)sizeof(session_key));
+                       rsafail++;
+               } else {
+                       memset(session_key, 0, sizeof(session_key));
+                       BN_bn2bin(session_key_int,
+                           session_key + sizeof(session_key) - len);
+
+                       derive_ssh1_session_id(
+                           sensitive_data.ssh1_host_key->rsa->n,
+                           sensitive_data.server_key->rsa->n,
+                           cookie, session_id);
+                       /*
+                        * Xor the first 16 bytes of the session key with the
+                        * session id.
+                        */
+                       for (i = 0; i < 16; i++)
+                               session_key[i] ^= session_id[i];
+               }
+       }
+       if (rsafail) {
+               int bytes = BN_num_bytes(session_key_int);
+               u_char *buf = xmalloc(bytes);
+               MD5_CTX md;
+
+               logit("do_connection: generating a fake encryption key");
+               BN_bn2bin(session_key_int, buf);
+               MD5_Init(&md);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key, &md);
+               MD5_Init(&md);
+               MD5_Update(&md, session_key, 16);
+               MD5_Update(&md, buf, bytes);
+               MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
+               MD5_Final(session_key + 16, &md);
+               memset(buf, 0, bytes);
+               xfree(buf);
+               for (i = 0; i < 16; i++)
+                       session_id[i] = session_key[i] ^ session_key[i + 16];
+       }
+       /* Destroy the private and public keys. No longer. */
+       destroy_sensitive_data();
+
+       if (use_privsep)
+               mm_ssh1_session_id(session_id);
+
+       /* Destroy the decrypted integer.  It is no longer needed. */
+       BN_clear_free(session_key_int);
+
+       /* Set the session key.  From this on all communications will be encrypted. */
+       packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);
+
+       /* Destroy our copy of the session key.  It is no longer needed. */
+       memset(session_key, 0, sizeof(session_key));
+
+       debug("Received session key; encryption turned on.");
+
+       /* Send an acknowledgment packet.  Note that this packet is sent encrypted. */
+       packet_start(SSH_SMSG_SUCCESS);
+       packet_send();
+       packet_write_wait();
+}
+
+/*
+ * SSH2 key exchange: diffie-hellman-group1-sha1
+ */
+static void
+do_ssh2_kex(void)
+{
+       Kex *kex;
+
+       if (options.ciphers != NULL) {
+               myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+               myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+       }
+       myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
+       myproposal[PROPOSAL_ENC_ALGS_STOC] =
+           compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
+
+       if (options.macs != NULL) {
+               myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+               myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+       }
+       if (options.compression == COMP_NONE) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
+       } else if (options.compression == COMP_DELAYED) {
+               myproposal[PROPOSAL_COMP_ALGS_CTOS] =
+               myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";
+       }
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+
+       myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
+
+#ifdef GSSAPI
+       {
+       char *orig;
+       char *gss = NULL;
+       char *newstr = NULL;
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+
+       /* 
+        * If we don't have a host key, then there's no point advertising
+        * the other key exchange algorithms
+        */
+
+       if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+               orig = NULL;
+
+       if (options.gss_keyex)
+               gss = ssh_gssapi_server_mechanisms();
+       else
+               gss = NULL;
+
+       if (gss && orig)
+               xasprintf(&newstr, "%s,%s", gss, orig);
+       else if (gss)
+               newstr = gss;
+       else if (orig)
+               newstr = orig;
+
+       /* 
+        * If we've got GSSAPI mechanisms, then we've got the 'null' host
+        * key alg, but we can't tell people about it unless its the only
+        * host key algorithm we support
+        */
+       if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+       if (newstr)
+               myproposal[PROPOSAL_KEX_ALGS] = newstr;
+       else
+               fatal("No supported key exchange algorithms");
+       }
+#endif
+
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
+#endif
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->load_host_public_key=&get_hostkey_public_by_type;
+       kex->load_host_private_key=&get_hostkey_private_by_type;
+       kex->host_key_index=&get_hostkey_index;
+
+       xxx_kex = kex;
+
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+
+       session_id2 = kex->session_id;
+       session_id2_len = kex->session_id_len;
+
+#ifdef DEBUG_KEXDH
+       /* send 1st encrypted/maced/compressed message */
+       packet_start(SSH2_MSG_IGNORE);
+       packet_put_cstring("markus");
+       packet_send();
+       packet_write_wait();
+#endif
+       debug("KEX done");
+}
+
+/* server specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       if (the_authctxt)
+               do_cleanup(the_authctxt);
+#ifdef SSH_AUDIT_EVENTS
+       /* done after do_cleanup so it can cancel the PAM auth 'thread' */
+       if (!use_privsep || mm_is_monitor())
+               audit_event(SSH_CONNECTION_ABANDON);
+#endif
+       _exit(i);
+}
diff --git a/.pc/ssh-vulnkey.patch/sshd_config.5 b/.pc/ssh-vulnkey.patch/sshd_config.5
new file mode 100644 (file)
index 0000000..76c95aa
--- /dev/null
@@ -0,0 +1,1243 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: sshd_config.5,v 1.135 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSHD_CONFIG 5
+.Os
+.Sh NAME
+.Nm sshd_config
+.Nd OpenSSH SSH daemon configuration file
+.Sh SYNOPSIS
+.Nm /etc/ssh/sshd_config
+.Sh DESCRIPTION
+.Xr sshd 8
+reads configuration data from
+.Pa /etc/ssh/sshd_config
+(or the file specified with
+.Fl f
+on the command line).
+The file contains keyword-argument pairs, one per line.
+Lines starting with
+.Ql #
+and empty lines are interpreted as comments.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm AcceptEnv
+Specifies what environment variables sent by the client will be copied into
+the session's
+.Xr environ 7 .
+See
+.Cm SendEnv
+in
+.Xr ssh_config 5
+for how to configure the client.
+Note that environment passing is only supported for protocol 2.
+Variables are specified by name, which may contain the wildcard characters
+.Ql *
+and
+.Ql \&? .
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm AcceptEnv
+directives.
+Be warned that some environment variables could be used to bypass restricted
+user environments.
+For this reason, care should be taken in the use of this directive.
+The default is not to accept any environment variables.
+.It Cm AddressFamily
+Specifies which address family should be used by
+.Xr sshd 8 .
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+The default is
+.Dq any .
+.It Cm AllowAgentForwarding
+Specifies whether
+.Xr ssh-agent 1
+forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling agent forwarding does not improve security
+unless users are also denied shell access, as they can always install
+their own forwarders.
+.It Cm AllowGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+If specified, login is allowed only for users whose primary
+group or supplementary group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AllowTcpForwarding
+Specifies whether TCP forwarding is permitted.
+The default is
+.Dq yes .
+Note that disabling TCP forwarding does not improve security unless
+users are also denied shell access, as they can always install their
+own forwarders.
+.It Cm AllowUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+If specified, login is allowed only for user names that
+match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm AuthorizedKeysFile
+Specifies the file that contains the public keys that can be used
+for user authentication.
+The format is described in the
+.Sx AUTHORIZED_KEYS FILE FORMAT
+section of
+.Xr sshd 8 .
+.Cm AuthorizedKeysFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedKeysFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+Multiple files may be listed, separated by whitespace.
+The default is
+.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
+.It Cm AuthorizedPrincipalsFile
+Specifies a file that lists principal names that are accepted for
+certificate authentication.
+When using certificates signed by a key listed in
+.Cm TrustedUserCAKeys ,
+this file lists names, one of which must appear in the certificate for it
+to be accepted for authentication.
+Names are listed one per line preceded by key options (as described
+in
+.Sx AUTHORIZED_KEYS FILE FORMAT
+in
+.Xr sshd 8 ) .
+Empty lines and comments starting with
+.Ql #
+are ignored.
+.Pp
+.Cm AuthorizedPrincipalsFile
+may contain tokens of the form %T which are substituted during connection
+setup.
+The following tokens are defined: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+After expansion,
+.Cm AuthorizedPrincipalsFile
+is taken to be an absolute path or one relative to the user's home
+directory.
+.Pp
+The default is not to use a principals file \(en in this case, the username
+of the user must appear in a certificate's principals list for it to be
+accepted.
+Note that
+.Cm AuthorizedPrincipalsFile
+is only used when authentication proceeds using a CA listed in
+.Cm TrustedUserCAKeys
+and is not consulted for certification authorities trusted via
+.Pa ~/.ssh/authorized_keys ,
+though the
+.Cm principals=
+key option offers a similar facility (see
+.Xr sshd 8
+for details).
+.It Cm Banner
+The contents of the specified file are sent to the remote user before
+authentication is allowed.
+If the argument is
+.Dq none
+then no banner is displayed.
+This option is only available for protocol version 2.
+By default, no banner is displayed.
+.It Cm ChallengeResponseAuthentication
+Specifies whether challenge-response authentication is allowed (e.g. via
+PAM or though authentication styles supported in
+.Xr login.conf 5 )
+The default is
+.Dq yes .
+.It Cm ChrootDirectory
+Specifies the pathname of a directory to
+.Xr chroot 2
+to after authentication.
+All components of the pathname must be root-owned directories that are
+not writable by any other user or group.
+After the chroot,
+.Xr sshd 8
+changes the working directory to the user's home directory.
+.Pp
+The pathname may contain the following tokens that are expanded at runtime once
+the connecting user has been authenticated: %% is replaced by a literal '%',
+%h is replaced by the home directory of the user being authenticated, and
+%u is replaced by the username of that user.
+.Pp
+The
+.Cm ChrootDirectory
+must contain the necessary files and directories to support the
+user's session.
+For an interactive session this requires at least a shell, typically
+.Xr sh 1 ,
+and basic
+.Pa /dev
+nodes such as
+.Xr null 4 ,
+.Xr zero 4 ,
+.Xr stdin 4 ,
+.Xr stdout 4 ,
+.Xr stderr 4 ,
+.Xr arandom 4
+and
+.Xr tty 4
+devices.
+For file transfer sessions using
+.Dq sftp ,
+no additional configuration of the environment is necessary if the
+in-process sftp server is used,
+though sessions which use logging do require
+.Pa /dev/log
+inside the chroot directory (see
+.Xr sftp-server 8
+for details).
+.Pp
+The default is not to
+.Xr chroot 2 .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClientAliveCountMax
+Sets the number of client alive messages (see below) which may be
+sent without
+.Xr sshd 8
+receiving any messages back from the client.
+If this threshold is reached while client alive messages are being sent,
+sshd will disconnect the client, terminating the session.
+It is important to note that the use of client alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The client alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The client alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If
+.Cm ClientAliveInterval
+(see below) is set to 15, and
+.Cm ClientAliveCountMax
+is left at the default, unresponsive SSH clients
+will be disconnected after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ClientAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the client,
+.Xr sshd 8
+will send a message through the encrypted
+channel to request a response from the client.
+The default
+is 0, indicating that these messages will not be sent to the client.
+This option applies to protocol version 2 only.
+.It Cm Compression
+Specifies whether compression is allowed, or delayed until
+the user has authenticated successfully.
+The argument must be
+.Dq yes ,
+.Dq delayed ,
+or
+.Dq no .
+The default is
+.Dq delayed .
+.It Cm DenyGroups
+This keyword can be followed by a list of group name patterns, separated
+by spaces.
+Login is disallowed for users whose primary group or supplementary
+group list matches one of the patterns.
+Only group names are valid; a numerical group ID is not recognized.
+By default, login is allowed for all groups.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm DenyUsers
+This keyword can be followed by a list of user name patterns, separated
+by spaces.
+Login is disallowed for user names that match one of the patterns.
+Only user names are valid; a numerical user ID is not recognized.
+By default, login is allowed for all users.
+If the pattern takes the form USER@HOST then USER and HOST
+are separately checked, restricting logins to particular
+users from particular hosts.
+The allow/deny directives are processed in the following order:
+.Cm DenyUsers ,
+.Cm AllowUsers ,
+.Cm DenyGroups ,
+and finally
+.Cm AllowGroups .
+.Pp
+See
+.Sx PATTERNS
+in
+.Xr ssh_config 5
+for more information on patterns.
+.It Cm ForceCommand
+Forces the execution of the command specified by
+.Cm ForceCommand ,
+ignoring any command supplied by the client and
+.Pa ~/.ssh/rc
+if present.
+The command is invoked by using the user's login shell with the -c option.
+This applies to shell, command, or subsystem execution.
+It is most useful inside a
+.Cm Match
+block.
+The command originally supplied by the client is available in the
+.Ev SSH_ORIGINAL_COMMAND
+environment variable.
+Specifying a command of
+.Dq internal-sftp
+will force the use of an in-process sftp server that requires no support
+files when used with
+.Cm ChrootDirectory .
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to ports
+forwarded for the client.
+By default,
+.Xr sshd 8
+binds remote port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that sshd
+should allow remote port forwardings to bind to non-loopback addresses, thus
+allowing other hosts to connect.
+The argument may be
+.Dq no
+to force remote port forwardings to be available to the local host only,
+.Dq yes
+to force remote port forwardings to bind to the wildcard address, or
+.Dq clientspecified
+to allow the client to select the address to which the forwarding is bound.
+The default is
+.Dq no .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICleanupCredentials
+Specifies whether to automatically destroy the user's credentials cache
+on logout.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor 
+a client authenticates against. If
+.Dq yes
+then the client must authenticate against the
+.Pa host
+service on the current hostname. If 
+.Dq no
+then the client may authenticate against any service key stored in the 
+machine's default store. This facility is provided to assist with operation 
+on multi homed machines. 
+The default is
+.Dq yes .
+Note that this option applies only to protocol version 2 GSSAPI connections,
+and setting it to 
+.Dq no
+may only work with recent Kerberos GSSAPI libraries.
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
+.Dq no .
+.It Cm HostbasedAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful public key client host authentication is allowed
+(host-based authentication).
+This option is similar to
+.Cm RhostsRSAAuthentication
+and applies to protocol version 2 only.
+The default is
+.Dq no .
+.It Cm HostbasedUsesNameFromPacketOnly
+Specifies whether or not the server will attempt to perform a reverse
+name lookup when matching the name in the
+.Pa ~/.shosts ,
+.Pa ~/.rhosts ,
+and
+.Pa /etc/hosts.equiv
+files during
+.Cm HostbasedAuthentication .
+A setting of
+.Dq yes
+means that
+.Xr sshd 8
+uses the name supplied by the client rather than
+attempting to resolve the name from the TCP connection itself.
+The default is
+.Dq no .
+.It Cm HostCertificate
+Specifies a file containing a public host certificate.
+The certificate's public key must match a private host key already specified
+by
+.Cm HostKey .
+The default behaviour of
+.Xr sshd 8
+is not to load any certificates.
+.It Cm HostKey
+Specifies a file containing a private host key
+used by SSH.
+The default is
+.Pa /etc/ssh/ssh_host_key
+for protocol version 1, and
+.Pa /etc/ssh/ssh_host_dsa_key ,
+.Pa /etc/ssh/ssh_host_ecdsa_key
+and
+.Pa /etc/ssh/ssh_host_rsa_key
+for protocol version 2.
+Note that
+.Xr sshd 8
+will refuse to use a file if it is group/world-accessible.
+It is possible to have multiple host key files.
+.Dq rsa1
+keys are used for version 1 and
+.Dq dsa ,
+.Dq ecdsa
+or
+.Dq rsa
+are used for version 2 of the SSH protocol.
+.It Cm IgnoreRhosts
+Specifies that
+.Pa .rhosts
+and
+.Pa .shosts
+files will not be used in
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+.Pp
+.Pa /etc/hosts.equiv
+and
+.Pa /etc/shosts.equiv
+are still used.
+The default is
+.Dq yes .
+.It Cm IgnoreUserKnownHosts
+Specifies whether
+.Xr sshd 8
+should ignore the user's
+.Pa ~/.ssh/known_hosts
+during
+.Cm RhostsRSAAuthentication
+or
+.Cm HostbasedAuthentication .
+The default is
+.Dq no .
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for the connection.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KerberosAuthentication
+Specifies whether the password provided by the user for
+.Cm PasswordAuthentication
+will be validated through the Kerberos KDC.
+To use this option, the server needs a
+Kerberos servtab which allows the verification of the KDC's identity.
+The default is
+.Dq no .
+.It Cm KerberosGetAFSToken
+If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
+an AFS token before accessing the user's home directory.
+The default is
+.Dq no .
+.It Cm KerberosOrLocalPasswd
+If password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as
+.Pa /etc/passwd .
+The default is
+.Dq yes .
+.It Cm KerberosTicketCleanup
+Specifies whether to automatically destroy the user's ticket cache
+file on logout.
+The default is
+.Dq yes .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is
+.Dq ecdh-sha2-nistp256 ,
+.Dq ecdh-sha2-nistp384 ,
+.Dq ecdh-sha2-nistp521 ,
+.Dq diffie-hellman-group-exchange-sha256 ,
+.Dq diffie-hellman-group-exchange-sha1 ,
+.Dq diffie-hellman-group14-sha1 ,
+.Dq diffie-hellman-group1-sha1 .
+.It Cm KeyRegenerationInterval
+In protocol version 1, the ephemeral server key is automatically regenerated
+after this many seconds (if it has been used).
+The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys.
+The key is never stored anywhere.
+If the value is 0, the key is never regenerated.
+The default is 3600 (seconds).
+.It Cm ListenAddress
+Specifies the local addresses
+.Xr sshd 8
+should listen on.
+The following forms may be used:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Ar host No | Ar IPv4_addr No : Ar port
+.Sm on
+.It
+.Cm ListenAddress
+.Sm off
+.Oo
+.Ar host No | Ar IPv6_addr Oc : Ar port
+.Sm on
+.El
+.Pp
+If
+.Ar port
+is not specified,
+sshd will listen on the address and all prior
+.Cm Port
+options specified.
+The default is to listen on all local addresses.
+Multiple
+.Cm ListenAddress
+options are permitted.
+Additionally, any
+.Cm Port
+options must precede this option for non-port qualified addresses.
+.It Cm LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in.
+If the value is 0, there is no time limit.
+The default is 120 seconds.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr sshd 8 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of debugging output.
+Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm MACs
+Specifies the available MAC (message authentication code) algorithms.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm Match
+Introduces a conditional block.
+If all of the criteria on the
+.Cm Match
+line are satisfied, the keywords on the following lines override those
+set in the global section of the config file, until either another
+.Cm Match
+line or the end of the file.
+.Pp
+The arguments to
+.Cm Match
+are one or more criteria-pattern pairs.
+The available criteria are
+.Cm User ,
+.Cm Group ,
+.Cm Host ,
+and
+.Cm Address .
+The match patterns may consist of single entries or comma-separated
+lists and may use the wildcard and negation operators described in the
+.Sx PATTERNS
+section of
+.Xr ssh_config 5 .
+.Pp
+The patterns in an
+.Cm Address
+criteria may additionally contain addresses to match in CIDR
+address/masklen format, e.g.\&
+.Dq 192.0.2.0/24
+or
+.Dq 3ffe:ffff::/32 .
+Note that the mask length provided must be consistent with the address -
+it is an error to specify a mask length that is too long for the address
+or one with bits set in this host portion of the address.
+For example,
+.Dq 192.0.2.0/33
+and
+.Dq 192.0.2.0/8
+respectively.
+.Pp
+Only a subset of keywords may be used on the lines following a
+.Cm Match
+keyword.
+Available keywords are
+.Cm AllowAgentForwarding ,
+.Cm AllowTcpForwarding ,
+.Cm AuthorizedKeysFile ,
+.Cm AuthorizedPrincipalsFile ,
+.Cm Banner ,
+.Cm ChrootDirectory ,
+.Cm ForceCommand ,
+.Cm GatewayPorts ,
+.Cm GSSAPIAuthentication ,
+.Cm HostbasedAuthentication ,
+.Cm HostbasedUsesNameFromPacketOnly ,
+.Cm KbdInteractiveAuthentication ,
+.Cm KerberosAuthentication ,
+.Cm MaxAuthTries ,
+.Cm MaxSessions ,
+.Cm PasswordAuthentication ,
+.Cm PermitEmptyPasswords ,
+.Cm PermitOpen ,
+.Cm PermitRootLogin ,
+.Cm PermitTunnel ,
+.Cm PubkeyAuthentication ,
+.Cm RhostsRSAAuthentication ,
+.Cm RSAAuthentication ,
+.Cm X11DisplayOffset ,
+.Cm X11Forwarding
+and
+.Cm X11UseLocalHost .
+.It Cm MaxAuthTries
+Specifies the maximum number of authentication attempts permitted per
+connection.
+Once the number of failures reaches half this value,
+additional failures are logged.
+The default is 6.
+.It Cm MaxSessions
+Specifies the maximum number of open sessions permitted per network connection.
+The default is 10.
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+SSH daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g. "10:30:60").
+.Xr sshd 8
+will refuse connection attempts with a probability of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probability increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
+.It Cm PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is
+.Dq yes .
+.It Cm PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings.
+The default is
+.Dq no .
+.It Cm PermitOpen
+Specifies the destinations to which TCP port forwarding is permitted.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Dq any
+can be used to remove all restrictions and permit any forwarding requests.
+By default all port forwarding requests are permitted.
+.It Cm PermitRootLogin
+Specifies whether root can log in using
+.Xr ssh 1 .
+The argument must be
+.Dq yes ,
+.Dq without-password ,
+.Dq forced-commands-only ,
+or
+.Dq no .
+The default is
+.Dq yes .
+.Pp
+If this option is set to
+.Dq without-password ,
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only ,
+root login with public key authentication will be allowed,
+but only if the
+.Ar command
+option has been specified
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+All other authentication methods are disabled for root.
+.Pp
+If this option is set to
+.Dq no ,
+root is not allowed to log in.
+.It Cm PermitTunnel
+Specifies whether
+.Xr tun 4
+device forwarding is allowed.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2), or
+.Dq no .
+Specifying
+.Dq yes
+permits both
+.Dq point-to-point
+and
+.Dq ethernet .
+The default is
+.Dq no .
+.It Cm PermitUserEnvironment
+Specifies whether
+.Pa ~/.ssh/environment
+and
+.Cm environment=
+options in
+.Pa ~/.ssh/authorized_keys
+are processed by
+.Xr sshd 8 .
+The default is
+.Dq no .
+Enabling environment processing may enable users to bypass access
+restrictions in some configurations using mechanisms such as
+.Ev LD_PRELOAD .
+.It Cm PidFile
+Specifies the file that contains the process ID of the
+SSH daemon.
+The default is
+.Pa /var/run/sshd.pid .
+.It Cm Port
+Specifies the port number that
+.Xr sshd 8
+listens on.
+The default is 22.
+Multiple options of this type are permitted.
+See also
+.Cm ListenAddress .
+.It Cm PrintLastLog
+Specifies whether
+.Xr sshd 8
+should print the date and time of the last user login when a user logs
+in interactively.
+The default is
+.Dq yes .
+.It Cm PrintMotd
+Specifies whether
+.Xr sshd 8
+should print
+.Pa /etc/motd
+when a user logs in interactively.
+(On some systems it is also printed by the shell,
+.Pa /etc/profile ,
+or equivalent.)
+The default is
+.Dq yes .
+.It Cm Protocol
+Specifies the protocol versions
+.Xr sshd 8
+supports.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+The default is
+.Sq 2 .
+Note that the order of the protocol list does not indicate preference,
+because the client selects among multiple protocol versions offered
+by the server.
+Specifying
+.Dq 2,1
+is identical to
+.Dq 1,2 .
+.It Cm PubkeyAuthentication
+Specifies whether public key authentication is allowed.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm RevokedKeys
+Specifies a list of revoked public keys.
+Keys listed in this file will be refused for public key authentication.
+Note that if this file is not readable, then public key authentication will
+be refused for all users.
+.It Cm RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
+.It Cm RSAAuthentication
+Specifies whether pure RSA authentication is allowed.
+The default is
+.Dq yes .
+This option applies to protocol version 1 only.
+.It Cm ServerKeyBits
+Defines the number of bits in the ephemeral protocol version 1 server key.
+The minimum value is 512, and the default is 1024.
+.It Cm StrictModes
+Specifies whether
+.Xr sshd 8
+should check file modes and ownership of the
+user's files and home directory before accepting login.
+This is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable.
+The default is
+.Dq yes .
+Note that this does not apply to
+.Cm ChrootDirectory ,
+whose permissions and ownership are checked unconditionally.
+.It Cm Subsystem
+Configures an external subsystem (e.g. file transfer daemon).
+Arguments should be a subsystem name and a command (with optional arguments)
+to execute upon subsystem request.
+.Pp
+The command
+.Xr sftp-server 8
+implements the
+.Dq sftp
+file transfer subsystem.
+.Pp
+Alternately the name
+.Dq internal-sftp
+implements an in-process
+.Dq sftp
+server.
+This may simplify configurations using
+.Cm ChrootDirectory
+to force a different filesystem root on clients.
+.Pp
+By default no subsystems are defined.
+Note that this option applies to protocol version 2 only.
+.It Cm SyslogFacility
+Gives the facility code that is used when logging messages from
+.Xr sshd 8 .
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+The default is AUTH.
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+On the other hand, if TCP keepalives are not sent,
+sessions may hang indefinitely on the server, leaving
+.Dq ghost
+users and consuming server resources.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the server will notice
+if the network goes down or the client host crashes.
+This avoids infinitely hanging sessions.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm TrustedUserCAKeys
+Specifies a file containing public keys of certificate authorities that are
+trusted to sign user certificates for authentication.
+Keys are listed one per line; empty lines and comments starting with
+.Ql #
+are allowed.
+If a certificate is presented for authentication and has its signing CA key
+listed in this file, then it may be used for authentication for any user
+listed in the certificate's principals list.
+Note that certificates that lack a list of principals will not be permitted
+for authentication using
+.Cm TrustedUserCAKeys .
+For more details on certificates, see the
+.Sx CERTIFICATES
+section in
+.Xr ssh-keygen 1 .
+.It Cm UseDNS
+Specifies whether
+.Xr sshd 8
+should look up the remote host name and check that
+the resolved host name for the remote IP address maps back to the
+very same IP address.
+The default is
+.Dq yes .
+.It Cm UseLogin
+Specifies whether
+.Xr login 1
+is used for interactive login sessions.
+The default is
+.Dq no .
+Note that
+.Xr login 1
+is never used for remote command execution.
+Note also, that if this is enabled,
+.Cm X11Forwarding
+will be disabled because
+.Xr login 1
+does not know how to handle
+.Xr xauth 1
+cookies.
+If
+.Cm UsePrivilegeSeparation
+is specified, it will be disabled after authentication.
+.It Cm UsePAM
+Enables the Pluggable Authentication Module interface.
+If set to
+.Dq yes
+this will enable PAM authentication using
+.Cm ChallengeResponseAuthentication
+and
+.Cm PasswordAuthentication
+in addition to PAM account and session module processing for all
+authentication types.
+.Pp
+Because PAM challenge-response authentication usually serves an equivalent
+role to password authentication, you should disable either
+.Cm PasswordAuthentication
+or
+.Cm ChallengeResponseAuthentication.
+.Pp
+If
+.Cm UsePAM
+is enabled, you will not be able to run
+.Xr sshd 8
+as a non-root user.
+The default is
+.Dq no .
+.It Cm UsePrivilegeSeparation
+Specifies whether
+.Xr sshd 8
+separates privileges by creating an unprivileged child process
+to deal with incoming network traffic.
+After successful authentication, another process will be created that has
+the privilege of the authenticated user.
+The goal of privilege separation is to prevent privilege
+escalation by containing any corruption within the unprivileged processes.
+The default is
+.Dq yes .
+If
+.Cm UsePrivilegeSeparation
+is set to
+.Dq sandbox
+then the pre-authentication unprivileged process is subject to additional
+restrictions.
+.It Cm X11DisplayOffset
+Specifies the first display number available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from interfering with real X11 servers.
+The default is 10.
+.It Cm X11Forwarding
+Specifies whether X11 forwarding is permitted.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+When X11 forwarding is enabled, there may be additional exposure to
+the server and to client displays if the
+.Xr sshd 8
+proxy display is configured to listen on the wildcard address (see
+.Cm X11UseLocalhost
+below), though this is not the default.
+Additionally, the authentication spoofing and authentication data
+verification and substitution occur on the client side.
+The security risk of using X11 forwarding is that the client's X11
+display server may be exposed to attack when the SSH client requests
+forwarding (see the warnings for
+.Cm ForwardX11
+in
+.Xr ssh_config 5 ) .
+A system administrator may have a stance in which they want to
+protect clients that may expose themselves to attack by unwittingly
+requesting X11 forwarding, which can warrant a
+.Dq no
+setting.
+.Pp
+Note that disabling X11 forwarding does not prevent users from
+forwarding X11 traffic, as users can always install their own forwarders.
+X11 forwarding is automatically disabled if
+.Cm UseLogin
+is enabled.
+.It Cm X11UseLocalhost
+Specifies whether
+.Xr sshd 8
+should bind the X11 forwarding server to the loopback address or to
+the wildcard address.
+By default,
+sshd binds the forwarding server to the loopback address and sets the
+hostname part of the
+.Ev DISPLAY
+environment variable to
+.Dq localhost .
+This prevents remote hosts from connecting to the proxy display.
+However, some older X11 clients may not function with this
+configuration.
+.Cm X11UseLocalhost
+may be set to
+.Dq no
+to specify that the forwarding server should be bound to the wildcard
+address.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh TIME FORMATS
+.Xr sshd 8
+command-line arguments and configuration file options that specify time
+may be expressed using a sequence of the form:
+.Sm off
+.Ar time Op Ar qualifier ,
+.Sm on
+where
+.Ar time
+is a positive integer value and
+.Ar qualifier
+is one of the following:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It Aq Cm none
+seconds
+.It Cm s | Cm S
+seconds
+.It Cm m | Cm M
+minutes
+.It Cm h | Cm H
+hours
+.It Cm d | Cm D
+days
+.It Cm w | Cm W
+weeks
+.El
+.Pp
+Each member of the sequence is added together to calculate
+the total time value.
+.Pp
+Time format examples:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It 600
+600 seconds (10 minutes)
+.It 10m
+10 minutes
+.It 1h30m
+1 hour 30 minutes (90 minutes)
+.El
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa /etc/ssh/sshd_config
+Contains configuration data for
+.Xr sshd 8 .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.El
+.Sh SEE ALSO
+.Xr sshd 8
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Niels Provos and Markus Friedl contributed support
+for privilege separation.
diff --git a/.pc/ssh1-keepalive.patch/clientloop.c b/.pc/ssh1-keepalive.patch/clientloop.c
new file mode 100644 (file)
index 0000000..17628ef
--- /dev/null
@@ -0,0 +1,2188 @@
+/* $OpenBSD: clientloop.c,v 1.236 2011/06/22 22:08:42 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * The main loop for the interactive session (client side).
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ *
+ * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * SSH2 support added by Markus Friedl.
+ * Copyright (c) 1999, 2000, 2001 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <errno.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "openbsd-compat/sys-queue.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "packet.h"
+#include "buffer.h"
+#include "compat.h"
+#include "channels.h"
+#include "dispatch.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "readconf.h"
+#include "clientloop.h"
+#include "sshconnect.h"
+#include "authfd.h"
+#include "atomicio.h"
+#include "sshpty.h"
+#include "misc.h"
+#include "match.h"
+#include "msg.h"
+#include "roaming.h"
+
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
+/* import options */
+extern Options options;
+
+/* Flag indicating that stdin should be redirected from /dev/null. */
+extern int stdin_null_flag;
+
+/* Flag indicating that no shell has been requested */
+extern int no_shell_flag;
+
+/* Control socket */
+extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
+
+/*
+ * Name of the host we are connecting to.  This is the name given on the
+ * command line, or the HostName specified for the user-supplied name in a
+ * configuration file.
+ */
+extern char *host;
+
+/*
+ * Flag to indicate that we have received a window change signal which has
+ * not yet been processed.  This will cause a message indicating the new
+ * window size to be sent to the server a little later.  This is volatile
+ * because this is updated in a signal handler.
+ */
+static volatile sig_atomic_t received_window_change_signal = 0;
+static volatile sig_atomic_t received_signal = 0;
+
+/* Flag indicating whether the user's terminal is in non-blocking mode. */
+static int in_non_blocking_mode = 0;
+
+/* Time when backgrounded control master using ControlPersist should exit */
+static time_t control_persist_exit_time = 0;
+
+/* Common data for the client loop code. */
+volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
+static int escape_char1;       /* Escape character. (proto1 only) */
+static int escape_pending1;    /* Last character was an escape (proto1 only) */
+static int last_was_cr;                /* Last character was a newline. */
+static int exit_status;                /* Used to store the command exit status. */
+static int stdin_eof;          /* EOF has been encountered on stderr. */
+static Buffer stdin_buffer;    /* Buffer for stdin data. */
+static Buffer stdout_buffer;   /* Buffer for stdout data. */
+static Buffer stderr_buffer;   /* Buffer for stderr data. */
+static u_int buffer_high;      /* Soft max buffer size. */
+static int connection_in;      /* Connection to server (input). */
+static int connection_out;     /* Connection to server (output). */
+static int need_rekeying;      /* Set to non-zero if rekeying is requested. */
+static int session_closed;     /* In SSH2: login session closed. */
+static int x11_refuse_time;    /* If >0, refuse x11 opens after this time. */
+
+static void client_init_dispatch(void);
+int    session_ident = -1;
+
+int    session_resumed = 0;
+
+/* Track escape per proto2 channel */
+struct escape_filter_ctx {
+       int escape_pending;
+       int escape_char;
+};
+
+/* Context for channel confirmation replies */
+struct channel_reply_ctx {
+       const char *request_type;
+       int id;
+       enum confirm_action action;
+};
+
+/* Global request success/failure callbacks */
+struct global_confirm {
+       TAILQ_ENTRY(global_confirm) entry;
+       global_confirm_cb *cb;
+       void *ctx;
+       int ref_count;
+};
+TAILQ_HEAD(global_confirms, global_confirm);
+static struct global_confirms global_confirms =
+    TAILQ_HEAD_INITIALIZER(global_confirms);
+
+/*XXX*/
+extern Kex *xxx_kex;
+
+void ssh_process_session2_setup(int, int, int, Buffer *);
+
+/* Restores stdin to blocking mode. */
+
+static void
+leave_non_blocking(void)
+{
+       if (in_non_blocking_mode) {
+               unset_nonblock(fileno(stdin));
+               in_non_blocking_mode = 0;
+       }
+}
+
+/* Puts stdin terminal in non-blocking mode. */
+
+static void
+enter_non_blocking(void)
+{
+       in_non_blocking_mode = 1;
+       set_nonblock(fileno(stdin));
+}
+
+/*
+ * Signal handler for the window change signal (SIGWINCH).  This just sets a
+ * flag indicating that the window has changed.
+ */
+/*ARGSUSED */
+static void
+window_change_handler(int sig)
+{
+       received_window_change_signal = 1;
+       signal(SIGWINCH, window_change_handler);
+}
+
+/*
+ * Signal handler for signals that cause the program to terminate.  These
+ * signals must be trapped to restore terminal modes.
+ */
+/*ARGSUSED */
+static void
+signal_handler(int sig)
+{
+       received_signal = sig;
+       quit_pending = 1;
+}
+
+/*
+ * Returns current time in seconds from Jan 1, 1970 with the maximum
+ * available resolution.
+ */
+
+static double
+get_current_time(void)
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+}
+
+/*
+ * Sets control_persist_exit_time to the absolute time when the
+ * backgrounded control master should exit due to expiry of the
+ * ControlPersist timeout.  Sets it to 0 if we are not a backgrounded
+ * control master process, or if there is no ControlPersist timeout.
+ */
+static void
+set_control_persist_exit_time(void)
+{
+       if (muxserver_sock == -1 || !options.control_persist
+           || options.control_persist_timeout == 0) {
+               /* not using a ControlPersist timeout */
+               control_persist_exit_time = 0;
+       } else if (channel_still_open()) {
+               /* some client connections are still open */
+               if (control_persist_exit_time > 0)
+                       debug2("%s: cancel scheduled exit", __func__);
+               control_persist_exit_time = 0;
+       } else if (control_persist_exit_time <= 0) {
+               /* a client connection has recently closed */
+               control_persist_exit_time = time(NULL) +
+                       (time_t)options.control_persist_timeout;
+               debug2("%s: schedule exit in %d seconds", __func__,
+                   options.control_persist_timeout);
+       }
+       /* else we are already counting down to the timeout */
+}
+
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+void
+client_x11_get_proto(const char *display, const char *xauth_path,
+    u_int trusted, u_int timeout, char **_proto, char **_data)
+{
+       char cmd[1024];
+       char line[512];
+       char xdisplay[512];
+       static char proto[512], data[512];
+       FILE *f;
+       int got_data = 0, generated = 0, do_unlink = 0, i;
+       char *xauthdir, *xauthfile;
+       struct stat st;
+       u_int now;
+
+       xauthdir = xauthfile = NULL;
+       *_proto = proto;
+       *_data = data;
+       proto[0] = data[0] = '\0';
+
+       if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) {
+               debug("No xauth program.");
+       } else {
+               if (display == NULL) {
+                       debug("x11_get_proto: DISPLAY not set");
+                       return;
+               }
+               /*
+                * Handle FamilyLocal case where $DISPLAY does
+                * not match an authorization entry.  For this we
+                * just try "xauth list unix:displaynum.screennum".
+                * XXX: "localhost" match to determine FamilyLocal
+                *      is not perfect.
+                */
+               if (strncmp(display, "localhost:", 10) == 0) {
+                       snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
+                           display + 10);
+                       display = xdisplay;
+               }
+               if (trusted == 0) {
+                       xauthdir = xmalloc(MAXPATHLEN);
+                       xauthfile = xmalloc(MAXPATHLEN);
+                       mktemp_proto(xauthdir, MAXPATHLEN);
+                       if (mkdtemp(xauthdir) != NULL) {
+                               do_unlink = 1;
+                               snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
+                                   xauthdir);
+                               snprintf(cmd, sizeof(cmd),
+                                   "%s -f %s generate %s " SSH_X11_PROTO
+                                   " untrusted timeout %u 2>" _PATH_DEVNULL,
+                                   xauth_path, xauthfile, display, timeout);
+                               debug2("x11_get_proto: %s", cmd);
+                               if (system(cmd) == 0)
+                                       generated = 1;
+                               if (x11_refuse_time == 0) {
+                                       now = time(NULL) + 1;
+                                       if (UINT_MAX - timeout < now)
+                                               x11_refuse_time = UINT_MAX;
+                                       else
+                                               x11_refuse_time = now + timeout;
+                               }
+                       }
+               }
+
+               /*
+                * When in untrusted mode, we read the cookie only if it was
+                * successfully generated as an untrusted one in the step
+                * above.
+                */
+               if (trusted || generated) {
+                       snprintf(cmd, sizeof(cmd),
+                           "%s %s%s list %s 2>" _PATH_DEVNULL,
+                           xauth_path,
+                           generated ? "-f " : "" ,
+                           generated ? xauthfile : "",
+                           display);
+                       debug2("x11_get_proto: %s", cmd);
+                       f = popen(cmd, "r");
+                       if (f && fgets(line, sizeof(line), f) &&
+                           sscanf(line, "%*s %511s %511s", proto, data) == 2)
+                               got_data = 1;
+                       if (f)
+                               pclose(f);
+               } else
+                       error("Warning: untrusted X11 forwarding setup failed: "
+                           "xauth key data not generated");
+       }
+
+       if (do_unlink) {
+               unlink(xauthfile);
+               rmdir(xauthdir);
+       }
+       if (xauthdir)
+               xfree(xauthdir);
+       if (xauthfile)
+               xfree(xauthfile);
+
+       /*
+        * If we didn't get authentication data, just make up some
+        * data.  The forwarding code will check the validity of the
+        * response anyway, and substitute this data.  The X11
+        * server, however, will ignore this fake data and use
+        * whatever authentication mechanisms it was using otherwise
+        * for the local connection.
+        */
+       if (!got_data) {
+               u_int32_t rnd = 0;
+
+               logit("Warning: No xauth data; "
+                   "using fake authentication data for X11 forwarding.");
+               strlcpy(proto, SSH_X11_PROTO, sizeof proto);
+               for (i = 0; i < 16; i++) {
+                       if (i % 4 == 0)
+                               rnd = arc4random();
+                       snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
+                           rnd & 0xff);
+                       rnd >>= 8;
+               }
+       }
+}
+
+/*
+ * This is called when the interactive is entered.  This checks if there is
+ * an EOF coming on stdin.  We must check this explicitly, as select() does
+ * not appear to wake up when redirecting from /dev/null.
+ */
+
+static void
+client_check_initial_eof_on_stdin(void)
+{
+       int len;
+       char buf[1];
+
+       /*
+        * If standard input is to be "redirected from /dev/null", we simply
+        * mark that we have seen an EOF and send an EOF message to the
+        * server. Otherwise, we try to read a single character; it appears
+        * that for some files, such /dev/null, select() never wakes up for
+        * read for this descriptor, which means that we never get EOF.  This
+        * way we will get the EOF if stdin comes from /dev/null or similar.
+        */
+       if (stdin_null_flag) {
+               /* Fake EOF on stdin. */
+               debug("Sending eof.");
+               stdin_eof = 1;
+               packet_start(SSH_CMSG_EOF);
+               packet_send();
+       } else {
+               enter_non_blocking();
+
+               /* Check for immediate EOF on stdin. */
+               len = read(fileno(stdin), buf, 1);
+               if (len == 0) {
+                       /*
+                        * EOF.  Record that we have seen it and send
+                        * EOF to server.
+                        */
+                       debug("Sending eof.");
+                       stdin_eof = 1;
+                       packet_start(SSH_CMSG_EOF);
+                       packet_send();
+               } else if (len > 0) {
+                       /*
+                        * Got data.  We must store the data in the buffer,
+                        * and also process it as an escape character if
+                        * appropriate.
+                        */
+                       if ((u_char) buf[0] == escape_char1)
+                               escape_pending1 = 1;
+                       else
+                               buffer_append(&stdin_buffer, buf, 1);
+               }
+               leave_non_blocking();
+       }
+}
+
+
+/*
+ * Make packets from buffered stdin data, and buffer them for sending to the
+ * connection.
+ */
+
+static void
+client_make_packets_from_stdin_data(void)
+{
+       u_int len;
+
+       /* Send buffered stdin data to the server. */
+       while (buffer_len(&stdin_buffer) > 0 &&
+           packet_not_very_much_data_to_write()) {
+               len = buffer_len(&stdin_buffer);
+               /* Keep the packets at reasonable size. */
+               if (len > packet_get_maxsize())
+                       len = packet_get_maxsize();
+               packet_start(SSH_CMSG_STDIN_DATA);
+               packet_put_string(buffer_ptr(&stdin_buffer), len);
+               packet_send();
+               buffer_consume(&stdin_buffer, len);
+               /* If we have a pending EOF, send it now. */
+               if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
+                       packet_start(SSH_CMSG_EOF);
+                       packet_send();
+               }
+       }
+}
+
+/*
+ * Checks if the client window has changed, and sends a packet about it to
+ * the server if so.  The actual change is detected elsewhere (by a software
+ * interrupt on Unix); this just checks the flag and sends a message if
+ * appropriate.
+ */
+
+static void
+client_check_window_change(void)
+{
+       struct winsize ws;
+
+       if (! received_window_change_signal)
+               return;
+       /** XXX race */
+       received_window_change_signal = 0;
+
+       debug2("client_check_window_change: changed");
+
+       if (compat20) {
+               channel_send_window_changes();
+       } else {
+               if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
+                       return;
+               packet_start(SSH_CMSG_WINDOW_SIZE);
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+               packet_send();
+       }
+}
+
+static void
+client_global_request_reply(int type, u_int32_t seq, void *ctxt)
+{
+       struct global_confirm *gc;
+
+       if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
+               return;
+       if (gc->cb != NULL)
+               gc->cb(type, seq, gc->ctx);
+       if (--gc->ref_count <= 0) {
+               TAILQ_REMOVE(&global_confirms, gc, entry);
+               bzero(gc, sizeof(*gc));
+               xfree(gc);
+       }
+
+       packet_set_alive_timeouts(0);
+}
+
+static void
+server_alive_check(void)
+{
+       if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
+               logit("Timeout, server %s not responding.", host);
+               cleanup_exit(255);
+       }
+       packet_start(SSH2_MSG_GLOBAL_REQUEST);
+       packet_put_cstring("keepalive@openssh.com");
+       packet_put_char(1);     /* boolean: want reply */
+       packet_send();
+       /* Insert an empty placeholder to maintain ordering */
+       client_register_global_confirm(NULL, NULL);
+}
+
+/*
+ * Waits until the client can do something (some data becomes available on
+ * one of the file descriptors).
+ */
+static void
+client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
+    int *maxfdp, u_int *nallocp, int rekeying)
+{
+       struct timeval tv, *tvp;
+       int timeout_secs;
+       int ret;
+
+       /* Add any selections by the channel mechanism. */
+       channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying);
+
+       if (!compat20) {
+               /* Read from the connection, unless our buffers are full. */
+               if (buffer_len(&stdout_buffer) < buffer_high &&
+                   buffer_len(&stderr_buffer) < buffer_high &&
+                   channel_not_very_much_buffered_data())
+                       FD_SET(connection_in, *readsetp);
+               /*
+                * Read from stdin, unless we have seen EOF or have very much
+                * buffered data to send to the server.
+                */
+               if (!stdin_eof && packet_not_very_much_data_to_write())
+                       FD_SET(fileno(stdin), *readsetp);
+
+               /* Select stdout/stderr if have data in buffer. */
+               if (buffer_len(&stdout_buffer) > 0)
+                       FD_SET(fileno(stdout), *writesetp);
+               if (buffer_len(&stderr_buffer) > 0)
+                       FD_SET(fileno(stderr), *writesetp);
+       } else {
+               /* channel_prepare_select could have closed the last channel */
+               if (session_closed && !channel_still_open() &&
+                   !packet_have_data_to_write()) {
+                       /* clear mask since we did not call select() */
+                       memset(*readsetp, 0, *nallocp);
+                       memset(*writesetp, 0, *nallocp);
+                       return;
+               } else {
+                       FD_SET(connection_in, *readsetp);
+               }
+       }
+
+       /* Select server connection if have data to write to the server. */
+       if (packet_have_data_to_write())
+               FD_SET(connection_out, *writesetp);
+
+       /*
+        * Wait for something to happen.  This will suspend the process until
+        * some selected descriptor can be read, written, or has some other
+        * event pending, or a timeout expires.
+        */
+
+       timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
+       if (options.server_alive_interval > 0 && compat20)
+               timeout_secs = options.server_alive_interval;
+       set_control_persist_exit_time();
+       if (control_persist_exit_time > 0) {
+               timeout_secs = MIN(timeout_secs,
+                       control_persist_exit_time - time(NULL));
+               if (timeout_secs < 0)
+                       timeout_secs = 0;
+       }
+       if (timeout_secs == INT_MAX)
+               tvp = NULL;
+       else {
+               tv.tv_sec = timeout_secs;
+               tv.tv_usec = 0;
+               tvp = &tv;
+       }
+
+       ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+       if (ret < 0) {
+               char buf[100];
+
+               /*
+                * We have to clear the select masks, because we return.
+                * We have to return, because the mainloop checks for the flags
+                * set by the signal handlers.
+                */
+               memset(*readsetp, 0, *nallocp);
+               memset(*writesetp, 0, *nallocp);
+
+               if (errno == EINTR)
+                       return;
+               /* Note: we might still have data in the buffers. */
+               snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
+               buffer_append(&stderr_buffer, buf, strlen(buf));
+               quit_pending = 1;
+       } else if (ret == 0)
+               server_alive_check();
+}
+
+static void
+client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
+{
+       /* Flush stdout and stderr buffers. */
+       if (buffer_len(bout) > 0)
+               atomicio(vwrite, fileno(stdout), buffer_ptr(bout),
+                   buffer_len(bout));
+       if (buffer_len(berr) > 0)
+               atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
+                   buffer_len(berr));
+
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       /*
+        * Free (and clear) the buffer to reduce the amount of data that gets
+        * written to swap.
+        */
+       buffer_free(bin);
+       buffer_free(bout);
+       buffer_free(berr);
+
+       /* Send the suspend signal to the program itself. */
+       kill(getpid(), SIGTSTP);
+
+       /* Reset window sizes in case they have changed */
+       received_window_change_signal = 1;
+
+       /* OK, we have been continued by the user. Reinitialize buffers. */
+       buffer_init(bin);
+       buffer_init(bout);
+       buffer_init(berr);
+
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+}
+
+static void
+client_process_net_input(fd_set *readset)
+{
+       int len, cont = 0;
+       char buf[SSH_IOBUFSZ];
+
+       /*
+        * Read input from the server, and add any such data to the buffer of
+        * the packet subsystem.
+        */
+       if (FD_ISSET(connection_in, readset)) {
+               /* Read as much as possible. */
+               len = roaming_read(connection_in, buf, sizeof(buf), &cont);
+               if (len == 0 && cont == 0) {
+                       /*
+                        * Received EOF.  The remote host has closed the
+                        * connection.
+                        */
+                       snprintf(buf, sizeof buf,
+                           "Connection to %.300s closed by remote host.\r\n",
+                           host);
+                       buffer_append(&stderr_buffer, buf, strlen(buf));
+                       quit_pending = 1;
+                       return;
+               }
+               /*
+                * There is a kernel bug on Solaris that causes select to
+                * sometimes wake up even though there is no data available.
+                */
+               if (len < 0 &&
+                   (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
+                       len = 0;
+
+               if (len < 0) {
+                       /*
+                        * An error has encountered.  Perhaps there is a
+                        * network problem.
+                        */
+                       snprintf(buf, sizeof buf,
+                           "Read from remote host %.300s: %.100s\r\n",
+                           host, strerror(errno));
+                       buffer_append(&stderr_buffer, buf, strlen(buf));
+                       quit_pending = 1;
+                       return;
+               }
+               packet_process_incoming(buf, len);
+       }
+}
+
+static void
+client_status_confirm(int type, Channel *c, void *ctx)
+{
+       struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
+       char errmsg[256];
+       int tochan;
+
+       /*
+        * If a TTY was explicitly requested, then a failure to allocate
+        * one is fatal.
+        */
+       if (cr->action == CONFIRM_TTY &&
+           (options.request_tty == REQUEST_TTY_FORCE ||
+           options.request_tty == REQUEST_TTY_YES))
+               cr->action = CONFIRM_CLOSE;
+
+       /* XXX supress on mux _client_ quietmode */
+       tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
+           c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
+
+       if (type == SSH2_MSG_CHANNEL_SUCCESS) {
+               debug2("%s request accepted on channel %d",
+                   cr->request_type, c->self);
+       } else if (type == SSH2_MSG_CHANNEL_FAILURE) {
+               if (tochan) {
+                       snprintf(errmsg, sizeof(errmsg),
+                           "%s request failed\r\n", cr->request_type);
+               } else {
+                       snprintf(errmsg, sizeof(errmsg),
+                           "%s request failed on channel %d",
+                           cr->request_type, c->self);
+               }
+               /* If error occurred on primary session channel, then exit */
+               if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
+                       fatal("%s", errmsg);
+               /*
+                * If error occurred on mux client, append to
+                * their stderr.
+                */
+               if (tochan) {
+                       buffer_append(&c->extended, errmsg,
+                           strlen(errmsg));
+               } else
+                       error("%s", errmsg);
+               if (cr->action == CONFIRM_TTY) {
+                       /*
+                        * If a TTY allocation error occurred, then arrange
+                        * for the correct TTY to leave raw mode.
+                        */
+                       if (c->self == session_ident)
+                               leave_raw_mode(0);
+                       else
+                               mux_tty_alloc_failed(c);
+               } else if (cr->action == CONFIRM_CLOSE) {
+                       chan_read_failed(c);
+                       chan_write_failed(c);
+               }
+       }
+       xfree(cr);
+}
+
+static void
+client_abandon_status_confirm(Channel *c, void *ctx)
+{
+       xfree(ctx);
+}
+
+void
+client_expect_confirm(int id, const char *request,
+    enum confirm_action action)
+{
+       struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
+
+       cr->request_type = request;
+       cr->action = action;
+
+       channel_register_status_confirm(id, client_status_confirm,
+           client_abandon_status_confirm, cr);
+}
+
+void
+client_register_global_confirm(global_confirm_cb *cb, void *ctx)
+{
+       struct global_confirm *gc, *last_gc;
+
+       /* Coalesce identical callbacks */
+       last_gc = TAILQ_LAST(&global_confirms, global_confirms);
+       if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
+               if (++last_gc->ref_count >= INT_MAX)
+                       fatal("%s: last_gc->ref_count = %d",
+                           __func__, last_gc->ref_count);
+               return;
+       }
+
+       gc = xmalloc(sizeof(*gc));
+       gc->cb = cb;
+       gc->ctx = ctx;
+       gc->ref_count = 1;
+       TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
+}
+
+static void
+process_cmdline(void)
+{
+       void (*handler)(int);
+       char *s, *cmd, *cancel_host;
+       int delete = 0;
+       int local = 0, remote = 0, dynamic = 0;
+       int cancel_port;
+       Forward fwd;
+
+       bzero(&fwd, sizeof(fwd));
+       fwd.listen_host = fwd.connect_host = NULL;
+
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       handler = signal(SIGINT, SIG_IGN);
+       cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
+       if (s == NULL)
+               goto out;
+       while (isspace(*s))
+               s++;
+       if (*s == '-')
+               s++;    /* Skip cmdline '-', if any */
+       if (*s == '\0')
+               goto out;
+
+       if (*s == 'h' || *s == 'H' || *s == '?') {
+               logit("Commands:");
+               logit("      -L[bind_address:]port:host:hostport    "
+                   "Request local forward");
+               logit("      -R[bind_address:]port:host:hostport    "
+                   "Request remote forward");
+               logit("      -D[bind_address:]port                  "
+                   "Request dynamic forward");
+               logit("      -KR[bind_address:]port                 "
+                   "Cancel remote forward");
+               if (!options.permit_local_command)
+                       goto out;
+               logit("      !args                                  "
+                   "Execute local command");
+               goto out;
+       }
+
+       if (*s == '!' && options.permit_local_command) {
+               s++;
+               ssh_local_cmd(s);
+               goto out;
+       }
+
+       if (*s == 'K') {
+               delete = 1;
+               s++;
+       }
+       if (*s == 'L')
+               local = 1;
+       else if (*s == 'R')
+               remote = 1;
+       else if (*s == 'D')
+               dynamic = 1;
+       else {
+               logit("Invalid command.");
+               goto out;
+       }
+
+       if ((local || dynamic) && delete) {
+               logit("Not supported.");
+               goto out;
+       }
+       if (remote && delete && !compat20) {
+               logit("Not supported for SSH protocol version 1.");
+               goto out;
+       }
+
+       while (isspace(*++s))
+               ;
+
+       /* XXX update list of forwards in options */
+       if (delete) {
+               cancel_port = 0;
+               cancel_host = hpdelim(&s);      /* may be NULL */
+               if (s != NULL) {
+                       cancel_port = a2port(s);
+                       cancel_host = cleanhostname(cancel_host);
+               } else {
+                       cancel_port = a2port(cancel_host);
+                       cancel_host = NULL;
+               }
+               if (cancel_port <= 0) {
+                       logit("Bad forwarding close port");
+                       goto out;
+               }
+               channel_request_rforward_cancel(cancel_host, cancel_port);
+       } else {
+               if (!parse_forward(&fwd, s, dynamic, remote)) {
+                       logit("Bad forwarding specification.");
+                       goto out;
+               }
+               if (local || dynamic) {
+                       if (channel_setup_local_fwd_listener(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port, options.gateway_ports) < 0) {
+                               logit("Port forwarding failed.");
+                               goto out;
+                       }
+               } else {
+                       if (channel_request_remote_forwarding(fwd.listen_host,
+                           fwd.listen_port, fwd.connect_host,
+                           fwd.connect_port) < 0) {
+                               logit("Port forwarding failed.");
+                               goto out;
+                       }
+               }
+
+               logit("Forwarding port.");
+       }
+
+out:
+       signal(SIGINT, handler);
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       if (cmd)
+               xfree(cmd);
+       if (fwd.listen_host != NULL)
+               xfree(fwd.listen_host);
+       if (fwd.connect_host != NULL)
+               xfree(fwd.connect_host);
+}
+
+/* 
+ * Process the characters one by one, call with c==NULL for proto1 case.
+ */
+static int
+process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
+    char *buf, int len)
+{
+       char string[1024];
+       pid_t pid;
+       int bytes = 0;
+       u_int i;
+       u_char ch;
+       char *s;
+       int *escape_pendingp, escape_char;
+       struct escape_filter_ctx *efc;
+
+       if (c == NULL) {
+               escape_pendingp = &escape_pending1;
+               escape_char = escape_char1;
+       } else {
+               if (c->filter_ctx == NULL)
+                       return 0;
+               efc = (struct escape_filter_ctx *)c->filter_ctx;
+               escape_pendingp = &efc->escape_pending;
+               escape_char = efc->escape_char;
+       }
+       
+       if (len <= 0)
+               return (0);
+
+       for (i = 0; i < (u_int)len; i++) {
+               /* Get one character at a time. */
+               ch = buf[i];
+
+               if (*escape_pendingp) {
+                       /* We have previously seen an escape character. */
+                       /* Clear the flag now. */
+                       *escape_pendingp = 0;
+
+                       /* Process the escaped character. */
+                       switch (ch) {
+                       case '.':
+                               /* Terminate the connection. */
+                               snprintf(string, sizeof string, "%c.\r\n",
+                                   escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               if (c && c->ctl_chan != -1) {
+                                       chan_read_failed(c);
+                                       chan_write_failed(c);
+                                       return 0;
+                               } else
+                                       quit_pending = 1;
+                               return -1;
+
+                       case 'Z' - 64:
+                               /* XXX support this for mux clients */
+                               if (c && c->ctl_chan != -1) {
+ noescape:
+                                       snprintf(string, sizeof string,
+                                           "%c%c escape not available to "
+                                           "multiplexed sessions\r\n",
+                                           escape_char, ch);
+                                       buffer_append(berr, string,
+                                           strlen(string));
+                                       continue;
+                               }
+                               /* Suspend the program. Inform the user */
+                               snprintf(string, sizeof string,
+                                   "%c^Z [suspend ssh]\r\n", escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               /* Restore terminal modes and suspend. */
+                               client_suspend_self(bin, bout, berr);
+
+                               /* We have been continued. */
+                               continue;
+
+                       case 'B':
+                               if (compat20) {
+                                       snprintf(string, sizeof string,
+                                           "%cB\r\n", escape_char);
+                                       buffer_append(berr, string,
+                                           strlen(string));
+                                       channel_request_start(session_ident,
+                                           "break", 0);
+                                       packet_put_int(1000);
+                                       packet_send();
+                               }
+                               continue;
+
+                       case 'R':
+                               if (compat20) {
+                                       if (datafellows & SSH_BUG_NOREKEY)
+                                               logit("Server does not "
+                                                   "support re-keying");
+                                       else
+                                               need_rekeying = 1;
+                               }
+                               continue;
+
+                       case '&':
+                               if (c && c->ctl_chan != -1)
+                                       goto noescape;
+                               /*
+                                * Detach the program (continue to serve
+                                * connections, but put in background and no
+                                * more new connections).
+                                */
+                               /* Restore tty modes. */
+                               leave_raw_mode(
+                                   options.request_tty == REQUEST_TTY_FORCE);
+
+                               /* Stop listening for new connections. */
+                               channel_stop_listening();
+
+                               snprintf(string, sizeof string,
+                                   "%c& [backgrounded]\n", escape_char);
+                               buffer_append(berr, string, strlen(string));
+
+                               /* Fork into background. */
+                               pid = fork();
+                               if (pid < 0) {
+                                       error("fork: %.100s", strerror(errno));
+                                       continue;
+                               }
+                               if (pid != 0) { /* This is the parent. */
+                                       /* The parent just exits. */
+                                       exit(0);
+                               }
+                               /* The child continues serving connections. */
+                               if (compat20) {
+                                       buffer_append(bin, "\004", 1);
+                                       /* fake EOF on stdin */
+                                       return -1;
+                               } else if (!stdin_eof) {
+                                       /*
+                                        * Sending SSH_CMSG_EOF alone does not
+                                        * always appear to be enough.  So we
+                                        * try to send an EOF character first.
+                                        */
+                                       packet_start(SSH_CMSG_STDIN_DATA);
+                                       packet_put_string("\004", 1);
+                                       packet_send();
+                                       /* Close stdin. */
+                                       stdin_eof = 1;
+                                       if (buffer_len(bin) == 0) {
+                                               packet_start(SSH_CMSG_EOF);
+                                               packet_send();
+                                       }
+                               }
+                               continue;
+
+                       case '?':
+                               if (c && c->ctl_chan != -1) {
+                                       snprintf(string, sizeof string,
+"%c?\r\n\
+Supported escape sequences:\r\n\
+  %c.  - terminate session\r\n\
+  %cB  - send a BREAK to the remote system\r\n\
+  %cR  - Request rekey (SSH protocol 2 only)\r\n\
+  %c#  - list forwarded connections\r\n\
+  %c?  - this message\r\n\
+  %c%c  - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char);
+                               } else {
+                                       snprintf(string, sizeof string,
+"%c?\r\n\
+Supported escape sequences:\r\n\
+  %c.  - terminate connection (and any multiplexed sessions)\r\n\
+  %cB  - send a BREAK to the remote system\r\n\
+  %cC  - open a command line\r\n\
+  %cR  - Request rekey (SSH protocol 2 only)\r\n\
+  %c^Z - suspend ssh\r\n\
+  %c#  - list forwarded connections\r\n\
+  %c&  - background ssh (when waiting for connections to terminate)\r\n\
+  %c?  - this message\r\n\
+  %c%c  - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char, escape_char,
+                                           escape_char);
+                               }
+                               buffer_append(berr, string, strlen(string));
+                               continue;
+
+                       case '#':
+                               snprintf(string, sizeof string, "%c#\r\n",
+                                   escape_char);
+                               buffer_append(berr, string, strlen(string));
+                               s = channel_open_message();
+                               buffer_append(berr, s, strlen(s));
+                               xfree(s);
+                               continue;
+
+                       case 'C':
+                               if (c && c->ctl_chan != -1)
+                                       goto noescape;
+                               process_cmdline();
+                               continue;
+
+                       default:
+                               if (ch != escape_char) {
+                                       buffer_put_char(bin, escape_char);
+                                       bytes++;
+                               }
+                               /* Escaped characters fall through here */
+                               break;
+                       }
+               } else {
+                       /*
+                        * The previous character was not an escape char.
+                        * Check if this is an escape.
+                        */
+                       if (last_was_cr && ch == escape_char) {
+                               /*
+                                * It is. Set the flag and continue to
+                                * next character.
+                                */
+                               *escape_pendingp = 1;
+                               continue;
+                       }
+               }
+
+               /*
+                * Normal character.  Record whether it was a newline,
+                * and append it to the buffer.
+                */
+               last_was_cr = (ch == '\r' || ch == '\n');
+               buffer_put_char(bin, ch);
+               bytes++;
+       }
+       return bytes;
+}
+
+static void
+client_process_input(fd_set *readset)
+{
+       int len;
+       char buf[SSH_IOBUFSZ];
+
+       /* Read input from stdin. */
+       if (FD_ISSET(fileno(stdin), readset)) {
+               /* Read as much as possible. */
+               len = read(fileno(stdin), buf, sizeof(buf));
+               if (len < 0 &&
+                   (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
+                       return;         /* we'll try again later */
+               if (len <= 0) {
+                       /*
+                        * Received EOF or error.  They are treated
+                        * similarly, except that an error message is printed
+                        * if it was an error condition.
+                        */
+                       if (len < 0) {
+                               snprintf(buf, sizeof buf, "read: %.100s\r\n",
+                                   strerror(errno));
+                               buffer_append(&stderr_buffer, buf, strlen(buf));
+                       }
+                       /* Mark that we have seen EOF. */
+                       stdin_eof = 1;
+                       /*
+                        * Send an EOF message to the server unless there is
+                        * data in the buffer.  If there is data in the
+                        * buffer, no message will be sent now.  Code
+                        * elsewhere will send the EOF when the buffer
+                        * becomes empty if stdin_eof is set.
+                        */
+                       if (buffer_len(&stdin_buffer) == 0) {
+                               packet_start(SSH_CMSG_EOF);
+                               packet_send();
+                       }
+               } else if (escape_char1 == SSH_ESCAPECHAR_NONE) {
+                       /*
+                        * Normal successful read, and no escape character.
+                        * Just append the data to buffer.
+                        */
+                       buffer_append(&stdin_buffer, buf, len);
+               } else {
+                       /*
+                        * Normal, successful read.  But we have an escape
+                        * character and have to process the characters one
+                        * by one.
+                        */
+                       if (process_escapes(NULL, &stdin_buffer,
+                           &stdout_buffer, &stderr_buffer, buf, len) == -1)
+                               return;
+               }
+       }
+}
+
+static void
+client_process_output(fd_set *writeset)
+{
+       int len;
+       char buf[100];
+
+       /* Write buffered output to stdout. */
+       if (FD_ISSET(fileno(stdout), writeset)) {
+               /* Write as much data as possible. */
+               len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
+                   buffer_len(&stdout_buffer));
+               if (len <= 0) {
+                       if (errno == EINTR || errno == EAGAIN ||
+                           errno == EWOULDBLOCK)
+                               len = 0;
+                       else {
+                               /*
+                                * An error or EOF was encountered.  Put an
+                                * error message to stderr buffer.
+                                */
+                               snprintf(buf, sizeof buf,
+                                   "write stdout: %.50s\r\n", strerror(errno));
+                               buffer_append(&stderr_buffer, buf, strlen(buf));
+                               quit_pending = 1;
+                               return;
+                       }
+               }
+               /* Consume printed data from the buffer. */
+               buffer_consume(&stdout_buffer, len);
+       }
+       /* Write buffered output to stderr. */
+       if (FD_ISSET(fileno(stderr), writeset)) {
+               /* Write as much data as possible. */
+               len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
+                   buffer_len(&stderr_buffer));
+               if (len <= 0) {
+                       if (errno == EINTR || errno == EAGAIN ||
+                           errno == EWOULDBLOCK)
+                               len = 0;
+                       else {
+                               /*
+                                * EOF or error, but can't even print
+                                * error message.
+                                */
+                               quit_pending = 1;
+                               return;
+                       }
+               }
+               /* Consume printed characters from the buffer. */
+               buffer_consume(&stderr_buffer, len);
+       }
+}
+
+/*
+ * Get packets from the connection input buffer, and process them as long as
+ * there are packets available.
+ *
+ * Any unknown packets received during the actual
+ * session cause the session to terminate.  This is
+ * intended to make debugging easier since no
+ * confirmations are sent.  Any compatible protocol
+ * extensions must be negotiated during the
+ * preparatory phase.
+ */
+
+static void
+client_process_buffered_input_packets(void)
+{
+       dispatch_run(DISPATCH_NONBLOCK, &quit_pending,
+           compat20 ? xxx_kex : NULL);
+}
+
+/* scan buf[] for '~' before sending data to the peer */
+
+/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
+void *
+client_new_escape_filter_ctx(int escape_char)
+{
+       struct escape_filter_ctx *ret;
+
+       ret = xmalloc(sizeof(*ret));
+       ret->escape_pending = 0;
+       ret->escape_char = escape_char;
+       return (void *)ret;
+}
+
+/* Free the escape filter context on channel free */
+void
+client_filter_cleanup(int cid, void *ctx)
+{
+       xfree(ctx);
+}
+
+int
+client_simple_escape_filter(Channel *c, char *buf, int len)
+{
+       if (c->extended_usage != CHAN_EXTENDED_WRITE)
+               return 0;
+
+       return process_escapes(c, &c->input, &c->output, &c->extended,
+           buf, len);
+}
+
+static void
+client_channel_closed(int id, void *arg)
+{
+       channel_cancel_cleanup(id);
+       session_closed = 1;
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+}
+
+/*
+ * Implements the interactive session with the server.  This is called after
+ * the user has been authenticated, and a command has been started on the
+ * remote host.  If escape_char != SSH_ESCAPECHAR_NONE, it is the character
+ * used as an escape character for terminating or suspending the session.
+ */
+
+int
+client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
+{
+       fd_set *readset = NULL, *writeset = NULL;
+       double start_time, total_time;
+       int max_fd = 0, max_fd2 = 0, len, rekeying = 0;
+       u_int64_t ibytes, obytes;
+       u_int nalloc = 0;
+       char buf[100];
+
+       debug("Entering interactive session.");
+
+       start_time = get_current_time();
+
+       /* Initialize variables. */
+       escape_pending1 = 0;
+       last_was_cr = 1;
+       exit_status = -1;
+       stdin_eof = 0;
+       buffer_high = 64 * 1024;
+       connection_in = packet_get_connection_in();
+       connection_out = packet_get_connection_out();
+       max_fd = MAX(connection_in, connection_out);
+
+       if (!compat20) {
+               /* enable nonblocking unless tty */
+               if (!isatty(fileno(stdin)))
+                       set_nonblock(fileno(stdin));
+               if (!isatty(fileno(stdout)))
+                       set_nonblock(fileno(stdout));
+               if (!isatty(fileno(stderr)))
+                       set_nonblock(fileno(stderr));
+               max_fd = MAX(max_fd, fileno(stdin));
+               max_fd = MAX(max_fd, fileno(stdout));
+               max_fd = MAX(max_fd, fileno(stderr));
+       }
+       quit_pending = 0;
+       escape_char1 = escape_char_arg;
+
+       /* Initialize buffers. */
+       buffer_init(&stdin_buffer);
+       buffer_init(&stdout_buffer);
+       buffer_init(&stderr_buffer);
+
+       client_init_dispatch();
+
+       /*
+        * Set signal handlers, (e.g. to restore non-blocking mode)
+        * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
+        */
+       if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+               signal(SIGHUP, signal_handler);
+       if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+               signal(SIGINT, signal_handler);
+       if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+               signal(SIGQUIT, signal_handler);
+       if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+               signal(SIGTERM, signal_handler);
+       signal(SIGWINCH, window_change_handler);
+
+       if (have_pty)
+               enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       if (compat20) {
+               session_ident = ssh2_chan_id;
+               if (session_ident != -1) {
+                       if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
+                               channel_register_filter(session_ident,
+                                   client_simple_escape_filter, NULL,
+                                   client_filter_cleanup,
+                                   client_new_escape_filter_ctx(
+                                   escape_char_arg));
+                       }
+                       channel_register_cleanup(session_ident,
+                           client_channel_closed, 0);
+               }
+       } else {
+               /* Check if we should immediately send eof on stdin. */
+               client_check_initial_eof_on_stdin();
+       }
+
+       /* Main loop of the client for the interactive session mode. */
+       while (!quit_pending) {
+
+               /* Process buffered packets sent by the server. */
+               client_process_buffered_input_packets();
+
+               if (compat20 && session_closed && !channel_still_open())
+                       break;
+
+               rekeying = (xxx_kex != NULL && !xxx_kex->done);
+
+               if (rekeying) {
+                       debug("rekeying in progress");
+               } else {
+                       /*
+                        * Make packets of buffered stdin data, and buffer
+                        * them for sending to the server.
+                        */
+                       if (!compat20)
+                               client_make_packets_from_stdin_data();
+
+                       /*
+                        * Make packets from buffered channel data, and
+                        * enqueue them for sending to the server.
+                        */
+                       if (packet_not_very_much_data_to_write())
+                               channel_output_poll();
+
+                       /*
+                        * Check if the window size has changed, and buffer a
+                        * message about it to the server if so.
+                        */
+                       client_check_window_change();
+
+                       if (quit_pending)
+                               break;
+               }
+               /*
+                * Wait until we have something to do (something becomes
+                * available on one of the descriptors).
+                */
+               max_fd2 = max_fd;
+               client_wait_until_can_do_something(&readset, &writeset,
+                   &max_fd2, &nalloc, rekeying);
+
+               if (quit_pending)
+                       break;
+
+               /* Do channel operations unless rekeying in progress. */
+               if (!rekeying) {
+                       channel_after_select(readset, writeset);
+
+#ifdef GSSAPI
+                       if (options.gss_renewal_rekey &&
+                           ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) {
+                               debug("credentials updated - forcing rekey");
+                               need_rekeying = 1;
+                       }
+#endif
+
+                       if (need_rekeying || packet_need_rekeying()) {
+                               debug("need rekeying");
+                               xxx_kex->done = 0;
+                               kex_send_kexinit(xxx_kex);
+                               need_rekeying = 0;
+                       }
+               }
+
+               /* Buffer input from the connection.  */
+               client_process_net_input(readset);
+
+               if (quit_pending)
+                       break;
+
+               if (!compat20) {
+                       /* Buffer data from stdin */
+                       client_process_input(readset);
+                       /*
+                        * Process output to stdout and stderr.  Output to
+                        * the connection is processed elsewhere (above).
+                        */
+                       client_process_output(writeset);
+               }
+
+               if (session_resumed) {
+                       connection_in = packet_get_connection_in();
+                       connection_out = packet_get_connection_out();
+                       max_fd = MAX(max_fd, connection_out);
+                       max_fd = MAX(max_fd, connection_in);
+                       session_resumed = 0;
+               }
+
+               /*
+                * Send as much buffered packet data as possible to the
+                * sender.
+                */
+               if (FD_ISSET(connection_out, writeset))
+                       packet_write_poll();
+
+               /*
+                * If we are a backgrounded control master, and the
+                * timeout has expired without any active client
+                * connections, then quit.
+                */
+               if (control_persist_exit_time > 0) {
+                       if (time(NULL) >= control_persist_exit_time) {
+                               debug("ControlPersist timeout expired");
+                               break;
+                       }
+               }
+       }
+       if (readset)
+               xfree(readset);
+       if (writeset)
+               xfree(writeset);
+
+       /* Terminate the session. */
+
+       /* Stop watching for window change. */
+       signal(SIGWINCH, SIG_DFL);
+
+       if (compat20) {
+               packet_start(SSH2_MSG_DISCONNECT);
+               packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
+               packet_put_cstring("disconnected by user");
+               packet_put_cstring(""); /* language tag */
+               packet_send();
+               packet_write_wait();
+       }
+
+       channel_free_all();
+
+       if (have_pty)
+               leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+
+       /* restore blocking io */
+       if (!isatty(fileno(stdin)))
+               unset_nonblock(fileno(stdin));
+       if (!isatty(fileno(stdout)))
+               unset_nonblock(fileno(stdout));
+       if (!isatty(fileno(stderr)))
+               unset_nonblock(fileno(stderr));
+
+       /*
+        * If there was no shell or command requested, there will be no remote
+        * exit status to be returned.  In that case, clear error code if the
+        * connection was deliberately terminated at this end.
+        */
+       if (no_shell_flag && received_signal == SIGTERM) {
+               received_signal = 0;
+               exit_status = 0;
+       }
+
+       if (received_signal)
+               fatal("Killed by signal %d.", (int) received_signal);
+
+       /*
+        * In interactive mode (with pseudo tty) display a message indicating
+        * that the connection has been closed.
+        */
+       if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
+               snprintf(buf, sizeof buf,
+                   "Connection to %.64s closed.\r\n", host);
+               buffer_append(&stderr_buffer, buf, strlen(buf));
+       }
+
+       /* Output any buffered data for stdout. */
+       if (buffer_len(&stdout_buffer) > 0) {
+               len = atomicio(vwrite, fileno(stdout),
+                   buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer));
+               if (len < 0 || (u_int)len != buffer_len(&stdout_buffer))
+                       error("Write failed flushing stdout buffer.");
+               else
+                       buffer_consume(&stdout_buffer, len);
+       }
+
+       /* Output any buffered data for stderr. */
+       if (buffer_len(&stderr_buffer) > 0) {
+               len = atomicio(vwrite, fileno(stderr),
+                   buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer));
+               if (len < 0 || (u_int)len != buffer_len(&stderr_buffer))
+                       error("Write failed flushing stderr buffer.");
+               else
+                       buffer_consume(&stderr_buffer, len);
+       }
+
+       /* Clear and free any buffers. */
+       memset(buf, 0, sizeof(buf));
+       buffer_free(&stdin_buffer);
+       buffer_free(&stdout_buffer);
+       buffer_free(&stderr_buffer);
+
+       /* Report bytes transferred, and transfer rates. */
+       total_time = get_current_time() - start_time;
+       packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
+       packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
+       verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
+           (unsigned long long)obytes, (unsigned long long)ibytes, total_time);
+       if (total_time > 0)
+               verbose("Bytes per second: sent %.1f, received %.1f",
+                   obytes / total_time, ibytes / total_time);
+       /* Return the exit status of the program. */
+       debug("Exit status %d", exit_status);
+       return exit_status;
+}
+
+/*********/
+
+static void
+client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
+{
+       u_int data_len;
+       char *data = packet_get_string(&data_len);
+       packet_check_eom();
+       buffer_append(&stdout_buffer, data, data_len);
+       memset(data, 0, data_len);
+       xfree(data);
+}
+static void
+client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
+{
+       u_int data_len;
+       char *data = packet_get_string(&data_len);
+       packet_check_eom();
+       buffer_append(&stderr_buffer, data, data_len);
+       memset(data, 0, data_len);
+       xfree(data);
+}
+static void
+client_input_exit_status(int type, u_int32_t seq, void *ctxt)
+{
+       exit_status = packet_get_int();
+       packet_check_eom();
+       /* Acknowledge the exit. */
+       packet_start(SSH_CMSG_EXIT_CONFIRMATION);
+       packet_send();
+       /*
+        * Must wait for packet to be sent since we are
+        * exiting the loop.
+        */
+       packet_write_wait();
+       /* Flag that we want to exit. */
+       quit_pending = 1;
+}
+static void
+client_input_agent_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       int remote_id, sock;
+
+       /* Read the remote channel number from the message. */
+       remote_id = packet_get_int();
+       packet_check_eom();
+
+       /*
+        * Get a connection to the local authentication agent (this may again
+        * get forwarded).
+        */
+       sock = ssh_get_authentication_socket();
+
+       /*
+        * If we could not connect the agent, send an error message back to
+        * the server. This should never happen unless the agent dies,
+        * because authentication forwarding is only enabled if we have an
+        * agent.
+        */
+       if (sock >= 0) {
+               c = channel_new("", SSH_CHANNEL_OPEN, sock, sock,
+                   -1, 0, 0, 0, "authentication agent connection", 1);
+               c->remote_id = remote_id;
+               c->force_drain = 1;
+       }
+       if (c == NULL) {
+               packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(remote_id);
+       } else {
+               /* Send a confirmation to the remote host. */
+               debug("Forwarding authentication connection.");
+               packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+               packet_put_int(remote_id);
+               packet_put_int(c->self);
+       }
+       packet_send();
+}
+
+static Channel *
+client_request_forwarded_tcpip(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       char *listen_address, *originator_address;
+       u_short listen_port, originator_port;
+
+       /* Get rest of the packet */
+       listen_address = packet_get_string(NULL);
+       listen_port = packet_get_int();
+       originator_address = packet_get_string(NULL);
+       originator_port = packet_get_int();
+       packet_check_eom();
+
+       debug("client_request_forwarded_tcpip: listen %s port %d, "
+           "originator %s port %d", listen_address, listen_port,
+           originator_address, originator_port);
+
+       c = channel_connect_by_listen_address(listen_port,
+           "forwarded-tcpip", originator_address);
+
+       xfree(originator_address);
+       xfree(listen_address);
+       return c;
+}
+
+static Channel *
+client_request_x11(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       char *originator;
+       u_short originator_port;
+       int sock;
+
+       if (!options.forward_x11) {
+               error("Warning: ssh server tried X11 forwarding.");
+               error("Warning: this is probably a break-in attempt by a "
+                   "malicious server.");
+               return NULL;
+       }
+       if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) {
+               verbose("Rejected X11 connection after ForwardX11Timeout "
+                   "expired");
+               return NULL;
+       }
+       originator = packet_get_string(NULL);
+       if (datafellows & SSH_BUG_X11FWD) {
+               debug2("buggy server: x11 request w/o originator_port");
+               originator_port = 0;
+       } else {
+               originator_port = packet_get_int();
+       }
+       packet_check_eom();
+       /* XXX check permission */
+       debug("client_request_x11: request from %s %d", originator,
+           originator_port);
+       xfree(originator);
+       sock = x11_connect_display();
+       if (sock < 0)
+               return NULL;
+       c = channel_new("x11",
+           SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+           CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
+       c->force_drain = 1;
+       return c;
+}
+
+static Channel *
+client_request_agent(const char *request_type, int rchan)
+{
+       Channel *c = NULL;
+       int sock;
+
+       if (!options.forward_agent) {
+               error("Warning: ssh server tried agent forwarding.");
+               error("Warning: this is probably a break-in attempt by a "
+                   "malicious server.");
+               return NULL;
+       }
+       sock = ssh_get_authentication_socket();
+       if (sock < 0)
+               return NULL;
+       c = channel_new("authentication agent connection",
+           SSH_CHANNEL_OPEN, sock, sock, -1,
+           CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
+           "authentication agent connection", 1);
+       c->force_drain = 1;
+       return c;
+}
+
+int
+client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
+{
+       Channel *c;
+       int fd;
+
+       if (tun_mode == SSH_TUNMODE_NO)
+               return 0;
+
+       if (!compat20) {
+               error("Tunnel forwarding is not supported for protocol 1");
+               return -1;
+       }
+
+       debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
+
+       /* Open local tunnel device */
+       if ((fd = tun_open(local_tun, tun_mode)) == -1) {
+               error("Tunnel device open failed.");
+               return -1;
+       }
+
+       c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+           CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+       c->datagram = 1;
+
+#if defined(SSH_TUN_FILTER)
+       if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
+               channel_register_filter(c->self, sys_tun_infilter,
+                   sys_tun_outfilter, NULL, NULL);
+#endif
+
+       packet_start(SSH2_MSG_CHANNEL_OPEN);
+       packet_put_cstring("tun@openssh.com");
+       packet_put_int(c->self);
+       packet_put_int(c->local_window_max);
+       packet_put_int(c->local_maxpacket);
+       packet_put_int(tun_mode);
+       packet_put_int(remote_tun);
+       packet_send();
+
+       return 0;
+}
+
+/* XXXX move to generic input handler */
+static void
+client_input_channel_open(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       char *ctype;
+       int rchan;
+       u_int rmaxpack, rwindow, len;
+
+       ctype = packet_get_string(&len);
+       rchan = packet_get_int();
+       rwindow = packet_get_int();
+       rmaxpack = packet_get_int();
+
+       debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
+           ctype, rchan, rwindow, rmaxpack);
+
+       if (strcmp(ctype, "forwarded-tcpip") == 0) {
+               c = client_request_forwarded_tcpip(ctype, rchan);
+       } else if (strcmp(ctype, "x11") == 0) {
+               c = client_request_x11(ctype, rchan);
+       } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
+               c = client_request_agent(ctype, rchan);
+       }
+/* XXX duplicate : */
+       if (c != NULL) {
+               debug("confirm %s", ctype);
+               c->remote_id = rchan;
+               c->remote_window = rwindow;
+               c->remote_maxpacket = rmaxpack;
+               if (c->type != SSH_CHANNEL_CONNECTING) {
+                       packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
+                       packet_put_int(c->remote_id);
+                       packet_put_int(c->self);
+                       packet_put_int(c->local_window);
+                       packet_put_int(c->local_maxpacket);
+                       packet_send();
+               }
+       } else {
+               debug("failure %s", ctype);
+               packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
+               packet_put_int(rchan);
+               packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
+               if (!(datafellows & SSH_BUG_OPENFAILURE)) {
+                       packet_put_cstring("open failed");
+                       packet_put_cstring("");
+               }
+               packet_send();
+       }
+       xfree(ctype);
+}
+static void
+client_input_channel_req(int type, u_int32_t seq, void *ctxt)
+{
+       Channel *c = NULL;
+       int exitval, id, reply, success = 0;
+       char *rtype;
+
+       id = packet_get_int();
+       rtype = packet_get_string(NULL);
+       reply = packet_get_char();
+
+       debug("client_input_channel_req: channel %d rtype %s reply %d",
+           id, rtype, reply);
+
+       if (id == -1) {
+               error("client_input_channel_req: request for channel -1");
+       } else if ((c = channel_lookup(id)) == NULL) {
+               error("client_input_channel_req: channel %d: "
+                   "unknown channel", id);
+       } else if (strcmp(rtype, "eow@openssh.com") == 0) {
+               packet_check_eom();
+               chan_rcvd_eow(c);
+       } else if (strcmp(rtype, "exit-status") == 0) {
+               exitval = packet_get_int();
+               if (c->ctl_chan != -1) {
+                       mux_exit_message(c, exitval);
+                       success = 1;
+               } else if (id == session_ident) {
+                       /* Record exit value of local session */
+                       success = 1;
+                       exit_status = exitval;
+               } else {
+                       /* Probably for a mux channel that has already closed */
+                       debug("%s: no sink for exit-status on channel %d",
+                           __func__, id);
+               }
+               packet_check_eom();
+       }
+       if (reply && c != NULL) {
+               packet_start(success ?
+                   SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
+               packet_put_int(c->remote_id);
+               packet_send();
+       }
+       xfree(rtype);
+}
+static void
+client_input_global_request(int type, u_int32_t seq, void *ctxt)
+{
+       char *rtype;
+       int want_reply;
+       int success = 0;
+
+       rtype = packet_get_string(NULL);
+       want_reply = packet_get_char();
+       debug("client_input_global_request: rtype %s want_reply %d",
+           rtype, want_reply);
+       if (want_reply) {
+               packet_start(success ?
+                   SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
+               packet_send();
+               packet_write_wait();
+       }
+       xfree(rtype);
+}
+
+void
+client_session2_setup(int id, int want_tty, int want_subsystem,
+    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
+{
+       int len;
+       Channel *c = NULL;
+
+       debug2("%s: id %d", __func__, id);
+
+       if ((c = channel_lookup(id)) == NULL)
+               fatal("client_session2_setup: channel %d: unknown channel", id);
+
+       packet_set_interactive(want_tty,
+           options.ip_qos_interactive, options.ip_qos_bulk);
+
+       if (want_tty) {
+               struct winsize ws;
+
+               /* Store window size in the packet. */
+               if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
+                       memset(&ws, 0, sizeof(ws));
+
+               channel_request_start(id, "pty-req", 1);
+               client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
+               packet_put_cstring(term != NULL ? term : "");
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+               if (tiop == NULL)
+                       tiop = get_saved_tio();
+               tty_make_modes(-1, tiop);
+               packet_send();
+               /* XXX wait for reply */
+               c->client_tty = 1;
+       }
+
+       /* Transfer any environment variables from client to server */
+       if (options.num_send_env != 0 && env != NULL) {
+               int i, j, matched;
+               char *name, *val;
+
+               debug("Sending environment.");
+               for (i = 0; env[i] != NULL; i++) {
+                       /* Split */
+                       name = xstrdup(env[i]);
+                       if ((val = strchr(name, '=')) == NULL) {
+                               xfree(name);
+                               continue;
+                       }
+                       *val++ = '\0';
+
+                       matched = 0;
+                       for (j = 0; j < options.num_send_env; j++) {
+                               if (match_pattern(name, options.send_env[j])) {
+                                       matched = 1;
+                                       break;
+                               }
+                       }
+                       if (!matched) {
+                               debug3("Ignored env %s", name);
+                               xfree(name);
+                               continue;
+                       }
+
+                       debug("Sending env %s = %s", name, val);
+                       channel_request_start(id, "env", 0);
+                       packet_put_cstring(name);
+                       packet_put_cstring(val);
+                       packet_send();
+                       xfree(name);
+               }
+       }
+
+       len = buffer_len(cmd);
+       if (len > 0) {
+               if (len > 900)
+                       len = 900;
+               if (want_subsystem) {
+                       debug("Sending subsystem: %.*s",
+                           len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "subsystem", 1);
+                       client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
+               } else {
+                       debug("Sending command: %.*s",
+                           len, (u_char*)buffer_ptr(cmd));
+                       channel_request_start(id, "exec", 1);
+                       client_expect_confirm(id, "exec", CONFIRM_CLOSE);
+               }
+               packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
+               packet_send();
+       } else {
+               channel_request_start(id, "shell", 1);
+               client_expect_confirm(id, "shell", CONFIRM_CLOSE);
+               packet_send();
+       }
+}
+
+static void
+client_init_dispatch_20(void)
+{
+       dispatch_init(&dispatch_protocol_error);
+
+       dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+       dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+       dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
+       dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+       dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
+       dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
+       dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
+
+       /* rekeying */
+       dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+
+       /* global request reply messages */
+       dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
+       dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
+}
+
+static void
+client_init_dispatch_13(void)
+{
+       dispatch_init(NULL);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+       dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+       dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
+       dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
+       dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
+       dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
+
+       dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
+           &client_input_agent_open : &deny_input_open);
+       dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
+           &x11_input_open : &deny_input_open);
+}
+
+static void
+client_init_dispatch_15(void)
+{
+       client_init_dispatch_13();
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
+       dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
+}
+
+static void
+client_init_dispatch(void)
+{
+       if (compat20)
+               client_init_dispatch_20();
+       else if (compat13)
+               client_init_dispatch_13();
+       else
+               client_init_dispatch_15();
+}
+
+void
+client_stop_mux(void)
+{
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+       /*
+        * If we are in persist mode, signal that we should close when all
+        * active channels are closed.
+        */
+       if (options.control_persist) {
+               session_closed = 1;
+               setproctitle("[stopped mux]");
+       }
+}
+
+/* client specific fatal cleanup */
+void
+cleanup_exit(int i)
+{
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+       leave_non_blocking();
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+       ssh_kill_proxy_command();
+       _exit(i);
+}
diff --git a/.pc/ssh1-keepalive.patch/ssh_config.5 b/.pc/ssh1-keepalive.patch/ssh_config.5
new file mode 100644 (file)
index 0000000..ea87d98
--- /dev/null
@@ -0,0 +1,1343 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Nm ~/.ssh/config
+.Nm /etc/ssh/ssh_config
+.Sh DESCRIPTION
+.Xr ssh 1
+obtains configuration data from the following sources in
+the following order:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+command-line options
+.It
+user's configuration file
+.Pq Pa ~/.ssh/config
+.It
+system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+.El
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections separated by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp ,
+and
+.Nm sftp
+.Fl o
+option.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+If more than one pattern is provided, they should be separated by whitespace.
+A single
+.Ql *
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e. the name is not converted to
+a canonicalized host name before matching).
+.Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm AddressFamily
+Specifies which address family to use when connecting.
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Use the specified address on the local machine as the source address of
+the connection.
+Only useful on systems with more than one address.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge-response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Xr ssh 1
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote, and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared.
+This option is primarily useful when used from the
+.Xr ssh 1
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout (in seconds) used when connecting to the
+SSH server, instead of using the default system TCP timeout.
+This value is used only when the target is down or really unreachable,
+not when it refuses the connection.
+.It Cm ControlMaster
+Enables the sharing of multiple sessions over a single network connection.
+When set to
+.Dq yes ,
+.Xr ssh 1
+will listen for connections on a control socket specified using the
+.Cm ControlPath
+argument.
+Additional sessions can connect to this socket using the same
+.Cm ControlPath
+with
+.Cm ControlMaster
+set to
+.Dq no
+(the default).
+These sessions will try to reuse the master instance's network connection
+rather than initiating new ones, but will fall back to connecting normally
+if the control socket does not exist, or is not listening.
+.Pp
+Setting this to
+.Dq ask
+will cause ssh
+to listen for control connections, but require confirmation using the
+.Ev SSH_ASKPASS
+program before they are accepted (see
+.Xr ssh-add 1
+for details).
+If the
+.Cm ControlPath
+cannot be opened,
+ssh will continue without connecting to a master instance.
+.Pp
+X11 and
+.Xr ssh-agent 1
+forwarding is supported over these multiplexed connections, however the
+display and agent forwarded will be the one belonging to the master
+connection i.e. it is not possible to forward multiple displays or agents.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
+.It Cm ControlPath
+Specify the path to the control socket used for connection sharing as described
+in the
+.Cm ControlMaster
+section above or the string
+.Dq none
+to disable connection sharing.
+In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
+.Ql %l
+will be substituted by the local host name (including any domain name),
+.Ql %h
+will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
+.Ql %p
+the port,
+.Ql %r
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+at least %h, %p, and %r.
+This ensures that shared connections are uniquely identified.
+.It Cm ControlPersist
+When used in conjunction with
+.Cm ControlMaster ,
+specifies that the master connection should remain open
+in the background (waiting for future client connections)
+after the initial client connection has been closed.
+If set to
+.Dq no ,
+then the master connection will not be placed into the background,
+and will close as soon as the initial client connection is closed.
+If set to
+.Dq yes ,
+then the master connection will remain in the background indefinitely
+(until killed or closed via a mechanism such as the
+.Xr ssh 1
+.Dq Fl O No exit
+option).
+If set to a time in seconds, or a time in any of the formats documented in
+.Xr sshd_config 5 ,
+then the backgrounded master connection will automatically terminate
+after it has remained idle (with no client connections) for the
+specified time.
+.It Cm DynamicForward
+Specifies that a TCP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+.Pp
+The argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port .
+.Sm on
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.Pp
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Xr ssh 1
+will act as a SOCKS server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm EnableSSHKeysign
+Setting this option to
+.Dq yes
+in the global client configuration file
+.Pa /etc/ssh/ssh_config
+enables the use of the helper program
+.Xr ssh-keysign 8
+during
+.Cm HostbasedAuthentication .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option should be placed in the non-hostspecific section.
+See
+.Xr ssh-keysign 8
+for more information.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ExitOnForwardFailure
+Specifies whether
+.Xr ssh 1
+should terminate the connection if it cannot set up all requested
+dynamic, tunnel, local, and remote port forwardings.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's Unix-domain socket)
+can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X11 authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring
+if the
+.Cm ForwardX11Trusted
+option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
+.It Cm ForwardX11Trusted
+If this option is set to
+.Dq yes ,
+remote X11 clients will have full access to the original X11 display.
+.Pp
+If this option is set to
+.Dq no ,
+remote X11 clients will be considered untrusted and prevented
+from stealing or tampering with data belonging to trusted X11
+clients.
+Furthermore, the
+.Xr xauth 1
+token used for the session will be set to expire after 20 minutes.
+Remote clients will be refused access after this time.
+.Pp
+The default is
+.Dq no .
+.Pp
+See the X11 SECURITY extension specification for full details on
+the restrictions imposed on untrusted clients.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Xr ssh 1
+binds local port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
+.It Cm GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when 
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
+.It Cm GSSAPIDelegateCredentials
+Forward (delegate) credentials to the server.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI.
+.It Cm HashKnownHosts
+Indicates that
+.Xr ssh 1
+should hash host names and addresses when they are added to
+.Pa ~/.ssh/known_hosts .
+These hashed names may be used normally by
+.Xr ssh 1
+and
+.Xr sshd 8 ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+The default is
+.Dq no .
+Note that existing names and addresses in known hosts files
+will not be converted automatically,
+but may be manually hashed using
+.Xr ssh-keygen 1 .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
+ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-rsa,ssh-dss
+.Ed
+.Pp
+If hostkeys are known for the destination host then this default is modified
+to prefer their algorithms.
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling SSH connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+If the hostname contains the character sequence
+.Ql %h ,
+then this will be replaced with the host name specified on the command line
+(this is useful for manipulating unqualified names).
+The default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentitiesOnly
+Specifies that
+.Xr ssh 1
+should only use the authentication identity files configured in the
+.Nm
+files,
+even if
+.Xr ssh-agent 1
+offers more identities.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option is intended for situations where ssh-agent
+offers many different identities.
+The default is
+.Dq no .
+.It Cm IdentityFile
+Specifies a file from which the user's DSA, ECDSA or DSA authentication
+identity is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+.Xr ssh 1
+will try to load certificate information from the filename obtained by
+appending
+.Pa -cert.pub
+to the path of a specified
+.Cm IdentityFile .
+.Pp
+The file name may use the tilde
+syntax to refer to a user's home directory or one of the following
+escape characters:
+.Ql %d
+(local user's home directory),
+.Ql %u
+(local user name),
+.Ql %l
+(local host name),
+.Ql %h
+(remote host name) or
+.Ql %r
+(remote user name).
+.Pp
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KbdInteractiveAuthentication
+Specifies whether to use keyboard-interactive authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm KbdInteractiveDevices
+Specifies the list of methods to use in keyboard-interactive authentication.
+Multiple method names must be comma-separated.
+The default is to use the server specified list.
+The methods available vary depending on what the server supports.
+For an OpenSSH server,
+it may be zero or more of:
+.Dq bsdauth ,
+.Dq pam ,
+and
+.Dq skey .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
+diffie-hellman-group-exchange-sha256,
+diffie-hellman-group-exchange-sha1,
+diffie-hellman-group14-sha1,
+diffie-hellman-group1-sha1
+.Ed
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+The following escape character substitutions will be performed:
+.Ql %d
+(local user's home directory),
+.Ql %h
+(remote host name),
+.Ql %l
+(local host name),
+.Ql %n
+(host name as provided on the command line),
+.Ql %p
+(remote port),
+.Ql %r
+(remote user name) or
+.Ql %u
+(local user name).
+.Pp
+The command is run synchronously and does not have access to the
+session of the
+.Xr ssh 1
+that spawned it.
+It should not be used for interactive commands.
+.Pp
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
+.It Cm LocalForward
+Specifies that a TCP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional forwardings can be
+given on the command line.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr ssh 1 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+The default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic !\& Ns Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm PKCS11Provider
+Specifies which PKCS#11 provider to use.
+The argument to this keyword is the PKCS#11 shared library
+.Xr ssh 1
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Cm Port
+Specifies the port number to connect on the remote host.
+The default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods.
+This allows a client to prefer one method (e.g.\&
+.Cm keyboard-interactive )
+over another method (e.g.\&
+.Cm password ) .
+The default is:
+.Bd -literal -offset indent
+gssapi-with-mic,hostbased,publickey,
+keyboard-interactive,password
+.Ed
+.It Cm Protocol
+Specifies the protocol versions
+.Xr ssh 1
+should support in order of preference.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+When this option is set to
+.Dq 2,1
+.Nm ssh
+will try version 2 and fall back to version 1
+if version 2 is not available.
+The default is
+.Sq 2 .
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+the user's shell.
+In the command string, any occurrence of
+.Ql %h
+will be substituted by the host name to
+connect,
+.Ql %p
+by the port, and
+.Ql %r
+by the remote user name.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Setting the command to
+.Dq none
+disables this option entirely.
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+This directive is useful in conjunction with
+.Xr nc 1
+and its proxy support.
+For example, the following directive would connect via an HTTP proxy at
+192.0.2.0:
+.Bd -literal -offset 3n
+ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
+.Ed
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RekeyLimit
+Specifies the maximum amount of data that may be transmitted before the
+session key is renegotiated.
+The argument is the number of bytes, with an optional suffix of
+.Sq K ,
+.Sq M ,
+or
+.Sq G
+to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
+The default is between
+.Sq 1G
+and
+.Sq 4G ,
+depending on the cipher.
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+.Pp
+If the
+.Ar bind_address
+is not specified, the default is to only bind to loopback addresses.
+If the
+.Ar bind_address
+is
+.Ql *
+or an empty string, then the forwarding is requested to listen on all
+interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Xr ssh 1
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SendEnv
+Specifies what variables from the local
+.Xr environ 7
+should be sent to the server.
+Note that environment passing is only supported for protocol 2.
+The server must also support it, and the server must be configured to
+accept these environment variables.
+Refer to
+.Cm AcceptEnv
+in
+.Xr sshd_config 5
+for how to configure the server.
+Variables are specified by name, which may contain wildcard characters.
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm SendEnv
+directives.
+The default is not to send any environment variables.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm ServerAliveCountMax
+Sets the number of server alive messages (see below) which may be
+sent without
+.Xr ssh 1
+receiving any messages back from the server.
+If this threshold is reached while server alive messages are being sent,
+ssh will disconnect from the server, terminating the session.
+It is important to note that the use of server alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The server alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The server alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If, for example,
+.Cm ServerAliveInterval
+(see below) is set to 15 and
+.Cm ServerAliveCountMax
+is left at the default, if the server becomes unresponsive,
+ssh will disconnect after approximately 45 seconds.
+This option applies to protocol version 2 only.
+.It Cm ServerAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the server,
+.Xr ssh 1
+will send a message through the encrypted
+channel to request a response from the server.
+The default
+is 0, indicating that these messages will not be sent to the server.
+This option applies to protocol version 2 only.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will never automatically add host keys to the
+.Pa ~/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+though it can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained or when connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+ssh will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+ssh will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm Tunnel
+Request
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2),
+or
+.Dq no .
+Specifying
+.Dq yes
+requests the default tunnel mode, which is
+.Dq point-to-point .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Specifies the
+.Xr tun 4
+devices to open on the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The argument must be
+.Sm off
+.Ar local_tun Op : Ar remote_tun .
+.Sm on
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+The default is
+.Dq any:any .
+.It Cm UseBlacklistedKeys
+Specifies whether
+.Xr ssh 1
+should use keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 )
+for authentication.
+If
+.Dq yes ,
+then attempts to use compromised keys for authentication will be logged but
+accepted.
+It is strongly recommended that this be used only to install new authorized
+keys on the remote system, and even then only with the utmost care.
+If
+.Dq no ,
+then attempts to use compromised keys for authentication will be prevented.
+The default is
+.Dq no .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+If set to
+.Dq yes ,
+.Xr ssh 1
+must be setuid root.
+Note that this option must be set to
+.Dq yes
+for
+.Cm RhostsRSAAuthentication
+with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
+.It Cm VerifyHostKeyDNS
+Specifies whether to verify the remote key using DNS and SSHFP resource
+records.
+If this option is set to
+.Dq yes ,
+the client will implicitly trust keys that match a secure fingerprint
+from DNS.
+Insecure fingerprints will be handled as if this option was set to
+.Dq ask .
+If this option is set to
+.Dq ask ,
+information on fingerprint match will be displayed, but the user will still
+need to confirm new host keys according to the
+.Cm StrictHostKeyChecking
+option.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.Pp
+See also
+.Sx VERIFYING HOST KEYS
+in
+.Xr ssh 1 .
+.It Cm VisualHostKey
+If this flag is set to
+.Dq yes ,
+an ASCII art representation of the remote host key fingerprint is
+printed in addition to the hex fingerprint string at login and
+for unknown host keys.
+If this flag is set to
+.Dq no ,
+no fingerprint strings are printed at login and
+only the hex fingerprint string will be printed for unknown host keys.
+The default is
+.Dq no .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh PATTERNS
+A
+.Em pattern
+consists of zero or more non-whitespace characters,
+.Sq *
+(a wildcard that matches zero or more characters),
+or
+.Sq ?\&
+(a wildcard that matches exactly one character).
+For example, to specify a set of declarations for any host in the
+.Dq .co.uk
+set of domains,
+the following pattern could be used:
+.Pp
+.Dl Host *.co.uk
+.Pp
+The following pattern
+would match any host in the 192.168.0.[0-9] network range:
+.Pp
+.Dl Host 192.168.0.?
+.Pp
+A
+.Em pattern-list
+is a comma-separated list of patterns.
+Patterns within pattern-lists may be negated
+by preceding them with an exclamation mark
+.Pq Sq !\& .
+For example,
+to allow a key to be used from anywhere within an organisation
+except from the
+.Dq dialup
+pool,
+the following entry (in authorized_keys) could be used:
+.Pp
+.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the SSH client.
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh SEE ALSO
+.Xr ssh 1
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/syslog-level-silent.patch/log.c b/.pc/syslog-level-silent.patch/log.c
new file mode 100644 (file)
index 0000000..ad5a10b
--- /dev/null
@@ -0,0 +1,430 @@
+/* $OpenBSD: log.c,v 1.42 2011/06/17 21:44:30 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <errno.h>
+#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
+# include <vis.h>
+#endif
+
+#include "xmalloc.h"
+#include "log.h"
+
+static LogLevel log_level = SYSLOG_LEVEL_INFO;
+static int log_on_stderr = 1;
+static int log_facility = LOG_AUTH;
+static char *argv0;
+static log_handler_fn *log_handler;
+static void *log_handler_ctx;
+
+extern char *__progname;
+
+#define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL)
+#define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL)
+
+/* textual representation of log-facilities/levels */
+
+static struct {
+       const char *name;
+       SyslogFacility val;
+} log_facilities[] = {
+       { "DAEMON",     SYSLOG_FACILITY_DAEMON },
+       { "USER",       SYSLOG_FACILITY_USER },
+       { "AUTH",       SYSLOG_FACILITY_AUTH },
+#ifdef LOG_AUTHPRIV
+       { "AUTHPRIV",   SYSLOG_FACILITY_AUTHPRIV },
+#endif
+       { "LOCAL0",     SYSLOG_FACILITY_LOCAL0 },
+       { "LOCAL1",     SYSLOG_FACILITY_LOCAL1 },
+       { "LOCAL2",     SYSLOG_FACILITY_LOCAL2 },
+       { "LOCAL3",     SYSLOG_FACILITY_LOCAL3 },
+       { "LOCAL4",     SYSLOG_FACILITY_LOCAL4 },
+       { "LOCAL5",     SYSLOG_FACILITY_LOCAL5 },
+       { "LOCAL6",     SYSLOG_FACILITY_LOCAL6 },
+       { "LOCAL7",     SYSLOG_FACILITY_LOCAL7 },
+       { NULL,         SYSLOG_FACILITY_NOT_SET }
+};
+
+static struct {
+       const char *name;
+       LogLevel val;
+} log_levels[] =
+{
+       { "QUIET",      SYSLOG_LEVEL_QUIET },
+       { "FATAL",      SYSLOG_LEVEL_FATAL },
+       { "ERROR",      SYSLOG_LEVEL_ERROR },
+       { "INFO",       SYSLOG_LEVEL_INFO },
+       { "VERBOSE",    SYSLOG_LEVEL_VERBOSE },
+       { "DEBUG",      SYSLOG_LEVEL_DEBUG1 },
+       { "DEBUG1",     SYSLOG_LEVEL_DEBUG1 },
+       { "DEBUG2",     SYSLOG_LEVEL_DEBUG2 },
+       { "DEBUG3",     SYSLOG_LEVEL_DEBUG3 },
+       { NULL,         SYSLOG_LEVEL_NOT_SET }
+};
+
+SyslogFacility
+log_facility_number(char *name)
+{
+       int i;
+
+       if (name != NULL)
+               for (i = 0; log_facilities[i].name; i++)
+                       if (strcasecmp(log_facilities[i].name, name) == 0)
+                               return log_facilities[i].val;
+       return SYSLOG_FACILITY_NOT_SET;
+}
+
+const char *
+log_facility_name(SyslogFacility facility)
+{
+       u_int i;
+
+       for (i = 0;  log_facilities[i].name; i++)
+               if (log_facilities[i].val == facility)
+                       return log_facilities[i].name;
+       return NULL;
+}
+
+LogLevel
+log_level_number(char *name)
+{
+       int i;
+
+       if (name != NULL)
+               for (i = 0; log_levels[i].name; i++)
+                       if (strcasecmp(log_levels[i].name, name) == 0)
+                               return log_levels[i].val;
+       return SYSLOG_LEVEL_NOT_SET;
+}
+
+const char *
+log_level_name(LogLevel level)
+{
+       u_int i;
+
+       for (i = 0; log_levels[i].name != NULL; i++)
+               if (log_levels[i].val == level)
+                       return log_levels[i].name;
+       return NULL;
+}
+
+/* Error messages that should be logged. */
+
+void
+error(const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(SYSLOG_LEVEL_ERROR, fmt, args);
+       va_end(args);
+}
+
+void
+sigdie(const char *fmt,...)
+{
+#ifdef DO_LOG_SAFE_IN_SIGHAND
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(SYSLOG_LEVEL_FATAL, fmt, args);
+       va_end(args);
+#endif
+       _exit(1);
+}
+
+
+/* Log this message (information that usually should go to the log). */
+
+void
+logit(const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(SYSLOG_LEVEL_INFO, fmt, args);
+       va_end(args);
+}
+
+/* More detailed messages (information that does not need to go to the log). */
+
+void
+verbose(const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
+       va_end(args);
+}
+
+/* Debugging messages that should not be logged during normal operation. */
+
+void
+debug(const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
+       va_end(args);
+}
+
+void
+debug2(const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
+       va_end(args);
+}
+
+void
+debug3(const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
+       va_end(args);
+}
+
+/*
+ * Initialize the log.
+ */
+
+void
+log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
+{
+#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
+       struct syslog_data sdata = SYSLOG_DATA_INIT;
+#endif
+
+       argv0 = av0;
+
+       switch (level) {
+       case SYSLOG_LEVEL_QUIET:
+       case SYSLOG_LEVEL_FATAL:
+       case SYSLOG_LEVEL_ERROR:
+       case SYSLOG_LEVEL_INFO:
+       case SYSLOG_LEVEL_VERBOSE:
+       case SYSLOG_LEVEL_DEBUG1:
+       case SYSLOG_LEVEL_DEBUG2:
+       case SYSLOG_LEVEL_DEBUG3:
+               log_level = level;
+               break;
+       default:
+               fprintf(stderr, "Unrecognized internal syslog level code %d\n",
+                   (int) level);
+               exit(1);
+       }
+
+       log_handler = NULL;
+       log_handler_ctx = NULL;
+
+       log_on_stderr = on_stderr;
+       if (on_stderr)
+               return;
+
+       switch (facility) {
+       case SYSLOG_FACILITY_DAEMON:
+               log_facility = LOG_DAEMON;
+               break;
+       case SYSLOG_FACILITY_USER:
+               log_facility = LOG_USER;
+               break;
+       case SYSLOG_FACILITY_AUTH:
+               log_facility = LOG_AUTH;
+               break;
+#ifdef LOG_AUTHPRIV
+       case SYSLOG_FACILITY_AUTHPRIV:
+               log_facility = LOG_AUTHPRIV;
+               break;
+#endif
+       case SYSLOG_FACILITY_LOCAL0:
+               log_facility = LOG_LOCAL0;
+               break;
+       case SYSLOG_FACILITY_LOCAL1:
+               log_facility = LOG_LOCAL1;
+               break;
+       case SYSLOG_FACILITY_LOCAL2:
+               log_facility = LOG_LOCAL2;
+               break;
+       case SYSLOG_FACILITY_LOCAL3:
+               log_facility = LOG_LOCAL3;
+               break;
+       case SYSLOG_FACILITY_LOCAL4:
+               log_facility = LOG_LOCAL4;
+               break;
+       case SYSLOG_FACILITY_LOCAL5:
+               log_facility = LOG_LOCAL5;
+               break;
+       case SYSLOG_FACILITY_LOCAL6:
+               log_facility = LOG_LOCAL6;
+               break;
+       case SYSLOG_FACILITY_LOCAL7:
+               log_facility = LOG_LOCAL7;
+               break;
+       default:
+               fprintf(stderr,
+                   "Unrecognized internal syslog facility code %d\n",
+                   (int) facility);
+               exit(1);
+       }
+
+       /*
+        * If an external library (eg libwrap) attempts to use syslog
+        * immediately after reexec, syslog may be pointing to the wrong
+        * facility, so we force an open/close of syslog here.
+        */
+#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
+       openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
+       closelog_r(&sdata);
+#else
+       openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
+       closelog();
+#endif
+}
+
+#define MSGBUFSIZ 1024
+
+void
+set_log_handler(log_handler_fn *handler, void *ctx)
+{
+       log_handler = handler;
+       log_handler_ctx = ctx;
+}
+
+void
+do_log2(LogLevel level, const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(level, fmt, args);
+       va_end(args);
+}
+
+void
+do_log(LogLevel level, const char *fmt, va_list args)
+{
+#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
+       struct syslog_data sdata = SYSLOG_DATA_INIT;
+#endif
+       char msgbuf[MSGBUFSIZ];
+       char fmtbuf[MSGBUFSIZ];
+       char *txt = NULL;
+       int pri = LOG_INFO;
+       int saved_errno = errno;
+       log_handler_fn *tmp_handler;
+
+       if (level > log_level)
+               return;
+
+       switch (level) {
+       case SYSLOG_LEVEL_FATAL:
+               if (!log_on_stderr)
+                       txt = "fatal";
+               pri = LOG_CRIT;
+               break;
+       case SYSLOG_LEVEL_ERROR:
+               if (!log_on_stderr)
+                       txt = "error";
+               pri = LOG_ERR;
+               break;
+       case SYSLOG_LEVEL_INFO:
+               pri = LOG_INFO;
+               break;
+       case SYSLOG_LEVEL_VERBOSE:
+               pri = LOG_INFO;
+               break;
+       case SYSLOG_LEVEL_DEBUG1:
+               txt = "debug1";
+               pri = LOG_DEBUG;
+               break;
+       case SYSLOG_LEVEL_DEBUG2:
+               txt = "debug2";
+               pri = LOG_DEBUG;
+               break;
+       case SYSLOG_LEVEL_DEBUG3:
+               txt = "debug3";
+               pri = LOG_DEBUG;
+               break;
+       default:
+               txt = "internal error";
+               pri = LOG_ERR;
+               break;
+       }
+       if (txt != NULL && log_handler == NULL) {
+               snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
+               vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
+       } else {
+               vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
+       }
+       strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
+           log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
+       if (log_handler != NULL) {
+               /* Avoid recursion */
+               tmp_handler = log_handler;
+               log_handler = NULL;
+               tmp_handler(level, fmtbuf, log_handler_ctx);
+               log_handler = tmp_handler;
+       } else if (log_on_stderr) {
+               snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
+               write(STDERR_FILENO, msgbuf, strlen(msgbuf));
+       } else {
+#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
+               openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
+               syslog_r(pri, &sdata, "%.500s", fmtbuf);
+               closelog_r(&sdata);
+#else
+               openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
+               syslog(pri, "%.500s", fmtbuf);
+               closelog();
+#endif
+       }
+       errno = saved_errno;
+}
diff --git a/.pc/syslog-level-silent.patch/ssh.c b/.pc/syslog-level-silent.patch/ssh.c
new file mode 100644 (file)
index 0000000..b589966
--- /dev/null
@@ -0,0 +1,1604 @@
+/* $OpenBSD: ssh.c,v 1.364 2011/08/02 23:15:03 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Ssh client program.  This program can be used to log into a remote machine.
+ * The software supports strong authentication, encryption, and forwarding
+ * of X11, TCP/IP, and authentication connections.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ *
+ * Copyright (c) 1999 Niels Provos.  All rights reserved.
+ * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl.  All rights reserved.
+ *
+ * Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
+ * in Canada (German citizen).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "openbsd-compat/openssl-compat.h"
+#include "openbsd-compat/sys-queue.h"
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
+#include "canohost.h"
+#include "compat.h"
+#include "cipher.h"
+#include "packet.h"
+#include "buffer.h"
+#include "channels.h"
+#include "key.h"
+#include "authfd.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "dispatch.h"
+#include "clientloop.h"
+#include "log.h"
+#include "readconf.h"
+#include "sshconnect.h"
+#include "misc.h"
+#include "kex.h"
+#include "mac.h"
+#include "sshpty.h"
+#include "match.h"
+#include "msg.h"
+#include "uidswap.h"
+#include "roaming.h"
+#include "version.h"
+
+#ifdef ENABLE_PKCS11
+#include "ssh-pkcs11.h"
+#endif
+
+extern char *__progname;
+
+/* Saves a copy of argv for setproctitle emulation */
+#ifndef HAVE_SETPROCTITLE
+static char **saved_av;
+#endif
+
+/* Flag indicating whether debug mode is on.  May be set on the command line. */
+int debug_flag = 0;
+
+/* Flag indicating whether a tty should be requested */
+int tty_flag = 0;
+
+/* don't exec a shell */
+int no_shell_flag = 0;
+
+/*
+ * Flag indicating that nothing should be read from stdin.  This can be set
+ * on the command line.
+ */
+int stdin_null_flag = 0;
+
+/*
+ * Flag indicating that the current process should be backgrounded and
+ * a new slave launched in the foreground for ControlPersist.
+ */
+int need_controlpersist_detach = 0;
+
+/* Copies of flags for ControlPersist foreground slave */
+int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
+
+/*
+ * Flag indicating that ssh should fork after authentication.  This is useful
+ * so that the passphrase can be entered manually, and then ssh goes to the
+ * background.
+ */
+int fork_after_authentication_flag = 0;
+
+/* forward stdio to remote host and port */
+char *stdio_forward_host = NULL;
+int stdio_forward_port = 0;
+
+/*
+ * General data structure for command line options and options configurable
+ * in configuration files.  See readconf.h.
+ */
+Options options;
+
+/* optional user configfile */
+char *config = NULL;
+
+/*
+ * Name of the host we are connecting to.  This is the name given on the
+ * command line, or the HostName specified for the user-supplied name in a
+ * configuration file.
+ */
+char *host;
+
+/* socket address the host resolves to */
+struct sockaddr_storage hostaddr;
+
+/* Private host keys. */
+Sensitive sensitive_data;
+
+/* Original real UID. */
+uid_t original_real_uid;
+uid_t original_effective_uid;
+
+/* command to be executed */
+Buffer command;
+
+/* Should we execute a command or invoke a subsystem? */
+int subsystem_flag = 0;
+
+/* # of replies received for global requests */
+static int remote_forward_confirms_received = 0;
+
+/* mux.c */
+extern int muxserver_sock;
+extern u_int muxclient_command;
+
+/* Prints a help message to the user.  This function never returns. */
+
+static void
+usage(void)
+{
+       fprintf(stderr,
+"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
+"           [-D [bind_address:]port] [-e escape_char] [-F configfile]\n"
+"           [-I pkcs11] [-i identity_file]\n"
+"           [-L [bind_address:]port:host:hostport]\n"
+"           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
+"           [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
+"           [-W host:port] [-w local_tun[:remote_tun]]\n"
+"           [user@]hostname [command]\n"
+       );
+       exit(255);
+}
+
+static int ssh_session(void);
+static int ssh_session2(void);
+static void load_public_identity_files(void);
+static void main_sigchld_handler(int);
+
+/* from muxclient.c */
+void muxclient(const char *);
+void muxserver_listen(void);
+
+/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
+static void
+tilde_expand_paths(char **paths, u_int num_paths)
+{
+       u_int i;
+       char *cp;
+
+       for (i = 0; i < num_paths; i++) {
+               cp = tilde_expand_filename(paths[i], original_real_uid);
+               xfree(paths[i]);
+               paths[i] = cp;
+       }
+}
+
+/*
+ * Main program for the ssh client.
+ */
+int
+main(int ac, char **av)
+{
+       int i, r, opt, exit_status, use_syslog;
+       char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg;
+       char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
+       struct stat st;
+       struct passwd *pw;
+       int dummy, timeout_ms;
+       extern int optind, optreset;
+       extern char *optarg;
+
+       struct servent *sp;
+       Forward fwd;
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       __progname = ssh_get_progname(av[0]);
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       /* Save argv so it isn't clobbered by setproctitle() emulation */
+       saved_av = xcalloc(ac + 1, sizeof(*saved_av));
+       for (i = 0; i < ac; i++)
+               saved_av[i] = xstrdup(av[i]);
+       saved_av[i] = NULL;
+       compat_init_setproctitle(ac, av);
+       av = saved_av;
+#endif
+
+       /*
+        * Discard other fds that are hanging around. These can cause problem
+        * with backgrounded ssh processes started by ControlPersist.
+        */
+       closefrom(STDERR_FILENO + 1);
+
+       /*
+        * Save the original real uid.  It will be needed later (uid-swapping
+        * may clobber the real uid).
+        */
+       original_real_uid = getuid();
+       original_effective_uid = geteuid();
+
+       /*
+        * Use uid-swapping to give up root privileges for the duration of
+        * option processing.  We will re-instantiate the rights when we are
+        * ready to create the privileged port, and will permanently drop
+        * them when the port has been created (actually, when the connection
+        * has been made, as we may need to create the port several times).
+        */
+       PRIV_END;
+
+#ifdef HAVE_SETRLIMIT
+       /* If we are installed setuid root be careful to not drop core. */
+       if (original_real_uid != original_effective_uid) {
+               struct rlimit rlim;
+               rlim.rlim_cur = rlim.rlim_max = 0;
+               if (setrlimit(RLIMIT_CORE, &rlim) < 0)
+                       fatal("setrlimit failed: %.100s", strerror(errno));
+       }
+#endif
+       /* Get user data. */
+       pw = getpwuid(original_real_uid);
+       if (!pw) {
+               logit("You don't exist, go away!");
+               exit(255);
+       }
+       /* Take a copy of the returned structure. */
+       pw = pwcopy(pw);
+
+       /*
+        * Set our umask to something reasonable, as some files are created
+        * with the default umask.  This will make them world-readable but
+        * writable only by the owner, which is ok for all files for which we
+        * don't set the modes explicitly.
+        */
+       umask(022);
+
+       /*
+        * Initialize option structure to indicate that no values have been
+        * set.
+        */
+       initialize_options(&options);
+
+       /* Parse command-line arguments. */
+       host = NULL;
+       use_syslog = 0;
+       argv0 = av[0];
+
+ again:
+       while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
+           "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) {
+               switch (opt) {
+               case '1':
+                       options.protocol = SSH_PROTO_1;
+                       break;
+               case '2':
+                       options.protocol = SSH_PROTO_2;
+                       break;
+               case '4':
+                       options.address_family = AF_INET;
+                       break;
+               case '6':
+                       options.address_family = AF_INET6;
+                       break;
+               case 'n':
+                       stdin_null_flag = 1;
+                       break;
+               case 'f':
+                       fork_after_authentication_flag = 1;
+                       stdin_null_flag = 1;
+                       break;
+               case 'x':
+                       options.forward_x11 = 0;
+                       break;
+               case 'X':
+                       options.forward_x11 = 1;
+                       break;
+               case 'y':
+                       use_syslog = 1;
+                       break;
+               case 'Y':
+                       options.forward_x11 = 1;
+                       options.forward_x11_trusted = 1;
+                       break;
+               case 'g':
+                       options.gateway_ports = 1;
+                       break;
+               case 'O':
+                       if (stdio_forward_host != NULL)
+                               fatal("Cannot specify multiplexing "
+                                   "command with -W");
+                       else if (muxclient_command != 0)
+                               fatal("Multiplexing command already specified");
+                       if (strcmp(optarg, "check") == 0)
+                               muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
+                       else if (strcmp(optarg, "forward") == 0)
+                               muxclient_command = SSHMUX_COMMAND_FORWARD;
+                       else if (strcmp(optarg, "exit") == 0)
+                               muxclient_command = SSHMUX_COMMAND_TERMINATE;
+                       else if (strcmp(optarg, "stop") == 0)
+                               muxclient_command = SSHMUX_COMMAND_STOP;
+                       else
+                               fatal("Invalid multiplex command.");
+                       break;
+               case 'P':       /* deprecated */
+                       options.use_privileged_port = 0;
+                       break;
+               case 'a':
+                       options.forward_agent = 0;
+                       break;
+               case 'A':
+                       options.forward_agent = 1;
+                       break;
+               case 'k':
+                       options.gss_deleg_creds = 0;
+                       break;
+               case 'K':
+                       options.gss_authentication = 1;
+                       options.gss_deleg_creds = 1;
+                       break;
+               case 'i':
+                       if (stat(optarg, &st) < 0) {
+                               fprintf(stderr, "Warning: Identity file %s "
+                                   "not accessible: %s.\n", optarg,
+                                   strerror(errno));
+                               break;
+                       }
+                       if (options.num_identity_files >=
+                           SSH_MAX_IDENTITY_FILES)
+                               fatal("Too many identity files specified "
+                                   "(max %d)", SSH_MAX_IDENTITY_FILES);
+                       options.identity_files[options.num_identity_files++] =
+                           xstrdup(optarg);
+                       break;
+               case 'I':
+#ifdef ENABLE_PKCS11
+                       options.pkcs11_provider = xstrdup(optarg);
+#else
+                       fprintf(stderr, "no support for PKCS#11.\n");
+#endif
+                       break;
+               case 't':
+                       if (options.request_tty == REQUEST_TTY_YES)
+                               options.request_tty = REQUEST_TTY_FORCE;
+                       else
+                               options.request_tty = REQUEST_TTY_YES;
+                       break;
+               case 'v':
+                       if (debug_flag == 0) {
+                               debug_flag = 1;
+                               options.log_level = SYSLOG_LEVEL_DEBUG1;
+                       } else {
+                               if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                                       options.log_level++;
+                               break;
+                       }
+                       /* FALLTHROUGH */
+               case 'V':
+                       fprintf(stderr, "%s, %s\n",
+                           SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
+                       if (opt == 'V')
+                               exit(0);
+                       break;
+               case 'w':
+                       if (options.tun_open == -1)
+                               options.tun_open = SSH_TUNMODE_DEFAULT;
+                       options.tun_local = a2tun(optarg, &options.tun_remote);
+                       if (options.tun_local == SSH_TUNID_ERR) {
+                               fprintf(stderr,
+                                   "Bad tun device '%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'W':
+                       if (stdio_forward_host != NULL)
+                               fatal("stdio forward already specified");
+                       if (muxclient_command != 0)
+                               fatal("Cannot specify stdio forward with -O");
+                       if (parse_forward(&fwd, optarg, 1, 0)) {
+                               stdio_forward_host = fwd.listen_host;
+                               stdio_forward_port = fwd.listen_port;
+                               xfree(fwd.connect_host);
+                       } else {
+                               fprintf(stderr,
+                                   "Bad stdio forwarding specification '%s'\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       options.request_tty = REQUEST_TTY_NO;
+                       no_shell_flag = 1;
+                       options.clear_forwardings = 1;
+                       options.exit_on_forward_failure = 1;
+                       break;
+               case 'q':
+                       options.log_level = SYSLOG_LEVEL_QUIET;
+                       break;
+               case 'e':
+                       if (optarg[0] == '^' && optarg[2] == 0 &&
+                           (u_char) optarg[1] >= 64 &&
+                           (u_char) optarg[1] < 128)
+                               options.escape_char = (u_char) optarg[1] & 31;
+                       else if (strlen(optarg) == 1)
+                               options.escape_char = (u_char) optarg[0];
+                       else if (strcmp(optarg, "none") == 0)
+                               options.escape_char = SSH_ESCAPECHAR_NONE;
+                       else {
+                               fprintf(stderr, "Bad escape character '%s'.\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'c':
+                       if (ciphers_valid(optarg)) {
+                               /* SSH2 only */
+                               options.ciphers = xstrdup(optarg);
+                               options.cipher = SSH_CIPHER_INVALID;
+                       } else {
+                               /* SSH1 only */
+                               options.cipher = cipher_number(optarg);
+                               if (options.cipher == -1) {
+                                       fprintf(stderr,
+                                           "Unknown cipher type '%s'\n",
+                                           optarg);
+                                       exit(255);
+                               }
+                               if (options.cipher == SSH_CIPHER_3DES)
+                                       options.ciphers = "3des-cbc";
+                               else if (options.cipher == SSH_CIPHER_BLOWFISH)
+                                       options.ciphers = "blowfish-cbc";
+                               else
+                                       options.ciphers = (char *)-1;
+                       }
+                       break;
+               case 'm':
+                       if (mac_valid(optarg))
+                               options.macs = xstrdup(optarg);
+                       else {
+                               fprintf(stderr, "Unknown mac type '%s'\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'M':
+                       if (options.control_master == SSHCTL_MASTER_YES)
+                               options.control_master = SSHCTL_MASTER_ASK;
+                       else
+                               options.control_master = SSHCTL_MASTER_YES;
+                       break;
+               case 'p':
+                       options.port = a2port(optarg);
+                       if (options.port <= 0) {
+                               fprintf(stderr, "Bad port '%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+               case 'l':
+                       options.user = optarg;
+                       break;
+
+               case 'L':
+                       if (parse_forward(&fwd, optarg, 0, 0))
+                               add_local_forward(&options, &fwd);
+                       else {
+                               fprintf(stderr,
+                                   "Bad local forwarding specification '%s'\n",
+                                   optarg);
+                               exit(255);
+                       }
+                       break;
+
+               case 'R':
+                       if (parse_forward(&fwd, optarg, 0, 1)) {
+                               add_remote_forward(&options, &fwd);
+                       } else {
+                               fprintf(stderr,
+                                   "Bad remote forwarding specification "
+                                   "'%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+
+               case 'D':
+                       if (parse_forward(&fwd, optarg, 1, 0)) {
+                               add_local_forward(&options, &fwd);
+                       } else {
+                               fprintf(stderr,
+                                   "Bad dynamic forwarding specification "
+                                   "'%s'\n", optarg);
+                               exit(255);
+                       }
+                       break;
+
+               case 'C':
+                       options.compression = 1;
+                       break;
+               case 'N':
+                       no_shell_flag = 1;
+                       options.request_tty = REQUEST_TTY_NO;
+                       break;
+               case 'T':
+                       options.request_tty = REQUEST_TTY_NO;
+                       break;
+               case 'o':
+                       dummy = 1;
+                       line = xstrdup(optarg);
+                       if (process_config_line(&options, host ? host : "",
+                           line, "command-line", 0, &dummy) != 0)
+                               exit(255);
+                       xfree(line);
+                       break;
+               case 's':
+                       subsystem_flag = 1;
+                       break;
+               case 'S':
+                       if (options.control_path != NULL)
+                               free(options.control_path);
+                       options.control_path = xstrdup(optarg);
+                       break;
+               case 'b':
+                       options.bind_address = optarg;
+                       break;
+               case 'F':
+                       config = optarg;
+                       break;
+               default:
+                       usage();
+               }
+       }
+
+       ac -= optind;
+       av += optind;
+
+       if (ac > 0 && !host) {
+               if (strrchr(*av, '@')) {
+                       p = xstrdup(*av);
+                       cp = strrchr(p, '@');
+                       if (cp == NULL || cp == p)
+                               usage();
+                       options.user = p;
+                       *cp = '\0';
+                       host = ++cp;
+               } else
+                       host = *av;
+               if (ac > 1) {
+                       optind = optreset = 1;
+                       goto again;
+               }
+               ac--, av++;
+       }
+
+       /* Check that we got a host name. */
+       if (!host)
+               usage();
+
+       OpenSSL_add_all_algorithms();
+       ERR_load_crypto_strings();
+
+       /* Initialize the command to execute on remote host. */
+       buffer_init(&command);
+
+       if (options.request_tty == REQUEST_TTY_YES ||
+           options.request_tty == REQUEST_TTY_FORCE)
+               tty_flag = 1;
+
+       /*
+        * Save the command to execute on the remote host in a buffer. There
+        * is no limit on the length of the command, except by the maximum
+        * packet size.  Also sets the tty flag if there is no command.
+        */
+       if (!ac) {
+               /* No command specified - execute shell on a tty. */
+               tty_flag = options.request_tty != REQUEST_TTY_NO;
+               if (subsystem_flag) {
+                       fprintf(stderr,
+                           "You must specify a subsystem to invoke.\n");
+                       usage();
+               }
+       } else {
+               /* A command has been specified.  Store it into the buffer. */
+               for (i = 0; i < ac; i++) {
+                       if (i)
+                               buffer_append(&command, " ", 1);
+                       buffer_append(&command, av[i], strlen(av[i]));
+               }
+       }
+
+       /* Cannot fork to background if no command. */
+       if (fork_after_authentication_flag && buffer_len(&command) == 0 &&
+           !no_shell_flag)
+               fatal("Cannot fork into background without a command "
+                   "to execute.");
+
+       /* Allocate a tty by default if no command specified. */
+       if (buffer_len(&command) == 0)
+               tty_flag = options.request_tty != REQUEST_TTY_NO;
+
+       /* Force no tty */
+       if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0)
+               tty_flag = 0;
+       /* Do not allocate a tty if stdin is not a tty. */
+       if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
+           options.request_tty != REQUEST_TTY_FORCE) {
+               if (tty_flag)
+                       logit("Pseudo-terminal will not be allocated because "
+                           "stdin is not a terminal.");
+               tty_flag = 0;
+       }
+
+       /*
+        * Initialize "log" output.  Since we are the client all output
+        * actually goes to stderr.
+        */
+       log_init(argv0,
+           options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
+           SYSLOG_FACILITY_USER, !use_syslog);
+
+       /*
+        * Read per-user configuration file.  Ignore the system wide config
+        * file if the user specifies a config file on the command line.
+        */
+       if (config != NULL) {
+               if (!read_config_file(config, host, &options, 0))
+                       fatal("Can't open user config file %.100s: "
+                           "%.100s", config, strerror(errno));
+       } else {
+               r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
+                   _PATH_SSH_USER_CONFFILE);
+               if (r > 0 && (size_t)r < sizeof(buf))
+                       (void)read_config_file(buf, host, &options, 1);
+
+               /* Read systemwide configuration file after user config. */
+               (void)read_config_file(_PATH_HOST_CONFIG_FILE, host,
+                   &options, 0);
+       }
+
+       /* Fill configuration defaults. */
+       fill_default_options(&options);
+
+       channel_set_af(options.address_family);
+
+       /* reinit */
+       log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);
+
+       seed_rng();
+
+       if (options.user == NULL)
+               options.user = xstrdup(pw->pw_name);
+
+       /* Get default port if port has not been set. */
+       if (options.port == 0) {
+               sp = getservbyname(SSH_SERVICE_NAME, "tcp");
+               options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
+       }
+
+       /* preserve host name given on command line for %n expansion */
+       host_arg = host;
+       if (options.hostname != NULL) {
+               host = percent_expand(options.hostname,
+                   "h", host, (char *)NULL);
+       }
+
+       if (gethostname(thishost, sizeof(thishost)) == -1)
+               fatal("gethostname: %s", strerror(errno));
+       strlcpy(shorthost, thishost, sizeof(shorthost));
+       shorthost[strcspn(thishost, ".")] = '\0';
+       snprintf(portstr, sizeof(portstr), "%d", options.port);
+
+       if (options.local_command != NULL) {
+               debug3("expanding LocalCommand: %s", options.local_command);
+               cp = options.local_command;
+               options.local_command = percent_expand(cp, "d", pw->pw_dir,
+                   "h", host, "l", thishost, "n", host_arg, "r", options.user,
+                   "p", portstr, "u", pw->pw_name, "L", shorthost,
+                   (char *)NULL);
+               debug3("expanded LocalCommand: %s", options.local_command);
+               xfree(cp);
+       }
+
+       /* force lowercase for hostkey matching */
+       if (options.host_key_alias != NULL) {
+               for (p = options.host_key_alias; *p; p++)
+                       if (isupper(*p))
+                               *p = (char)tolower(*p);
+       }
+
+       if (options.proxy_command != NULL &&
+           strcmp(options.proxy_command, "none") == 0) {
+               xfree(options.proxy_command);
+               options.proxy_command = NULL;
+       }
+       if (options.control_path != NULL &&
+           strcmp(options.control_path, "none") == 0) {
+               xfree(options.control_path);
+               options.control_path = NULL;
+       }
+
+       if (options.control_path != NULL) {
+               cp = tilde_expand_filename(options.control_path,
+                   original_real_uid);
+               xfree(options.control_path);
+               options.control_path = percent_expand(cp, "h", host,
+                   "l", thishost, "n", host_arg, "r", options.user,
+                   "p", portstr, "u", pw->pw_name, "L", shorthost,
+                   (char *)NULL);
+               xfree(cp);
+       }
+       if (muxclient_command != 0 && options.control_path == NULL)
+               fatal("No ControlPath specified for \"-O\" command");
+       if (options.control_path != NULL)
+               muxclient(options.control_path);
+
+       timeout_ms = options.connection_timeout * 1000;
+
+       /* Open a connection to the remote host. */
+       if (ssh_connect(host, &hostaddr, options.port,
+           options.address_family, options.connection_attempts, &timeout_ms,
+           options.tcp_keep_alive, 
+#ifdef HAVE_CYGWIN
+           options.use_privileged_port,
+#else
+           original_effective_uid == 0 && options.use_privileged_port,
+#endif
+           options.proxy_command) != 0)
+               exit(255);
+
+       if (timeout_ms > 0)
+               debug3("timeout: %d ms remain after connect", timeout_ms);
+
+       /*
+        * If we successfully made the connection, load the host private key
+        * in case we will need it later for combined rsa-rhosts
+        * authentication. This must be done before releasing extra
+        * privileges, because the file is only readable by root.
+        * If we cannot access the private keys, load the public keys
+        * instead and try to execute the ssh-keysign helper instead.
+        */
+       sensitive_data.nkeys = 0;
+       sensitive_data.keys = NULL;
+       sensitive_data.external_keysign = 0;
+       if (options.rhosts_rsa_authentication ||
+           options.hostbased_authentication) {
+               sensitive_data.nkeys = 7;
+               sensitive_data.keys = xcalloc(sensitive_data.nkeys,
+                   sizeof(Key));
+               for (i = 0; i < sensitive_data.nkeys; i++)
+                       sensitive_data.keys[i] = NULL;
+
+               PRIV_START;
+               sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
+                   _PATH_HOST_KEY_FILE, "", NULL, NULL);
+               sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
+                   _PATH_HOST_DSA_KEY_FILE, "", NULL);
+#ifdef OPENSSL_HAS_ECC
+               sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA,
+                   _PATH_HOST_ECDSA_KEY_FILE, "", NULL);
+#endif
+               sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
+                   _PATH_HOST_RSA_KEY_FILE, "", NULL);
+               sensitive_data.keys[4] = key_load_private_type(KEY_DSA,
+                   _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
+#ifdef OPENSSL_HAS_ECC
+               sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA,
+                   _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
+#endif
+               sensitive_data.keys[6] = key_load_private_type(KEY_RSA,
+                   _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
+               PRIV_END;
+
+               if (options.hostbased_authentication == 1 &&
+                   sensitive_data.keys[0] == NULL &&
+                   sensitive_data.keys[4] == NULL &&
+                   sensitive_data.keys[5] == NULL &&
+                   sensitive_data.keys[6] == NULL) {
+                       sensitive_data.keys[1] = key_load_cert(
+                           _PATH_HOST_DSA_KEY_FILE);
+#ifdef OPENSSL_HAS_ECC
+                       sensitive_data.keys[2] = key_load_cert(
+                           _PATH_HOST_ECDSA_KEY_FILE);
+#endif
+                       sensitive_data.keys[3] = key_load_cert(
+                           _PATH_HOST_RSA_KEY_FILE);
+                       sensitive_data.keys[4] = key_load_public(
+                           _PATH_HOST_DSA_KEY_FILE, NULL);
+#ifdef OPENSSL_HAS_ECC
+                       sensitive_data.keys[5] = key_load_public(
+                           _PATH_HOST_ECDSA_KEY_FILE, NULL);
+#endif
+                       sensitive_data.keys[6] = key_load_public(
+                           _PATH_HOST_RSA_KEY_FILE, NULL);
+                       sensitive_data.external_keysign = 1;
+               }
+       }
+       /*
+        * Get rid of any extra privileges that we may have.  We will no
+        * longer need them.  Also, extra privileges could make it very hard
+        * to read identity files and other non-world-readable files from the
+        * user's home directory if it happens to be on a NFS volume where
+        * root is mapped to nobody.
+        */
+       if (original_effective_uid == 0) {
+               PRIV_START;
+               permanently_set_uid(pw);
+       }
+
+       /*
+        * Now that we are back to our own permissions, create ~/.ssh
+        * directory if it doesn't already exist.
+        */
+       r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
+           strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
+       if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) {
+#ifdef WITH_SELINUX
+               ssh_selinux_setfscreatecon(buf);
+#endif
+               if (mkdir(buf, 0700) < 0)
+                       error("Could not create directory '%.200s'.", buf);
+#ifdef WITH_SELINUX
+               ssh_selinux_setfscreatecon(NULL);
+#endif
+       }
+       /* load options.identity_files */
+       load_public_identity_files();
+
+       /* Expand ~ in known host file names. */
+       tilde_expand_paths(options.system_hostfiles,
+           options.num_system_hostfiles);
+       tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
+
+       signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
+       signal(SIGCHLD, main_sigchld_handler);
+
+       /* Log into the remote system.  Never returns if the login fails. */
+       ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
+           options.port, pw, timeout_ms);
+
+       if (packet_connection_is_on_socket()) {
+               verbose("Authenticated to %s ([%s]:%d).", host,
+                   get_remote_ipaddr(), get_remote_port());
+       } else {
+               verbose("Authenticated to %s (via proxy).", host);
+       }
+
+       /* We no longer need the private host keys.  Clear them now. */
+       if (sensitive_data.nkeys != 0) {
+               for (i = 0; i < sensitive_data.nkeys; i++) {
+                       if (sensitive_data.keys[i] != NULL) {
+                               /* Destroys contents safely */
+                               debug3("clear hostkey %d", i);
+                               key_free(sensitive_data.keys[i]);
+                               sensitive_data.keys[i] = NULL;
+                       }
+               }
+               xfree(sensitive_data.keys);
+       }
+       for (i = 0; i < options.num_identity_files; i++) {
+               if (options.identity_files[i]) {
+                       xfree(options.identity_files[i]);
+                       options.identity_files[i] = NULL;
+               }
+               if (options.identity_keys[i]) {
+                       key_free(options.identity_keys[i]);
+                       options.identity_keys[i] = NULL;
+               }
+       }
+
+       exit_status = compat20 ? ssh_session2() : ssh_session();
+       packet_close();
+
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+
+       /* Kill ProxyCommand if it is running. */
+       ssh_kill_proxy_command();
+
+       return exit_status;
+}
+
+static void
+control_persist_detach(void)
+{
+       pid_t pid;
+       int devnull;
+
+       debug("%s: backgrounding master process", __func__);
+
+       /*
+        * master (current process) into the background, and make the
+        * foreground process a client of the backgrounded master.
+        */
+       switch ((pid = fork())) {
+       case -1:
+               fatal("%s: fork: %s", __func__, strerror(errno));
+       case 0:
+               /* Child: master process continues mainloop */
+               break;
+       default:
+               /* Parent: set up mux slave to connect to backgrounded master */
+               debug2("%s: background process is %ld", __func__, (long)pid);
+               stdin_null_flag = ostdin_null_flag;
+               options.request_tty = orequest_tty;
+               tty_flag = otty_flag;
+               close(muxserver_sock);
+               muxserver_sock = -1;
+               options.control_master = SSHCTL_MASTER_NO;
+               muxclient(options.control_path);
+               /* muxclient() doesn't return on success. */
+               fatal("Failed to connect to new control master");
+       }
+       if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+               error("%s: open(\"/dev/null\"): %s", __func__,
+                   strerror(errno));
+       } else {
+               if (dup2(devnull, STDIN_FILENO) == -1 ||
+                   dup2(devnull, STDOUT_FILENO) == -1)
+                       error("%s: dup2: %s", __func__, strerror(errno));
+               if (devnull > STDERR_FILENO)
+                       close(devnull);
+       }
+       setproctitle("%s [mux]", options.control_path);
+}
+
+/* Do fork() after authentication. Used by "ssh -f" */
+static void
+fork_postauth(void)
+{
+       if (need_controlpersist_detach)
+               control_persist_detach();
+       debug("forking to background");
+       fork_after_authentication_flag = 0;
+       if (daemon(1, 1) < 0)
+               fatal("daemon() failed: %.200s", strerror(errno));
+}
+
+/* Callback for remote forward global requests */
+static void
+ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
+{
+       Forward *rfwd = (Forward *)ctxt;
+
+       /* XXX verbose() on failure? */
+       debug("remote forward %s for: listen %d, connect %s:%d",
+           type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
+           rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
+       if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) {
+               rfwd->allocated_port = packet_get_int();
+               logit("Allocated port %u for remote forward to %s:%d",
+                   rfwd->allocated_port,
+                   rfwd->connect_host, rfwd->connect_port);
+       }
+       
+       if (type == SSH2_MSG_REQUEST_FAILURE) {
+               if (options.exit_on_forward_failure)
+                       fatal("Error: remote port forwarding failed for "
+                           "listen port %d", rfwd->listen_port);
+               else
+                       logit("Warning: remote port forwarding failed for "
+                           "listen port %d", rfwd->listen_port);
+       }
+       if (++remote_forward_confirms_received == options.num_remote_forwards) {
+               debug("All remote forwarding requests processed");
+               if (fork_after_authentication_flag)
+                       fork_postauth();
+       }
+}
+
+static void
+client_cleanup_stdio_fwd(int id, void *arg)
+{
+       debug("stdio forwarding: done");
+       cleanup_exit(0);
+}
+
+static int
+client_setup_stdio_fwd(const char *host_to_connect, u_short port_to_connect)
+{
+       Channel *c;
+       int in, out;
+
+       debug3("client_setup_stdio_fwd %s:%d", host_to_connect,
+           port_to_connect);
+
+       in = dup(STDIN_FILENO);
+       out = dup(STDOUT_FILENO);
+       if (in < 0 || out < 0)
+               fatal("channel_connect_stdio_fwd: dup() in/out failed");
+
+       if ((c = channel_connect_stdio_fwd(host_to_connect, port_to_connect,
+           in, out)) == NULL)
+               return 0;
+       channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
+       return 1;
+}
+
+static void
+ssh_init_forwarding(void)
+{
+       int success = 0;
+       int i;
+
+       if (stdio_forward_host != NULL) {
+               if (!compat20) {
+                       fatal("stdio forwarding require Protocol 2");
+               }
+               if (!client_setup_stdio_fwd(stdio_forward_host,
+                   stdio_forward_port))
+                       fatal("Failed to connect in stdio forward mode.");
+       }
+
+       /* Initiate local TCP/IP port forwardings. */
+       for (i = 0; i < options.num_local_forwards; i++) {
+               debug("Local connections to %.200s:%d forwarded to remote "
+                   "address %.200s:%d",
+                   (options.local_forwards[i].listen_host == NULL) ?
+                   (options.gateway_ports ? "*" : "LOCALHOST") :
+                   options.local_forwards[i].listen_host,
+                   options.local_forwards[i].listen_port,
+                   options.local_forwards[i].connect_host,
+                   options.local_forwards[i].connect_port);
+               success += channel_setup_local_fwd_listener(
+                   options.local_forwards[i].listen_host,
+                   options.local_forwards[i].listen_port,
+                   options.local_forwards[i].connect_host,
+                   options.local_forwards[i].connect_port,
+                   options.gateway_ports);
+       }
+       if (i > 0 && success != i && options.exit_on_forward_failure)
+               fatal("Could not request local forwarding.");
+       if (i > 0 && success == 0)
+               error("Could not request local forwarding.");
+
+       /* Initiate remote TCP/IP port forwardings. */
+       for (i = 0; i < options.num_remote_forwards; i++) {
+               debug("Remote connections from %.200s:%d forwarded to "
+                   "local address %.200s:%d",
+                   (options.remote_forwards[i].listen_host == NULL) ?
+                   "LOCALHOST" : options.remote_forwards[i].listen_host,
+                   options.remote_forwards[i].listen_port,
+                   options.remote_forwards[i].connect_host,
+                   options.remote_forwards[i].connect_port);
+               if (channel_request_remote_forwarding(
+                   options.remote_forwards[i].listen_host,
+                   options.remote_forwards[i].listen_port,
+                   options.remote_forwards[i].connect_host,
+                   options.remote_forwards[i].connect_port) < 0) {
+                       if (options.exit_on_forward_failure)
+                               fatal("Could not request remote forwarding.");
+                       else
+                               logit("Warning: Could not request remote "
+                                   "forwarding.");
+               }
+               client_register_global_confirm(ssh_confirm_remote_forward,
+                   &options.remote_forwards[i]);
+       }
+
+       /* Initiate tunnel forwarding. */
+       if (options.tun_open != SSH_TUNMODE_NO) {
+               if (client_request_tun_fwd(options.tun_open,
+                   options.tun_local, options.tun_remote) == -1) {
+                       if (options.exit_on_forward_failure)
+                               fatal("Could not request tunnel forwarding.");
+                       else
+                               error("Could not request tunnel forwarding.");
+               }
+       }                       
+}
+
+static void
+check_agent_present(void)
+{
+       if (options.forward_agent) {
+               /* Clear agent forwarding if we don't have an agent. */
+               if (!ssh_agent_present())
+                       options.forward_agent = 0;
+       }
+}
+
+static int
+ssh_session(void)
+{
+       int type;
+       int interactive = 0;
+       int have_tty = 0;
+       struct winsize ws;
+       char *cp;
+       const char *display;
+
+       /* Enable compression if requested. */
+       if (options.compression) {
+               debug("Requesting compression at level %d.",
+                   options.compression_level);
+
+               if (options.compression_level < 1 ||
+                   options.compression_level > 9)
+                       fatal("Compression level must be from 1 (fast) to "
+                           "9 (slow, best).");
+
+               /* Send the request. */
+               packet_start(SSH_CMSG_REQUEST_COMPRESSION);
+               packet_put_int(options.compression_level);
+               packet_send();
+               packet_write_wait();
+               type = packet_read();
+               if (type == SSH_SMSG_SUCCESS)
+                       packet_start_compression(options.compression_level);
+               else if (type == SSH_SMSG_FAILURE)
+                       logit("Warning: Remote host refused compression.");
+               else
+                       packet_disconnect("Protocol error waiting for "
+                           "compression response.");
+       }
+       /* Allocate a pseudo tty if appropriate. */
+       if (tty_flag) {
+               debug("Requesting pty.");
+
+               /* Start the packet. */
+               packet_start(SSH_CMSG_REQUEST_PTY);
+
+               /* Store TERM in the packet.  There is no limit on the
+                  length of the string. */
+               cp = getenv("TERM");
+               if (!cp)
+                       cp = "";
+               packet_put_cstring(cp);
+
+               /* Store window size in the packet. */
+               if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
+                       memset(&ws, 0, sizeof(ws));
+               packet_put_int((u_int)ws.ws_row);
+               packet_put_int((u_int)ws.ws_col);
+               packet_put_int((u_int)ws.ws_xpixel);
+               packet_put_int((u_int)ws.ws_ypixel);
+
+               /* Store tty modes in the packet. */
+               tty_make_modes(fileno(stdin), NULL);
+
+               /* Send the packet, and wait for it to leave. */
+               packet_send();
+               packet_write_wait();
+
+               /* Read response from the server. */
+               type = packet_read();
+               if (type == SSH_SMSG_SUCCESS) {
+                       interactive = 1;
+                       have_tty = 1;
+               } else if (type == SSH_SMSG_FAILURE)
+                       logit("Warning: Remote host failed or refused to "
+                           "allocate a pseudo tty.");
+               else
+                       packet_disconnect("Protocol error waiting for pty "
+                           "request response.");
+       }
+       /* Request X11 forwarding if enabled and DISPLAY is set. */
+       display = getenv("DISPLAY");
+       if (options.forward_x11 && display != NULL) {
+               char *proto, *data;
+               /* Get reasonable local authentication information. */
+               client_x11_get_proto(display, options.xauth_location,
+                   options.forward_x11_trusted, 
+                   options.forward_x11_timeout,
+                   &proto, &data);
+               /* Request forwarding with authentication spoofing. */
+               debug("Requesting X11 forwarding with authentication "
+                   "spoofing.");
+               x11_request_forwarding_with_spoofing(0, display, proto,
+                   data, 0);
+               /* Read response from the server. */
+               type = packet_read();
+               if (type == SSH_SMSG_SUCCESS) {
+                       interactive = 1;
+               } else if (type == SSH_SMSG_FAILURE) {
+                       logit("Warning: Remote host denied X11 forwarding.");
+               } else {
+                       packet_disconnect("Protocol error waiting for X11 "
+                           "forwarding");
+               }
+       }
+       /* Tell the packet module whether this is an interactive session. */
+       packet_set_interactive(interactive,
+           options.ip_qos_interactive, options.ip_qos_bulk);
+
+       /* Request authentication agent forwarding if appropriate. */
+       check_agent_present();
+
+       if (options.forward_agent) {
+               debug("Requesting authentication agent forwarding.");
+               auth_request_forwarding();
+
+               /* Read response from the server. */
+               type = packet_read();
+               packet_check_eom();
+               if (type != SSH_SMSG_SUCCESS)
+                       logit("Warning: Remote host denied authentication agent forwarding.");
+       }
+
+       /* Initiate port forwardings. */
+       ssh_init_forwarding();
+
+       /* Execute a local command */
+       if (options.local_command != NULL &&
+           options.permit_local_command)
+               ssh_local_cmd(options.local_command);
+
+       /*
+        * If requested and we are not interested in replies to remote
+        * forwarding requests, then let ssh continue in the background.
+        */
+       if (fork_after_authentication_flag) {
+               if (options.exit_on_forward_failure &&
+                   options.num_remote_forwards > 0) {
+                       debug("deferring postauth fork until remote forward "
+                           "confirmation received");
+               } else
+                       fork_postauth();
+       }
+
+       /*
+        * If a command was specified on the command line, execute the
+        * command now. Otherwise request the server to start a shell.
+        */
+       if (buffer_len(&command) > 0) {
+               int len = buffer_len(&command);
+               if (len > 900)
+                       len = 900;
+               debug("Sending command: %.*s", len,
+                   (u_char *)buffer_ptr(&command));
+               packet_start(SSH_CMSG_EXEC_CMD);
+               packet_put_string(buffer_ptr(&command), buffer_len(&command));
+               packet_send();
+               packet_write_wait();
+       } else {
+               debug("Requesting shell.");
+               packet_start(SSH_CMSG_EXEC_SHELL);
+               packet_send();
+               packet_write_wait();
+       }
+
+       /* Enter the interactive session. */
+       return client_loop(have_tty, tty_flag ?
+           options.escape_char : SSH_ESCAPECHAR_NONE, 0);
+}
+
+/* request pty/x11/agent/tcpfwd/shell for channel */
+static void
+ssh_session2_setup(int id, int success, void *arg)
+{
+       extern char **environ;
+       const char *display;
+       int interactive = tty_flag;
+
+       if (!success)
+               return; /* No need for error message, channels code sens one */
+
+       display = getenv("DISPLAY");
+       if (options.forward_x11 && display != NULL) {
+               char *proto, *data;
+               /* Get reasonable local authentication information. */
+               client_x11_get_proto(display, options.xauth_location,
+                   options.forward_x11_trusted,
+                   options.forward_x11_timeout, &proto, &data);
+               /* Request forwarding with authentication spoofing. */
+               debug("Requesting X11 forwarding with authentication "
+                   "spoofing.");
+               x11_request_forwarding_with_spoofing(id, display, proto,
+                   data, 1);
+               client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
+               /* XXX exit_on_forward_failure */
+               interactive = 1;
+       }
+
+       check_agent_present();
+       if (options.forward_agent) {
+               debug("Requesting authentication agent forwarding.");
+               channel_request_start(id, "auth-agent-req@openssh.com", 0);
+               packet_send();
+       }
+
+       client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
+           NULL, fileno(stdin), &command, environ);
+}
+
+/* open new channel for a session */
+static int
+ssh_session2_open(void)
+{
+       Channel *c;
+       int window, packetmax, in, out, err;
+
+       if (stdin_null_flag) {
+               in = open(_PATH_DEVNULL, O_RDONLY);
+       } else {
+               in = dup(STDIN_FILENO);
+       }
+       out = dup(STDOUT_FILENO);
+       err = dup(STDERR_FILENO);
+
+       if (in < 0 || out < 0 || err < 0)
+               fatal("dup() in/out/err failed");
+
+       /* enable nonblocking unless tty */
+       if (!isatty(in))
+               set_nonblock(in);
+       if (!isatty(out))
+               set_nonblock(out);
+       if (!isatty(err))
+               set_nonblock(err);
+
+       window = CHAN_SES_WINDOW_DEFAULT;
+       packetmax = CHAN_SES_PACKET_DEFAULT;
+       if (tty_flag) {
+               window >>= 1;
+               packetmax >>= 1;
+       }
+       c = channel_new(
+           "session", SSH_CHANNEL_OPENING, in, out, err,
+           window, packetmax, CHAN_EXTENDED_WRITE,
+           "client-session", /*nonblock*/0);
+
+       debug3("ssh_session2_open: channel_new: %d", c->self);
+
+       channel_send_open(c->self);
+       if (!no_shell_flag)
+               channel_register_open_confirm(c->self,
+                   ssh_session2_setup, NULL);
+
+       return c->self;
+}
+
+static int
+ssh_session2(void)
+{
+       int id = -1;
+
+       /* XXX should be pre-session */
+       ssh_init_forwarding();
+
+       /* Start listening for multiplex clients */
+       muxserver_listen();
+
+       /*
+        * If we are in control persist mode, then prepare to background
+        * ourselves and have a foreground client attach as a control
+        * slave. NB. we must save copies of the flags that we override for
+        * the backgrounding, since we defer attachment of the slave until
+        * after the connection is fully established (in particular,
+        * async rfwd replies have been received for ExitOnForwardFailure).
+        */
+       if (options.control_persist && muxserver_sock != -1) {
+               ostdin_null_flag = stdin_null_flag;
+               ono_shell_flag = no_shell_flag;
+               orequest_tty = options.request_tty;
+               otty_flag = tty_flag;
+               stdin_null_flag = 1;
+               no_shell_flag = 1;
+               tty_flag = 0;
+               if (!fork_after_authentication_flag)
+                       need_controlpersist_detach = 1;
+               fork_after_authentication_flag = 1;
+       }
+
+       if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
+               id = ssh_session2_open();
+
+       /* If we don't expect to open a new session, then disallow it */
+       if (options.control_master == SSHCTL_MASTER_NO &&
+           (datafellows & SSH_NEW_OPENSSH)) {
+               debug("Requesting no-more-sessions@openssh.com");
+               packet_start(SSH2_MSG_GLOBAL_REQUEST);
+               packet_put_cstring("no-more-sessions@openssh.com");
+               packet_put_char(0);
+               packet_send();
+       }
+
+       /* Execute a local command */
+       if (options.local_command != NULL &&
+           options.permit_local_command)
+               ssh_local_cmd(options.local_command);
+
+       /*
+        * If requested and we are not interested in replies to remote
+        * forwarding requests, then let ssh continue in the background.
+        */
+       if (fork_after_authentication_flag) {
+               if (options.exit_on_forward_failure &&
+                   options.num_remote_forwards > 0) {
+                       debug("deferring postauth fork until remote forward "
+                           "confirmation received");
+               } else
+                       fork_postauth();
+       }
+
+       if (options.use_roaming)
+               request_roaming();
+
+       return client_loop(tty_flag, tty_flag ?
+           options.escape_char : SSH_ESCAPECHAR_NONE, id);
+}
+
+static void
+load_public_identity_files(void)
+{
+       char *filename, *cp, thishost[NI_MAXHOST], *fp;
+       char *pwdir = NULL, *pwname = NULL;
+       int i = 0;
+       Key *public;
+       struct passwd *pw;
+       u_int n_ids;
+       char *identity_files[SSH_MAX_IDENTITY_FILES];
+       Key *identity_keys[SSH_MAX_IDENTITY_FILES];
+#ifdef ENABLE_PKCS11
+       Key **keys;
+       int nkeys;
+#endif /* PKCS11 */
+
+       n_ids = 0;
+       bzero(identity_files, sizeof(identity_files));
+       bzero(identity_keys, sizeof(identity_keys));
+
+#ifdef ENABLE_PKCS11
+       if (options.pkcs11_provider != NULL &&
+           options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
+           (pkcs11_init(!options.batch_mode) == 0) &&
+           (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
+           &keys)) > 0) {
+               for (i = 0; i < nkeys; i++) {
+                       if (n_ids >= SSH_MAX_IDENTITY_FILES) {
+                               key_free(keys[i]);
+                               continue;
+                       }
+                       identity_keys[n_ids] = keys[i];
+                       identity_files[n_ids] =
+                           xstrdup(options.pkcs11_provider); /* XXX */
+                       n_ids++;
+               }
+               xfree(keys);
+       }
+#endif /* ENABLE_PKCS11 */
+       if ((pw = getpwuid(original_real_uid)) == NULL)
+               fatal("load_public_identity_files: getpwuid failed");
+       pwname = xstrdup(pw->pw_name);
+       pwdir = xstrdup(pw->pw_dir);
+       if (gethostname(thishost, sizeof(thishost)) == -1)
+               fatal("load_public_identity_files: gethostname: %s",
+                   strerror(errno));
+       for (i = 0; i < options.num_identity_files; i++) {
+               if (n_ids >= SSH_MAX_IDENTITY_FILES) {
+                       xfree(options.identity_files[i]);
+                       continue;
+               }
+               cp = tilde_expand_filename(options.identity_files[i],
+                   original_real_uid);
+               filename = percent_expand(cp, "d", pwdir,
+                   "u", pwname, "l", thishost, "h", host,
+                   "r", options.user, (char *)NULL);
+               xfree(cp);
+               public = key_load_public(filename, NULL);
+               debug("identity file %s type %d", filename,
+                   public ? public->type : -1);
+               if (public && blacklisted_key(public, &fp) == 1) {
+                       if (options.use_blacklisted_keys)
+                               logit("Public key %s blacklisted (see "
+                                   "ssh-vulnkey(1)); continuing anyway", fp);
+                       else
+                               logit("Public key %s blacklisted (see "
+                                   "ssh-vulnkey(1)); refusing to send it",
+                                   fp);
+                       xfree(fp);
+                       if (!options.use_blacklisted_keys) {
+                               key_free(public);
+                               xfree(filename);
+                               filename = NULL;
+                               public = NULL;
+                       }
+               }
+               xfree(options.identity_files[i]);
+               identity_files[n_ids] = filename;
+               identity_keys[n_ids] = public;
+
+               if (++n_ids >= SSH_MAX_IDENTITY_FILES)
+                       continue;
+
+               /* Try to add the certificate variant too */
+               xasprintf(&cp, "%s-cert", filename);
+               public = key_load_public(cp, NULL);
+               debug("identity file %s type %d", cp,
+                   public ? public->type : -1);
+               if (public == NULL) {
+                       xfree(cp);
+                       continue;
+               }
+               if (!key_is_cert(public)) {
+                       debug("%s: key %s type %s is not a certificate",
+                           __func__, cp, key_type(public));
+                       key_free(public);
+                       xfree(cp);
+                       continue;
+               }
+               identity_keys[n_ids] = public;
+               /* point to the original path, most likely the private key */
+               identity_files[n_ids] = xstrdup(filename);
+               n_ids++;
+       }
+       options.num_identity_files = n_ids;
+       memcpy(options.identity_files, identity_files, sizeof(identity_files));
+       memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
+
+       bzero(pwname, strlen(pwname));
+       xfree(pwname);
+       bzero(pwdir, strlen(pwdir));
+       xfree(pwdir);
+}
+
+static void
+main_sigchld_handler(int sig)
+{
+       int save_errno = errno;
+       pid_t pid;
+       int status;
+
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
+           (pid < 0 && errno == EINTR))
+               ;
+
+       signal(sig, main_sigchld_handler);
+       errno = save_errno;
+}
+
diff --git a/.pc/user-group-modes.patch/auth-rhosts.c b/.pc/user-group-modes.patch/auth-rhosts.c
new file mode 100644 (file)
index 0000000..06ae7f0
--- /dev/null
@@ -0,0 +1,321 @@
+/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Rhosts authentication.  This file contains code to check whether to admit
+ * the login based on rhosts authentication.  This file also processes
+ * /etc/hosts.equiv.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_NETGROUP_H
+# include <netgroup.h>
+#endif
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "packet.h"
+#include "buffer.h"
+#include "uidswap.h"
+#include "pathnames.h"
+#include "log.h"
+#include "servconf.h"
+#include "canohost.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "misc.h"
+
+/* import */
+extern ServerOptions options;
+extern int use_privsep;
+
+/*
+ * This function processes an rhosts-style file (.rhosts, .shosts, or
+ * /etc/hosts.equiv).  This returns true if authentication can be granted
+ * based on the file, and returns zero otherwise.
+ */
+
+static int
+check_rhosts_file(const char *filename, const char *hostname,
+                 const char *ipaddr, const char *client_user,
+                 const char *server_user)
+{
+       FILE *f;
+       char buf[1024]; /* Must not be larger than host, user, dummy below. */
+       int fd;
+       struct stat st;
+
+       /* Open the .rhosts file, deny if unreadable */
+       if ((fd = open(filename, O_RDONLY|O_NONBLOCK)) == -1)
+               return 0;
+       if (fstat(fd, &st) == -1) {
+               close(fd);
+               return 0;
+       }
+       if (!S_ISREG(st.st_mode)) {
+               logit("User %s hosts file %s is not a regular file",
+                   server_user, filename);
+               close(fd);
+               return 0;
+       }
+       unset_nonblock(fd);
+       if ((f = fdopen(fd, "r")) == NULL) {
+               close(fd);
+               return 0;
+       }
+       while (fgets(buf, sizeof(buf), f)) {
+               /* All three must be at least as big as buf to avoid overflows. */
+               char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
+               int negated;
+
+               for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               if (*cp == '#' || *cp == '\n' || !*cp)
+                       continue;
+
+               /*
+                * NO_PLUS is supported at least on OSF/1.  We skip it (we
+                * don't ever support the plus syntax).
+                */
+               if (strncmp(cp, "NO_PLUS", 7) == 0)
+                       continue;
+
+               /*
+                * This should be safe because each buffer is as big as the
+                * whole string, and thus cannot be overwritten.
+                */
+               switch (sscanf(buf, "%1023s %1023s %1023s", hostbuf, userbuf,
+                   dummy)) {
+               case 0:
+                       auth_debug_add("Found empty line in %.100s.", filename);
+                       continue;
+               case 1:
+                       /* Host name only. */
+                       strlcpy(userbuf, server_user, sizeof(userbuf));
+                       break;
+               case 2:
+                       /* Got both host and user name. */
+                       break;
+               case 3:
+                       auth_debug_add("Found garbage in %.100s.", filename);
+                       continue;
+               default:
+                       /* Weird... */
+                       continue;
+               }
+
+               host = hostbuf;
+               user = userbuf;
+               negated = 0;
+
+               /* Process negated host names, or positive netgroups. */
+               if (host[0] == '-') {
+                       negated = 1;
+                       host++;
+               } else if (host[0] == '+')
+                       host++;
+
+               if (user[0] == '-') {
+                       negated = 1;
+                       user++;
+               } else if (user[0] == '+')
+                       user++;
+
+               /* Check for empty host/user names (particularly '+'). */
+               if (!host[0] || !user[0]) {
+                       /* We come here if either was '+' or '-'. */
+                       auth_debug_add("Ignoring wild host/user names in %.100s.",
+                           filename);
+                       continue;
+               }
+               /* Verify that host name matches. */
+               if (host[0] == '@') {
+                       if (!innetgr(host + 1, hostname, NULL, NULL) &&
+                           !innetgr(host + 1, ipaddr, NULL, NULL))
+                               continue;
+               } else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
+                       continue;       /* Different hostname. */
+
+               /* Verify that user name matches. */
+               if (user[0] == '@') {
+                       if (!innetgr(user + 1, NULL, client_user, NULL))
+                               continue;
+               } else if (strcmp(user, client_user) != 0)
+                       continue;       /* Different username. */
+
+               /* Found the user and host. */
+               fclose(f);
+
+               /* If the entry was negated, deny access. */
+               if (negated) {
+                       auth_debug_add("Matched negative entry in %.100s.",
+                           filename);
+                       return 0;
+               }
+               /* Accept authentication. */
+               return 1;
+       }
+
+       /* Authentication using this file denied. */
+       fclose(f);
+       return 0;
+}
+
+/*
+ * Tries to authenticate the user using the .shosts or .rhosts file. Returns
+ * true if authentication succeeds.  If ignore_rhosts is true, only
+ * /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored).
+ */
+
+int
+auth_rhosts(struct passwd *pw, const char *client_user)
+{
+       const char *hostname, *ipaddr;
+
+       hostname = get_canonical_hostname(options.use_dns);
+       ipaddr = get_remote_ipaddr();
+       return auth_rhosts2(pw, client_user, hostname, ipaddr);
+}
+
+static int
+auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
+    const char *ipaddr)
+{
+       char buf[1024];
+       struct stat st;
+       static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
+       u_int rhosts_file_index;
+
+       debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s",
+           client_user, hostname, ipaddr);
+
+       /* Switch to the user's uid. */
+       temporarily_use_uid(pw);
+       /*
+        * Quick check: if the user has no .shosts or .rhosts files, return
+        * failure immediately without doing costly lookups from name
+        * servers.
+        */
+       for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
+           rhosts_file_index++) {
+               /* Check users .rhosts or .shosts. */
+               snprintf(buf, sizeof buf, "%.500s/%.100s",
+                        pw->pw_dir, rhosts_files[rhosts_file_index]);
+               if (stat(buf, &st) >= 0)
+                       break;
+       }
+       /* Switch back to privileged uid. */
+       restore_uid();
+
+       /* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */
+       if (!rhosts_files[rhosts_file_index] &&
+           stat(_PATH_RHOSTS_EQUIV, &st) < 0 &&
+           stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0)
+               return 0;
+
+       /* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
+       if (pw->pw_uid != 0) {
+               if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
+                   client_user, pw->pw_name)) {
+                       auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
+                           hostname, ipaddr);
+                       return 1;
+               }
+               if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
+                   client_user, pw->pw_name)) {
+                       auth_debug_add("Accepted for %.100s [%.100s] by %.100s.",
+                           hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
+                       return 1;
+               }
+       }
+       /*
+        * Check that the home directory is owned by root or the user, and is
+        * not group or world writable.
+        */
+       if (stat(pw->pw_dir, &st) < 0) {
+               logit("Rhosts authentication refused for %.100s: "
+                   "no home directory %.200s", pw->pw_name, pw->pw_dir);
+               auth_debug_add("Rhosts authentication refused for %.100s: "
+                   "no home directory %.200s", pw->pw_name, pw->pw_dir);
+               return 0;
+       }
+       if (options.strict_modes &&
+           ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+           (st.st_mode & 022) != 0)) {
+               logit("Rhosts authentication refused for %.100s: "
+                   "bad ownership or modes for home directory.", pw->pw_name);
+               auth_debug_add("Rhosts authentication refused for %.100s: "
+                   "bad ownership or modes for home directory.", pw->pw_name);
+               return 0;
+       }
+       /* Temporarily use the user's uid. */
+       temporarily_use_uid(pw);
+
+       /* Check all .rhosts files (currently .shosts and .rhosts). */
+       for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
+           rhosts_file_index++) {
+               /* Check users .rhosts or .shosts. */
+               snprintf(buf, sizeof buf, "%.500s/%.100s",
+                        pw->pw_dir, rhosts_files[rhosts_file_index]);
+               if (stat(buf, &st) < 0)
+                       continue;
+
+               /*
+                * Make sure that the file is either owned by the user or by
+                * root, and make sure it is not writable by anyone but the
+                * owner.  This is to help avoid novices accidentally
+                * allowing access to their account by anyone.
+                */
+               if (options.strict_modes &&
+                   ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+                   (st.st_mode & 022) != 0)) {
+                       logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
+                           pw->pw_name, buf);
+                       auth_debug_add("Bad file modes for %.200s", buf);
+                       continue;
+               }
+               /* Check if we have been configured to ignore .rhosts and .shosts files. */
+               if (options.ignore_rhosts) {
+                       auth_debug_add("Server has been configured to ignore %.100s.",
+                           rhosts_files[rhosts_file_index]);
+                       continue;
+               }
+               /* Check if authentication is permitted by the file. */
+               if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
+                       auth_debug_add("Accepted by %.100s.",
+                           rhosts_files[rhosts_file_index]);
+                       /* Restore the privileged uid. */
+                       restore_uid();
+                       auth_debug_add("Accepted host %s ip %s client_user %s server_user %s",
+                               hostname, ipaddr, client_user, pw->pw_name);
+                       return 1;
+               }
+       }
+
+       /* Restore the privileged uid. */
+       restore_uid();
+       return 0;
+}
+
+int
+auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
+    const char *ipaddr)
+{
+       return auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
+}
diff --git a/.pc/user-group-modes.patch/auth.c b/.pc/user-group-modes.patch/auth.c
new file mode 100644 (file)
index 0000000..c76b53f
--- /dev/null
@@ -0,0 +1,720 @@
+/* $OpenBSD: auth.c,v 1.94 2011/05/23 03:33:38 djm Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+#include <pwd.h>
+#ifdef HAVE_LOGIN_H
+#include <login.h>
+#endif
+#ifdef USE_SHADOW
+#include <shadow.h>
+#endif
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "match.h"
+#include "groupaccess.h"
+#include "log.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "key.h"
+#include "hostfile.h"
+#include "authfile.h"
+#include "auth.h"
+#include "auth-options.h"
+#include "canohost.h"
+#include "uidswap.h"
+#include "misc.h"
+#include "packet.h"
+#include "loginrec.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+#include "authfile.h"
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+extern int use_privsep;
+extern Buffer loginmsg;
+extern struct passwd *privsep_pw;
+
+/* Debugging messages */
+Buffer auth_debug;
+int auth_debug_init;
+
+/*
+ * Check if the user is allowed to log in via ssh. If user is listed
+ * in DenyUsers or one of user's groups is listed in DenyGroups, false
+ * will be returned. If AllowUsers isn't empty and user isn't listed
+ * there, or if AllowGroups isn't empty and one of user's groups isn't
+ * listed there, false will be returned.
+ * If the user's shell is not executable, false will be returned.
+ * Otherwise true is returned.
+ */
+int
+allowed_user(struct passwd * pw)
+{
+       struct stat st;
+       const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
+       u_int i;
+#ifdef USE_SHADOW
+       struct spwd *spw = NULL;
+#endif
+
+       /* Shouldn't be called if pw is NULL, but better safe than sorry... */
+       if (!pw || !pw->pw_name)
+               return 0;
+
+#ifdef USE_SHADOW
+       if (!options.use_pam)
+               spw = getspnam(pw->pw_name);
+#ifdef HAS_SHADOW_EXPIRE
+       if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
+               return 0;
+#endif /* HAS_SHADOW_EXPIRE */
+#endif /* USE_SHADOW */
+
+       /* grab passwd field for locked account check */
+       passwd = pw->pw_passwd;
+#ifdef USE_SHADOW
+       if (spw != NULL)
+#ifdef USE_LIBIAF
+               passwd = get_iaf_password(pw);
+#else
+               passwd = spw->sp_pwdp;
+#endif /* USE_LIBIAF */
+#endif
+
+       /* check for locked account */
+       if (!options.use_pam && passwd && *passwd) {
+               int locked = 0;
+
+#ifdef LOCKED_PASSWD_STRING
+               if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
+                        locked = 1;
+#endif
+#ifdef LOCKED_PASSWD_PREFIX
+               if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
+                   strlen(LOCKED_PASSWD_PREFIX)) == 0)
+                        locked = 1;
+#endif
+#ifdef LOCKED_PASSWD_SUBSTR
+               if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
+                       locked = 1;
+#endif
+#ifdef USE_LIBIAF
+               free((void *) passwd);
+#endif /* USE_LIBIAF */
+               if (locked) {
+                       logit("User %.100s not allowed because account is locked",
+                           pw->pw_name);
+                       return 0;
+               }
+       }
+
+       /*
+        * Deny if shell does not exist or is not executable unless we
+        * are chrooting.
+        */
+       if (options.chroot_directory == NULL ||
+           strcasecmp(options.chroot_directory, "none") == 0) {
+               char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
+                   _PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
+
+               if (stat(shell, &st) != 0) {
+                       logit("User %.100s not allowed because shell %.100s "
+                           "does not exist", pw->pw_name, shell);
+                       xfree(shell);
+                       return 0;
+               }
+               if (S_ISREG(st.st_mode) == 0 ||
+                   (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
+                       logit("User %.100s not allowed because shell %.100s "
+                           "is not executable", pw->pw_name, shell);
+                       xfree(shell);
+                       return 0;
+               }
+               xfree(shell);
+       }
+
+       if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
+           options.num_deny_groups > 0 || options.num_allow_groups > 0) {
+               hostname = get_canonical_hostname(options.use_dns);
+               ipaddr = get_remote_ipaddr();
+       }
+
+       /* Return false if user is listed in DenyUsers */
+       if (options.num_deny_users > 0) {
+               for (i = 0; i < options.num_deny_users; i++)
+                       if (match_user(pw->pw_name, hostname, ipaddr,
+                           options.deny_users[i])) {
+                               logit("User %.100s from %.100s not allowed "
+                                   "because listed in DenyUsers",
+                                   pw->pw_name, hostname);
+                               return 0;
+                       }
+       }
+       /* Return false if AllowUsers isn't empty and user isn't listed there */
+       if (options.num_allow_users > 0) {
+               for (i = 0; i < options.num_allow_users; i++)
+                       if (match_user(pw->pw_name, hostname, ipaddr,
+                           options.allow_users[i]))
+                               break;
+               /* i < options.num_allow_users iff we break for loop */
+               if (i >= options.num_allow_users) {
+                       logit("User %.100s from %.100s not allowed because "
+                           "not listed in AllowUsers", pw->pw_name, hostname);
+                       return 0;
+               }
+       }
+       if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
+               /* Get the user's group access list (primary and supplementary) */
+               if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+                       logit("User %.100s from %.100s not allowed because "
+                           "not in any group", pw->pw_name, hostname);
+                       return 0;
+               }
+
+               /* Return false if one of user's groups is listed in DenyGroups */
+               if (options.num_deny_groups > 0)
+                       if (ga_match(options.deny_groups,
+                           options.num_deny_groups)) {
+                               ga_free();
+                               logit("User %.100s from %.100s not allowed "
+                                   "because a group is listed in DenyGroups",
+                                   pw->pw_name, hostname);
+                               return 0;
+                       }
+               /*
+                * Return false if AllowGroups isn't empty and one of user's groups
+                * isn't listed there
+                */
+               if (options.num_allow_groups > 0)
+                       if (!ga_match(options.allow_groups,
+                           options.num_allow_groups)) {
+                               ga_free();
+                               logit("User %.100s from %.100s not allowed "
+                                   "because none of user's groups are listed "
+                                   "in AllowGroups", pw->pw_name, hostname);
+                               return 0;
+                       }
+               ga_free();
+       }
+
+#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER
+       if (!sys_auth_allowed_user(pw, &loginmsg))
+               return 0;
+#endif
+
+       /* We found no reason not to let this user try to log on... */
+       return 1;
+}
+
+void
+auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
+{
+       void (*authlog) (const char *fmt,...) = verbose;
+       char *authmsg;
+
+       if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
+               return;
+
+       /* Raise logging level */
+       if (authenticated == 1 ||
+           !authctxt->valid ||
+           authctxt->failures >= options.max_authtries / 2 ||
+           strcmp(method, "password") == 0)
+               authlog = logit;
+
+       if (authctxt->postponed)
+               authmsg = "Postponed";
+       else
+               authmsg = authenticated ? "Accepted" : "Failed";
+
+       authlog("%s %s for %s%.100s from %.200s port %d%s",
+           authmsg,
+           method,
+           authctxt->valid ? "" : "invalid user ",
+           authctxt->user,
+           get_remote_ipaddr(),
+           get_remote_port(),
+           info);
+
+#ifdef CUSTOM_FAILED_LOGIN
+       if (authenticated == 0 && !authctxt->postponed &&
+           (strcmp(method, "password") == 0 ||
+           strncmp(method, "keyboard-interactive", 20) == 0 ||
+           strcmp(method, "challenge-response") == 0))
+               record_failed_login(authctxt->user,
+                   get_canonical_hostname(options.use_dns), "ssh");
+# ifdef WITH_AIXAUTHENTICATE
+       if (authenticated)
+               sys_auth_record_login(authctxt->user,
+                   get_canonical_hostname(options.use_dns), "ssh", &loginmsg);
+# endif
+#endif
+#ifdef SSH_AUDIT_EVENTS
+       if (authenticated == 0 && !authctxt->postponed)
+               audit_event(audit_classify_auth(method));
+#endif
+}
+
+/*
+ * Check whether root logins are disallowed.
+ */
+int
+auth_root_allowed(char *method)
+{
+       switch (options.permit_root_login) {
+       case PERMIT_YES:
+               return 1;
+       case PERMIT_NO_PASSWD:
+               if (strcmp(method, "password") != 0)
+                       return 1;
+               break;
+       case PERMIT_FORCED_ONLY:
+               if (forced_command) {
+                       logit("Root login accepted for forced command.");
+                       return 1;
+               }
+               break;
+       }
+       logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
+       return 0;
+}
+
+
+/*
+ * Given a template and a passwd structure, build a filename
+ * by substituting % tokenised options. Currently, %% becomes '%',
+ * %h becomes the home directory and %u the username.
+ *
+ * This returns a buffer allocated by xmalloc.
+ */
+char *
+expand_authorized_keys(const char *filename, struct passwd *pw)
+{
+       char *file, ret[MAXPATHLEN];
+       int i;
+
+       file = percent_expand(filename, "h", pw->pw_dir,
+           "u", pw->pw_name, (char *)NULL);
+
+       /*
+        * Ensure that filename starts anchored. If not, be backward
+        * compatible and prepend the '%h/'
+        */
+       if (*file == '/')
+               return (file);
+
+       i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
+       if (i < 0 || (size_t)i >= sizeof(ret))
+               fatal("expand_authorized_keys: path too long");
+       xfree(file);
+       return (xstrdup(ret));
+}
+
+char *
+authorized_principals_file(struct passwd *pw)
+{
+       if (options.authorized_principals_file == NULL)
+               return NULL;
+       return expand_authorized_keys(options.authorized_principals_file, pw);
+}
+
+/* return ok if key exists in sysfile or userfile */
+HostStatus
+check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
+    const char *sysfile, const char *userfile)
+{
+       char *user_hostfile;
+       struct stat st;
+       HostStatus host_status;
+       struct hostkeys *hostkeys;
+       const struct hostkey_entry *found;
+
+       hostkeys = init_hostkeys();
+       load_hostkeys(hostkeys, host, sysfile);
+       if (userfile != NULL) {
+               user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
+               if (options.strict_modes &&
+                   (stat(user_hostfile, &st) == 0) &&
+                   ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+                   (st.st_mode & 022) != 0)) {
+                       logit("Authentication refused for %.100s: "
+                           "bad owner or modes for %.200s",
+                           pw->pw_name, user_hostfile);
+                       auth_debug_add("Ignored %.200s: bad ownership or modes",
+                           user_hostfile);
+               } else {
+                       temporarily_use_uid(pw);
+                       load_hostkeys(hostkeys, host, user_hostfile);
+                       restore_uid();
+               }
+               xfree(user_hostfile);
+       }
+       host_status = check_key_in_hostkeys(hostkeys, key, &found);
+       if (host_status == HOST_REVOKED)
+               error("WARNING: revoked key for %s attempted authentication",
+                   found->host);
+       else if (host_status == HOST_OK)
+               debug("%s: key for %s found at %s:%ld", __func__,
+                   found->host, found->file, found->line);
+       else
+               debug("%s: key for host %s not found", __func__, host);
+
+       free_hostkeys(hostkeys);
+
+       return host_status;
+}
+
+
+/*
+ * Check a given file for security. This is defined as all components
+ * of the path to the file must be owned by either the owner of
+ * of the file or root and no directories must be group or world writable.
+ *
+ * XXX Should any specific check be done for sym links ?
+ *
+ * Takes an open file descriptor, the file name, a uid and and
+ * error buffer plus max size as arguments.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+static int
+secure_filename(FILE *f, const char *file, struct passwd *pw,
+    char *err, size_t errlen)
+{
+       uid_t uid = pw->pw_uid;
+       char buf[MAXPATHLEN], homedir[MAXPATHLEN];
+       char *cp;
+       int comparehome = 0;
+       struct stat st;
+
+       if (realpath(file, buf) == NULL) {
+               snprintf(err, errlen, "realpath %s failed: %s", file,
+                   strerror(errno));
+               return -1;
+       }
+       if (realpath(pw->pw_dir, homedir) != NULL)
+               comparehome = 1;
+
+       /* check the open file to avoid races */
+       if (fstat(fileno(f), &st) < 0 ||
+           (st.st_uid != 0 && st.st_uid != uid) ||
+           (st.st_mode & 022) != 0) {
+               snprintf(err, errlen, "bad ownership or modes for file %s",
+                   buf);
+               return -1;
+       }
+
+       /* for each component of the canonical path, walking upwards */
+       for (;;) {
+               if ((cp = dirname(buf)) == NULL) {
+                       snprintf(err, errlen, "dirname() failed");
+                       return -1;
+               }
+               strlcpy(buf, cp, sizeof(buf));
+
+               if (stat(buf, &st) < 0 ||
+                   (st.st_uid != 0 && st.st_uid != uid) ||
+                   (st.st_mode & 022) != 0) {
+                       snprintf(err, errlen,
+                           "bad ownership or modes for directory %s", buf);
+                       return -1;
+               }
+
+               /* If are past the homedir then we can stop */
+               if (comparehome && strcmp(homedir, buf) == 0)
+                       break;
+
+               /*
+                * dirname should always complete with a "/" path,
+                * but we can be paranoid and check for "." too
+                */
+               if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
+                       break;
+       }
+       return 0;
+}
+
+static FILE *
+auth_openfile(const char *file, struct passwd *pw, int strict_modes,
+    int log_missing, char *file_type)
+{
+       char line[1024];
+       struct stat st;
+       int fd;
+       FILE *f;
+
+       if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
+               if (log_missing || errno != ENOENT)
+                       debug("Could not open %s '%s': %s", file_type, file,
+                          strerror(errno));
+               return NULL;
+       }
+
+       if (fstat(fd, &st) < 0) {
+               close(fd);
+               return NULL;
+       }
+       if (!S_ISREG(st.st_mode)) {
+               logit("User %s %s %s is not a regular file",
+                   pw->pw_name, file_type, file);
+               close(fd);
+               return NULL;
+       }
+       unset_nonblock(fd);
+       if ((f = fdopen(fd, "r")) == NULL) {
+               close(fd);
+               return NULL;
+       }
+       if (strict_modes &&
+           secure_filename(f, file, pw, line, sizeof(line)) != 0) {
+               fclose(f);
+               logit("Authentication refused: %s", line);
+               auth_debug_add("Ignored %s: %s", file_type, line);
+               return NULL;
+       }
+
+       return f;
+}
+
+
+FILE *
+auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
+{
+       return auth_openfile(file, pw, strict_modes, 1, "authorized keys");
+}
+
+FILE *
+auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
+{
+       return auth_openfile(file, pw, strict_modes, 0,
+           "authorized principals");
+}
+
+struct passwd *
+getpwnamallow(const char *user)
+{
+#ifdef HAVE_LOGIN_CAP
+       extern login_cap_t *lc;
+#ifdef BSD_AUTH
+       auth_session_t *as;
+#endif
+#endif
+       struct passwd *pw;
+
+       parse_server_match_config(&options, user,
+           get_canonical_hostname(options.use_dns), get_remote_ipaddr());
+
+#if defined(_AIX) && defined(HAVE_SETAUTHDB)
+       aix_setauthdb(user);
+#endif
+
+       pw = getpwnam(user);
+
+#if defined(_AIX) && defined(HAVE_SETAUTHDB)
+       aix_restoreauthdb();
+#endif
+#ifdef HAVE_CYGWIN
+       /*
+        * Windows usernames are case-insensitive.  To avoid later problems
+        * when trying to match the username, the user is only allowed to
+        * login if the username is given in the same case as stored in the
+        * user database.
+        */
+       if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
+               logit("Login name %.100s does not match stored username %.100s",
+                   user, pw->pw_name);
+               pw = NULL;
+       }
+#endif
+       if (pw == NULL) {
+               logit("Invalid user %.100s from %.100s",
+                   user, get_remote_ipaddr());
+#ifdef CUSTOM_FAILED_LOGIN
+               record_failed_login(user,
+                   get_canonical_hostname(options.use_dns), "ssh");
+#endif
+#ifdef SSH_AUDIT_EVENTS
+               audit_event(SSH_INVALID_USER);
+#endif /* SSH_AUDIT_EVENTS */
+               return (NULL);
+       }
+       if (!allowed_user(pw))
+               return (NULL);
+#ifdef HAVE_LOGIN_CAP
+       if ((lc = login_getclass(pw->pw_class)) == NULL) {
+               debug("unable to get login class: %s", user);
+               return (NULL);
+       }
+#ifdef BSD_AUTH
+       if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
+           auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
+               debug("Approval failure for %s", user);
+               pw = NULL;
+       }
+       if (as != NULL)
+               auth_close(as);
+#endif
+#endif
+       if (pw != NULL)
+               return (pwcopy(pw));
+       return (NULL);
+}
+
+/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
+int
+auth_key_is_revoked(Key *key, int hostkey)
+{
+       char *key_fp;
+
+       if (blacklisted_key(key, &key_fp) == 1) {
+               if (options.permit_blacklisted_keys) {
+                       if (hostkey)
+                               error("Host key %s blacklisted (see "
+                                   "ssh-vulnkey(1)); continuing anyway",
+                                   key_fp);
+                       else
+                               logit("Public key %s from %s blacklisted (see "
+                                   "ssh-vulnkey(1)); continuing anyway",
+                                   key_fp, get_remote_ipaddr());
+                       xfree(key_fp);
+               } else {
+                       if (hostkey)
+                               error("Host key %s blacklisted (see "
+                                   "ssh-vulnkey(1))", key_fp);
+                       else
+                               logit("Public key %s from %s blacklisted (see "
+                                   "ssh-vulnkey(1))",
+                                   key_fp, get_remote_ipaddr());
+                       xfree(key_fp);
+                       return 1;
+               }
+       }
+
+       if (options.revoked_keys_file == NULL)
+               return 0;
+
+       switch (key_in_file(key, options.revoked_keys_file, 0)) {
+       case 0:
+               /* key not revoked */
+               return 0;
+       case -1:
+               /* Error opening revoked_keys_file: refuse all keys */
+               error("Revoked keys file is unreadable: refusing public key "
+                   "authentication");
+               return 1;
+       case 1:
+               /* Key revoked */
+               key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+               error("WARNING: authentication attempt with a revoked "
+                   "%s key %s ", key_type(key), key_fp);
+               xfree(key_fp);
+               return 1;
+       }
+       fatal("key_in_file returned junk");
+}
+
+void
+auth_debug_add(const char *fmt,...)
+{
+       char buf[1024];
+       va_list args;
+
+       if (!auth_debug_init)
+               return;
+
+       va_start(args, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, args);
+       va_end(args);
+       buffer_put_cstring(&auth_debug, buf);
+}
+
+void
+auth_debug_send(void)
+{
+       char *msg;
+
+       if (!auth_debug_init)
+               return;
+       while (buffer_len(&auth_debug)) {
+               msg = buffer_get_string(&auth_debug, NULL);
+               packet_send_debug("%s", msg);
+               xfree(msg);
+       }
+}
+
+void
+auth_debug_reset(void)
+{
+       if (auth_debug_init)
+               buffer_clear(&auth_debug);
+       else {
+               buffer_init(&auth_debug);
+               auth_debug_init = 1;
+       }
+}
+
+struct passwd *
+fakepw(void)
+{
+       static struct passwd fake;
+
+       memset(&fake, 0, sizeof(fake));
+       fake.pw_name = "NOUSER";
+       fake.pw_passwd =
+           "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
+       fake.pw_gecos = "NOUSER";
+       fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
+       fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+       fake.pw_class = "";
+#endif
+       fake.pw_dir = "/nonexist";
+       fake.pw_shell = "/nonexist";
+
+       return (&fake);
+}
diff --git a/.pc/user-group-modes.patch/misc.c b/.pc/user-group-modes.patch/misc.c
new file mode 100644 (file)
index 0000000..5f63090
--- /dev/null
@@ -0,0 +1,1011 @@
+/* $OpenBSD: misc.c,v 1.85 2011/03/29 18:54:17 stevesk Exp $ */
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#include <pwd.h>
+#endif
+#ifdef SSH_TUN_OPENBSD
+#include <net/if.h>
+#endif
+
+#include "xmalloc.h"
+#include "misc.h"
+#include "log.h"
+#include "ssh.h"
+
+/* remove newline at end of string */
+char *
+chop(char *s)
+{
+       char *t = s;
+       while (*t) {
+               if (*t == '\n' || *t == '\r') {
+                       *t = '\0';
+                       return s;
+               }
+               t++;
+       }
+       return s;
+
+}
+
+/* set/unset filedescriptor to non-blocking */
+int
+set_nonblock(int fd)
+{
+       int val;
+
+       val = fcntl(fd, F_GETFL, 0);
+       if (val < 0) {
+               error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
+               return (-1);
+       }
+       if (val & O_NONBLOCK) {
+               debug3("fd %d is O_NONBLOCK", fd);
+               return (0);
+       }
+       debug2("fd %d setting O_NONBLOCK", fd);
+       val |= O_NONBLOCK;
+       if (fcntl(fd, F_SETFL, val) == -1) {
+               debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
+                   strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+
+int
+unset_nonblock(int fd)
+{
+       int val;
+
+       val = fcntl(fd, F_GETFL, 0);
+       if (val < 0) {
+               error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
+               return (-1);
+       }
+       if (!(val & O_NONBLOCK)) {
+               debug3("fd %d is not O_NONBLOCK", fd);
+               return (0);
+       }
+       debug("fd %d clearing O_NONBLOCK", fd);
+       val &= ~O_NONBLOCK;
+       if (fcntl(fd, F_SETFL, val) == -1) {
+               debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
+                   fd, strerror(errno));
+               return (-1);
+       }
+       return (0);
+}
+
+const char *
+ssh_gai_strerror(int gaierr)
+{
+       if (gaierr == EAI_SYSTEM)
+               return strerror(errno);
+       return gai_strerror(gaierr);
+}
+
+/* disable nagle on socket */
+void
+set_nodelay(int fd)
+{
+       int opt;
+       socklen_t optlen;
+
+       optlen = sizeof opt;
+       if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
+               debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
+               return;
+       }
+       if (opt == 1) {
+               debug2("fd %d is TCP_NODELAY", fd);
+               return;
+       }
+       opt = 1;
+       debug2("fd %d setting TCP_NODELAY", fd);
+       if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
+               error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
+}
+
+/* Characters considered whitespace in strsep calls. */
+#define WHITESPACE " \t\r\n"
+#define QUOTE  "\""
+
+/* return next token in configuration line */
+char *
+strdelim(char **s)
+{
+       char *old;
+       int wspace = 0;
+
+       if (*s == NULL)
+               return NULL;
+
+       old = *s;
+
+       *s = strpbrk(*s, WHITESPACE QUOTE "=");
+       if (*s == NULL)
+               return (old);
+
+       if (*s[0] == '\"') {
+               memmove(*s, *s + 1, strlen(*s)); /* move nul too */
+               /* Find matching quote */
+               if ((*s = strpbrk(*s, QUOTE)) == NULL) {
+                       return (NULL);          /* no matching quote */
+               } else {
+                       *s[0] = '\0';
+                       *s += strspn(*s + 1, WHITESPACE) + 1;
+                       return (old);
+               }
+       }
+
+       /* Allow only one '=' to be skipped */
+       if (*s[0] == '=')
+               wspace = 1;
+       *s[0] = '\0';
+
+       /* Skip any extra whitespace after first token */
+       *s += strspn(*s + 1, WHITESPACE) + 1;
+       if (*s[0] == '=' && !wspace)
+               *s += strspn(*s + 1, WHITESPACE) + 1;
+
+       return (old);
+}
+
+struct passwd *
+pwcopy(struct passwd *pw)
+{
+       struct passwd *copy = xcalloc(1, sizeof(*copy));
+
+       copy->pw_name = xstrdup(pw->pw_name);
+       copy->pw_passwd = xstrdup(pw->pw_passwd);
+       copy->pw_gecos = xstrdup(pw->pw_gecos);
+       copy->pw_uid = pw->pw_uid;
+       copy->pw_gid = pw->pw_gid;
+#ifdef HAVE_PW_EXPIRE_IN_PASSWD
+       copy->pw_expire = pw->pw_expire;
+#endif
+#ifdef HAVE_PW_CHANGE_IN_PASSWD
+       copy->pw_change = pw->pw_change;
+#endif
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+       copy->pw_class = xstrdup(pw->pw_class);
+#endif
+       copy->pw_dir = xstrdup(pw->pw_dir);
+       copy->pw_shell = xstrdup(pw->pw_shell);
+       return copy;
+}
+
+/*
+ * Convert ASCII string to TCP/IP port number.
+ * Port must be >=0 and <=65535.
+ * Return -1 if invalid.
+ */
+int
+a2port(const char *s)
+{
+       long long port;
+       const char *errstr;
+
+       port = strtonum(s, 0, 65535, &errstr);
+       if (errstr != NULL)
+               return -1;
+       return (int)port;
+}
+
+int
+a2tun(const char *s, int *remote)
+{
+       const char *errstr = NULL;
+       char *sp, *ep;
+       int tun;
+
+       if (remote != NULL) {
+               *remote = SSH_TUNID_ANY;
+               sp = xstrdup(s);
+               if ((ep = strchr(sp, ':')) == NULL) {
+                       xfree(sp);
+                       return (a2tun(s, NULL));
+               }
+               ep[0] = '\0'; ep++;
+               *remote = a2tun(ep, NULL);
+               tun = a2tun(sp, NULL);
+               xfree(sp);
+               return (*remote == SSH_TUNID_ERR ? *remote : tun);
+       }
+
+       if (strcasecmp(s, "any") == 0)
+               return (SSH_TUNID_ANY);
+
+       tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
+       if (errstr != NULL)
+               return (SSH_TUNID_ERR);
+
+       return (tun);
+}
+
+#define SECONDS                1
+#define MINUTES                (SECONDS * 60)
+#define HOURS          (MINUTES * 60)
+#define DAYS           (HOURS * 24)
+#define WEEKS          (DAYS * 7)
+
+/*
+ * Convert a time string into seconds; format is
+ * a sequence of:
+ *      time[qualifier]
+ *
+ * Valid time qualifiers are:
+ *      <none>  seconds
+ *      s|S     seconds
+ *      m|M     minutes
+ *      h|H     hours
+ *      d|D     days
+ *      w|W     weeks
+ *
+ * Examples:
+ *      90m     90 minutes
+ *      1h30m   90 minutes
+ *      2d      2 days
+ *      1w      1 week
+ *
+ * Return -1 if time string is invalid.
+ */
+long
+convtime(const char *s)
+{
+       long total, secs;
+       const char *p;
+       char *endp;
+
+       errno = 0;
+       total = 0;
+       p = s;
+
+       if (p == NULL || *p == '\0')
+               return -1;
+
+       while (*p) {
+               secs = strtol(p, &endp, 10);
+               if (p == endp ||
+                   (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
+                   secs < 0)
+                       return -1;
+
+               switch (*endp++) {
+               case '\0':
+                       endp--;
+                       break;
+               case 's':
+               case 'S':
+                       break;
+               case 'm':
+               case 'M':
+                       secs *= MINUTES;
+                       break;
+               case 'h':
+               case 'H':
+                       secs *= HOURS;
+                       break;
+               case 'd':
+               case 'D':
+                       secs *= DAYS;
+                       break;
+               case 'w':
+               case 'W':
+                       secs *= WEEKS;
+                       break;
+               default:
+                       return -1;
+               }
+               total += secs;
+               if (total < 0)
+                       return -1;
+               p = endp;
+       }
+
+       return total;
+}
+
+/*
+ * Returns a standardized host+port identifier string.
+ * Caller must free returned string.
+ */
+char *
+put_host_port(const char *host, u_short port)
+{
+       char *hoststr;
+
+       if (port == 0 || port == SSH_DEFAULT_PORT)
+               return(xstrdup(host));
+       if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
+               fatal("put_host_port: asprintf: %s", strerror(errno));
+       debug3("put_host_port: %s", hoststr);
+       return hoststr;
+}
+
+/*
+ * Search for next delimiter between hostnames/addresses and ports.
+ * Argument may be modified (for termination).
+ * Returns *cp if parsing succeeds.
+ * *cp is set to the start of the next delimiter, if one was found.
+ * If this is the last field, *cp is set to NULL.
+ */
+char *
+hpdelim(char **cp)
+{
+       char *s, *old;
+
+       if (cp == NULL || *cp == NULL)
+               return NULL;
+
+       old = s = *cp;
+       if (*s == '[') {
+               if ((s = strchr(s, ']')) == NULL)
+                       return NULL;
+               else
+                       s++;
+       } else if ((s = strpbrk(s, ":/")) == NULL)
+               s = *cp + strlen(*cp); /* skip to end (see first case below) */
+
+       switch (*s) {
+       case '\0':
+               *cp = NULL;     /* no more fields*/
+               break;
+
+       case ':':
+       case '/':
+               *s = '\0';      /* terminate */
+               *cp = s + 1;
+               break;
+
+       default:
+               return NULL;
+       }
+
+       return old;
+}
+
+char *
+cleanhostname(char *host)
+{
+       if (*host == '[' && host[strlen(host) - 1] == ']') {
+               host[strlen(host) - 1] = '\0';
+               return (host + 1);
+       } else
+               return host;
+}
+
+char *
+colon(char *cp)
+{
+       int flag = 0;
+
+       if (*cp == ':')         /* Leading colon is part of file name. */
+               return NULL;
+       if (*cp == '[')
+               flag = 1;
+
+       for (; *cp; ++cp) {
+               if (*cp == '@' && *(cp+1) == '[')
+                       flag = 1;
+               if (*cp == ']' && *(cp+1) == ':' && flag)
+                       return (cp+1);
+               if (*cp == ':' && !flag)
+                       return (cp);
+               if (*cp == '/')
+                       return NULL;
+       }
+       return NULL;
+}
+
+/* function to assist building execv() arguments */
+void
+addargs(arglist *args, char *fmt, ...)
+{
+       va_list ap;
+       char *cp;
+       u_int nalloc;
+       int r;
+
+       va_start(ap, fmt);
+       r = vasprintf(&cp, fmt, ap);
+       va_end(ap);
+       if (r == -1)
+               fatal("addargs: argument too long");
+
+       nalloc = args->nalloc;
+       if (args->list == NULL) {
+               nalloc = 32;
+               args->num = 0;
+       } else if (args->num+2 >= nalloc)
+               nalloc *= 2;
+
+       args->list = xrealloc(args->list, nalloc, sizeof(char *));
+       args->nalloc = nalloc;
+       args->list[args->num++] = cp;
+       args->list[args->num] = NULL;
+}
+
+void
+replacearg(arglist *args, u_int which, char *fmt, ...)
+{
+       va_list ap;
+       char *cp;
+       int r;
+
+       va_start(ap, fmt);
+       r = vasprintf(&cp, fmt, ap);
+       va_end(ap);
+       if (r == -1)
+               fatal("replacearg: argument too long");
+
+       if (which >= args->num)
+               fatal("replacearg: tried to replace invalid arg %d >= %d",
+                   which, args->num);
+       xfree(args->list[which]);
+       args->list[which] = cp;
+}
+
+void
+freeargs(arglist *args)
+{
+       u_int i;
+
+       if (args->list != NULL) {
+               for (i = 0; i < args->num; i++)
+                       xfree(args->list[i]);
+               xfree(args->list);
+               args->nalloc = args->num = 0;
+               args->list = NULL;
+       }
+}
+
+/*
+ * Expands tildes in the file name.  Returns data allocated by xmalloc.
+ * Warning: this calls getpw*.
+ */
+char *
+tilde_expand_filename(const char *filename, uid_t uid)
+{
+       const char *path;
+       char user[128], ret[MAXPATHLEN];
+       struct passwd *pw;
+       u_int len, slash;
+
+       if (*filename != '~')
+               return (xstrdup(filename));
+       filename++;
+
+       path = strchr(filename, '/');
+       if (path != NULL && path > filename) {          /* ~user/path */
+               slash = path - filename;
+               if (slash > sizeof(user) - 1)
+                       fatal("tilde_expand_filename: ~username too long");
+               memcpy(user, filename, slash);
+               user[slash] = '\0';
+               if ((pw = getpwnam(user)) == NULL)
+                       fatal("tilde_expand_filename: No such user %s", user);
+       } else if ((pw = getpwuid(uid)) == NULL)        /* ~/path */
+               fatal("tilde_expand_filename: No such uid %ld", (long)uid);
+
+       if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
+               fatal("tilde_expand_filename: Path too long");
+
+       /* Make sure directory has a trailing '/' */
+       len = strlen(pw->pw_dir);
+       if ((len == 0 || pw->pw_dir[len - 1] != '/') &&
+           strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
+               fatal("tilde_expand_filename: Path too long");
+
+       /* Skip leading '/' from specified path */
+       if (path != NULL)
+               filename = path + 1;
+       if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
+               fatal("tilde_expand_filename: Path too long");
+
+       return (xstrdup(ret));
+}
+
+/*
+ * Expand a string with a set of %[char] escapes. A number of escapes may be
+ * specified as (char *escape_chars, char *replacement) pairs. The list must
+ * be terminated by a NULL escape_char. Returns replaced string in memory
+ * allocated by xmalloc.
+ */
+char *
+percent_expand(const char *string, ...)
+{
+#define EXPAND_MAX_KEYS        16
+       u_int num_keys, i, j;
+       struct {
+               const char *key;
+               const char *repl;
+       } keys[EXPAND_MAX_KEYS];
+       char buf[4096];
+       va_list ap;
+
+       /* Gather keys */
+       va_start(ap, string);
+       for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
+               keys[num_keys].key = va_arg(ap, char *);
+               if (keys[num_keys].key == NULL)
+                       break;
+               keys[num_keys].repl = va_arg(ap, char *);
+               if (keys[num_keys].repl == NULL)
+                       fatal("%s: NULL replacement", __func__);
+       }
+       if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL)
+               fatal("%s: too many keys", __func__);
+       va_end(ap);
+
+       /* Expand string */
+       *buf = '\0';
+       for (i = 0; *string != '\0'; string++) {
+               if (*string != '%') {
+ append:
+                       buf[i++] = *string;
+                       if (i >= sizeof(buf))
+                               fatal("%s: string too long", __func__);
+                       buf[i] = '\0';
+                       continue;
+               }
+               string++;
+               /* %% case */
+               if (*string == '%')
+                       goto append;
+               for (j = 0; j < num_keys; j++) {
+                       if (strchr(keys[j].key, *string) != NULL) {
+                               i = strlcat(buf, keys[j].repl, sizeof(buf));
+                               if (i >= sizeof(buf))
+                                       fatal("%s: string too long", __func__);
+                               break;
+                       }
+               }
+               if (j >= num_keys)
+                       fatal("%s: unknown key %%%c", __func__, *string);
+       }
+       return (xstrdup(buf));
+#undef EXPAND_MAX_KEYS
+}
+
+/*
+ * Read an entire line from a public key file into a static buffer, discarding
+ * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
+ */
+int
+read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
+   u_long *lineno)
+{
+       while (fgets(buf, bufsz, f) != NULL) {
+               if (buf[0] == '\0')
+                       continue;
+               (*lineno)++;
+               if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
+                       return 0;
+               } else {
+                       debug("%s: %s line %lu exceeds size limit", __func__,
+                           filename, *lineno);
+                       /* discard remainder of line */
+                       while (fgetc(f) != '\n' && !feof(f))
+                               ;       /* nothing */
+               }
+       }
+       return -1;
+}
+
+int
+tun_open(int tun, int mode)
+{
+#if defined(CUSTOM_SYS_TUN_OPEN)
+       return (sys_tun_open(tun, mode));
+#elif defined(SSH_TUN_OPENBSD)
+       struct ifreq ifr;
+       char name[100];
+       int fd = -1, sock;
+
+       /* Open the tunnel device */
+       if (tun <= SSH_TUNID_MAX) {
+               snprintf(name, sizeof(name), "/dev/tun%d", tun);
+               fd = open(name, O_RDWR);
+       } else if (tun == SSH_TUNID_ANY) {
+               for (tun = 100; tun >= 0; tun--) {
+                       snprintf(name, sizeof(name), "/dev/tun%d", tun);
+                       if ((fd = open(name, O_RDWR)) >= 0)
+                               break;
+               }
+       } else {
+               debug("%s: invalid tunnel %u", __func__, tun);
+               return (-1);
+       }
+
+       if (fd < 0) {
+               debug("%s: %s open failed: %s", __func__, name, strerror(errno));
+               return (-1);
+       }
+
+       debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
+
+       /* Set the tunnel device operation mode */
+       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
+       if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
+               goto failed;
+
+       if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
+               goto failed;
+
+       /* Set interface mode */
+       ifr.ifr_flags &= ~IFF_UP;
+       if (mode == SSH_TUNMODE_ETHERNET)
+               ifr.ifr_flags |= IFF_LINK0;
+       else
+               ifr.ifr_flags &= ~IFF_LINK0;
+       if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
+               goto failed;
+
+       /* Bring interface up */
+       ifr.ifr_flags |= IFF_UP;
+       if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
+               goto failed;
+
+       close(sock);
+       return (fd);
+
+ failed:
+       if (fd >= 0)
+               close(fd);
+       if (sock >= 0)
+               close(sock);
+       debug("%s: failed to set %s mode %d: %s", __func__, name,
+           mode, strerror(errno));
+       return (-1);
+#else
+       error("Tunnel interfaces are not supported on this platform");
+       return (-1);
+#endif
+}
+
+void
+sanitise_stdfd(void)
+{
+       int nullfd, dupfd;
+
+       if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+               fprintf(stderr, "Couldn't open /dev/null: %s\n",
+                   strerror(errno));
+               exit(1);
+       }
+       while (++dupfd <= 2) {
+               /* Only clobber closed fds */
+               if (fcntl(dupfd, F_GETFL, 0) >= 0)
+                       continue;
+               if (dup2(nullfd, dupfd) == -1) {
+                       fprintf(stderr, "dup2: %s\n", strerror(errno));
+                       exit(1);
+               }
+       }
+       if (nullfd > 2)
+               close(nullfd);
+}
+
+char *
+tohex(const void *vp, size_t l)
+{
+       const u_char *p = (const u_char *)vp;
+       char b[3], *r;
+       size_t i, hl;
+
+       if (l > 65536)
+               return xstrdup("tohex: length > 65536");
+
+       hl = l * 2 + 1;
+       r = xcalloc(1, hl);
+       for (i = 0; i < l; i++) {
+               snprintf(b, sizeof(b), "%02x", p[i]);
+               strlcat(r, b, hl);
+       }
+       return (r);
+}
+
+u_int64_t
+get_u64(const void *vp)
+{
+       const u_char *p = (const u_char *)vp;
+       u_int64_t v;
+
+       v  = (u_int64_t)p[0] << 56;
+       v |= (u_int64_t)p[1] << 48;
+       v |= (u_int64_t)p[2] << 40;
+       v |= (u_int64_t)p[3] << 32;
+       v |= (u_int64_t)p[4] << 24;
+       v |= (u_int64_t)p[5] << 16;
+       v |= (u_int64_t)p[6] << 8;
+       v |= (u_int64_t)p[7];
+
+       return (v);
+}
+
+u_int32_t
+get_u32(const void *vp)
+{
+       const u_char *p = (const u_char *)vp;
+       u_int32_t v;
+
+       v  = (u_int32_t)p[0] << 24;
+       v |= (u_int32_t)p[1] << 16;
+       v |= (u_int32_t)p[2] << 8;
+       v |= (u_int32_t)p[3];
+
+       return (v);
+}
+
+u_int16_t
+get_u16(const void *vp)
+{
+       const u_char *p = (const u_char *)vp;
+       u_int16_t v;
+
+       v  = (u_int16_t)p[0] << 8;
+       v |= (u_int16_t)p[1];
+
+       return (v);
+}
+
+void
+put_u64(void *vp, u_int64_t v)
+{
+       u_char *p = (u_char *)vp;
+
+       p[0] = (u_char)(v >> 56) & 0xff;
+       p[1] = (u_char)(v >> 48) & 0xff;
+       p[2] = (u_char)(v >> 40) & 0xff;
+       p[3] = (u_char)(v >> 32) & 0xff;
+       p[4] = (u_char)(v >> 24) & 0xff;
+       p[5] = (u_char)(v >> 16) & 0xff;
+       p[6] = (u_char)(v >> 8) & 0xff;
+       p[7] = (u_char)v & 0xff;
+}
+
+void
+put_u32(void *vp, u_int32_t v)
+{
+       u_char *p = (u_char *)vp;
+
+       p[0] = (u_char)(v >> 24) & 0xff;
+       p[1] = (u_char)(v >> 16) & 0xff;
+       p[2] = (u_char)(v >> 8) & 0xff;
+       p[3] = (u_char)v & 0xff;
+}
+
+
+void
+put_u16(void *vp, u_int16_t v)
+{
+       u_char *p = (u_char *)vp;
+
+       p[0] = (u_char)(v >> 8) & 0xff;
+       p[1] = (u_char)v & 0xff;
+}
+
+void
+ms_subtract_diff(struct timeval *start, int *ms)
+{
+       struct timeval diff, finish;
+
+       gettimeofday(&finish, NULL);
+       timersub(&finish, start, &diff);        
+       *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
+}
+
+void
+ms_to_timeval(struct timeval *tv, int ms)
+{
+       if (ms < 0)
+               ms = 0;
+       tv->tv_sec = ms / 1000;
+       tv->tv_usec = (ms % 1000) * 1000;
+}
+
+void
+bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
+{
+       bw->buflen = buflen;
+       bw->rate = kbps;
+       bw->thresh = bw->rate;
+       bw->lamt = 0;
+       timerclear(&bw->bwstart);
+       timerclear(&bw->bwend);
+}      
+
+/* Callback from read/write loop to insert bandwidth-limiting delays */
+void
+bandwidth_limit(struct bwlimit *bw, size_t read_len)
+{
+       u_int64_t waitlen;
+       struct timespec ts, rm;
+
+       if (!timerisset(&bw->bwstart)) {
+               gettimeofday(&bw->bwstart, NULL);
+               return;
+       }
+
+       bw->lamt += read_len;
+       if (bw->lamt < bw->thresh)
+               return;
+
+       gettimeofday(&bw->bwend, NULL);
+       timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
+       if (!timerisset(&bw->bwend))
+               return;
+
+       bw->lamt *= 8;
+       waitlen = (double)1000000L * bw->lamt / bw->rate;
+
+       bw->bwstart.tv_sec = waitlen / 1000000L;
+       bw->bwstart.tv_usec = waitlen % 1000000L;
+
+       if (timercmp(&bw->bwstart, &bw->bwend, >)) {
+               timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
+
+               /* Adjust the wait time */
+               if (bw->bwend.tv_sec) {
+                       bw->thresh /= 2;
+                       if (bw->thresh < bw->buflen / 4)
+                               bw->thresh = bw->buflen / 4;
+               } else if (bw->bwend.tv_usec < 10000) {
+                       bw->thresh *= 2;
+                       if (bw->thresh > bw->buflen * 8)
+                               bw->thresh = bw->buflen * 8;
+               }
+
+               TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
+               while (nanosleep(&ts, &rm) == -1) {
+                       if (errno != EINTR)
+                               break;
+                       ts = rm;
+               }
+       }
+
+       bw->lamt = 0;
+       gettimeofday(&bw->bwstart, NULL);
+}
+
+/* Make a template filename for mk[sd]temp() */
+void
+mktemp_proto(char *s, size_t len)
+{
+       const char *tmpdir;
+       int r;
+
+       if ((tmpdir = getenv("TMPDIR")) != NULL) {
+               r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir);
+               if (r > 0 && (size_t)r < len)
+                       return;
+       }
+       r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
+       if (r < 0 || (size_t)r >= len)
+               fatal("%s: template string too short", __func__);
+}
+
+static const struct {
+       const char *name;
+       int value;
+} ipqos[] = {
+       { "af11", IPTOS_DSCP_AF11 },
+       { "af12", IPTOS_DSCP_AF12 },
+       { "af13", IPTOS_DSCP_AF13 },
+       { "af14", IPTOS_DSCP_AF21 },
+       { "af22", IPTOS_DSCP_AF22 },
+       { "af23", IPTOS_DSCP_AF23 },
+       { "af31", IPTOS_DSCP_AF31 },
+       { "af32", IPTOS_DSCP_AF32 },
+       { "af33", IPTOS_DSCP_AF33 },
+       { "af41", IPTOS_DSCP_AF41 },
+       { "af42", IPTOS_DSCP_AF42 },
+       { "af43", IPTOS_DSCP_AF43 },
+       { "cs0", IPTOS_DSCP_CS0 },
+       { "cs1", IPTOS_DSCP_CS1 },
+       { "cs2", IPTOS_DSCP_CS2 },
+       { "cs3", IPTOS_DSCP_CS3 },
+       { "cs4", IPTOS_DSCP_CS4 },
+       { "cs5", IPTOS_DSCP_CS5 },
+       { "cs6", IPTOS_DSCP_CS6 },
+       { "cs7", IPTOS_DSCP_CS7 },
+       { "ef", IPTOS_DSCP_EF },
+       { "lowdelay", IPTOS_LOWDELAY },
+       { "throughput", IPTOS_THROUGHPUT },
+       { "reliability", IPTOS_RELIABILITY },
+       { NULL, -1 }
+};
+
+int
+parse_ipqos(const char *cp)
+{
+       u_int i;
+       char *ep;
+       long val;
+
+       if (cp == NULL)
+               return -1;
+       for (i = 0; ipqos[i].name != NULL; i++) {
+               if (strcasecmp(cp, ipqos[i].name) == 0)
+                       return ipqos[i].value;
+       }
+       /* Try parsing as an integer */
+       val = strtol(cp, &ep, 0);
+       if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255)
+               return -1;
+       return val;
+}
+
+const char *
+iptos2str(int iptos)
+{
+       int i;
+       static char iptos_str[sizeof "0xff"];
+
+       for (i = 0; ipqos[i].name != NULL; i++) {
+               if (ipqos[i].value == iptos)
+                       return ipqos[i].name;
+       }
+       snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos);
+       return iptos_str;
+}
+void
+sock_set_v6only(int s)
+{
+#ifdef IPV6_V6ONLY
+       int on = 1;
+
+       debug3("%s: set socket %d IPV6_V6ONLY", __func__, s);
+       if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
+               error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
+#endif
+}
diff --git a/.pc/user-group-modes.patch/misc.h b/.pc/user-group-modes.patch/misc.h
new file mode 100644 (file)
index 0000000..f3142a9
--- /dev/null
@@ -0,0 +1,106 @@
+/* $OpenBSD: misc.h,v 1.48 2011/03/29 18:54:17 stevesk 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".
+ */
+
+#ifndef _MISC_H
+#define _MISC_H
+
+/* misc.c */
+
+char   *chop(char *);
+char   *strdelim(char **);
+int     set_nonblock(int);
+int     unset_nonblock(int);
+void    set_nodelay(int);
+int     a2port(const char *);
+int     a2tun(const char *, int *);
+char   *put_host_port(const char *, u_short);
+char   *hpdelim(char **);
+char   *cleanhostname(char *);
+char   *colon(char *);
+long    convtime(const char *);
+char   *tilde_expand_filename(const char *, uid_t);
+char   *percent_expand(const char *, ...) __attribute__((__sentinel__));
+char   *tohex(const void *, size_t);
+void    sanitise_stdfd(void);
+void    ms_subtract_diff(struct timeval *, int *);
+void    ms_to_timeval(struct timeval *, int);
+void    sock_set_v6only(int);
+
+struct passwd *pwcopy(struct passwd *);
+const char *ssh_gai_strerror(int);
+
+typedef struct arglist arglist;
+struct arglist {
+       char    **list;
+       u_int   num;
+       u_int   nalloc;
+};
+void    addargs(arglist *, char *, ...)
+            __attribute__((format(printf, 2, 3)));
+void    replacearg(arglist *, u_int, char *, ...)
+            __attribute__((format(printf, 3, 4)));
+void    freeargs(arglist *);
+
+int     tun_open(int, int);
+
+/* Common definitions for ssh tunnel device forwarding */
+#define SSH_TUNMODE_NO         0x00
+#define SSH_TUNMODE_POINTOPOINT        0x01
+#define SSH_TUNMODE_ETHERNET   0x02
+#define SSH_TUNMODE_DEFAULT    SSH_TUNMODE_POINTOPOINT
+#define SSH_TUNMODE_YES                (SSH_TUNMODE_POINTOPOINT|SSH_TUNMODE_ETHERNET)
+
+#define SSH_TUNID_ANY          0x7fffffff
+#define SSH_TUNID_ERR          (SSH_TUNID_ANY - 1)
+#define SSH_TUNID_MAX          (SSH_TUNID_ANY - 2)
+
+/* Functions to extract or store big-endian words of various sizes */
+u_int64_t      get_u64(const void *)
+    __attribute__((__bounded__( __minbytes__, 1, 8)));
+u_int32_t      get_u32(const void *)
+    __attribute__((__bounded__( __minbytes__, 1, 4)));
+u_int16_t      get_u16(const void *)
+    __attribute__((__bounded__( __minbytes__, 1, 2)));
+void           put_u64(void *, u_int64_t)
+    __attribute__((__bounded__( __minbytes__, 1, 8)));
+void           put_u32(void *, u_int32_t)
+    __attribute__((__bounded__( __minbytes__, 1, 4)));
+void           put_u16(void *, u_int16_t)
+    __attribute__((__bounded__( __minbytes__, 1, 2)));
+
+struct bwlimit {
+       size_t buflen;
+       u_int64_t rate, thresh, lamt;
+       struct timeval bwstart, bwend;
+};
+
+void bandwidth_limit_init(struct bwlimit *, u_int64_t, size_t);
+void bandwidth_limit(struct bwlimit *, size_t);
+
+int parse_ipqos(const char *);
+const char *iptos2str(int);
+void mktemp_proto(char *, size_t);
+
+/* readpass.c */
+
+#define RP_ECHO                        0x0001
+#define RP_ALLOW_STDIN         0x0002
+#define RP_ALLOW_EOF           0x0004
+#define RP_USE_ASKPASS         0x0008
+
+char   *read_passphrase(const char *, int);
+int     ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
+int     read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
+
+#endif /* _MISC_H */
diff --git a/.pc/user-group-modes.patch/readconf.c b/.pc/user-group-modes.patch/readconf.c
new file mode 100644 (file)
index 0000000..d1336ab
--- /dev/null
@@ -0,0 +1,1534 @@
+/* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
+/*
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Functions for reading the configuration files.
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "compat.h"
+#include "cipher.h"
+#include "pathnames.h"
+#include "log.h"
+#include "key.h"
+#include "readconf.h"
+#include "match.h"
+#include "misc.h"
+#include "buffer.h"
+#include "kex.h"
+#include "mac.h"
+
+/* Format of the configuration file:
+
+   # Configuration data is parsed as follows:
+   #  1. command line options
+   #  2. user-specific file
+   #  3. system-wide file
+   # Any configuration value is only changed the first time it is set.
+   # Thus, host-specific definitions should be at the beginning of the
+   # configuration file, and defaults at the end.
+
+   # Host-specific declarations.  These may override anything above.  A single
+   # host may match multiple declarations; these are processed in the order
+   # that they are given in.
+
+   Host *.ngs.fi ngs.fi
+     User foo
+
+   Host fake.com
+     HostName another.host.name.real.org
+     User blaah
+     Port 34289
+     ForwardX11 no
+     ForwardAgent no
+
+   Host books.com
+     RemoteForward 9999 shadows.cs.hut.fi:9999
+     Cipher 3des
+
+   Host fascist.blob.com
+     Port 23123
+     User tylonen
+     PasswordAuthentication no
+
+   Host puukko.hut.fi
+     User t35124p
+     ProxyCommand ssh-proxy %h %p
+
+   Host *.fr
+     PublicKeyAuthentication no
+
+   Host *.su
+     Cipher none
+     PasswordAuthentication no
+
+   Host vpn.fake.com
+     Tunnel yes
+     TunnelDevice 3
+
+   # Defaults for various options
+   Host *
+     ForwardAgent no
+     ForwardX11 no
+     PasswordAuthentication yes
+     RSAAuthentication yes
+     RhostsRSAAuthentication yes
+     StrictHostKeyChecking yes
+     TcpKeepAlive no
+     IdentityFile ~/.ssh/identity
+     Port 22
+     EscapeChar ~
+
+*/
+
+/* Keyword tokens. */
+
+typedef enum {
+       oBadOption,
+       oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
+       oGatewayPorts, oExitOnForwardFailure,
+       oPasswordAuthentication, oRSAAuthentication,
+       oChallengeResponseAuthentication, oXAuthLocation,
+       oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
+       oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+       oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
+       oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
+       oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
+       oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
+       oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
+       oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
+       oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
+       oUseBlacklistedKeys,
+       oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
+       oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+       oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
+       oGssServerIdentity, 
+       oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+       oSendEnv, oControlPath, oControlMaster, oControlPersist,
+       oHashKnownHosts,
+       oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
+       oKexAlgorithms, oIPQoS, oRequestTTY,
+       oProtocolKeepAlives, oSetupTimeOut,
+       oDeprecated, oUnsupported
+} OpCodes;
+
+/* Textual representations of the tokens. */
+
+static struct {
+       const char *name;
+       OpCodes opcode;
+} keywords[] = {
+       { "forwardagent", oForwardAgent },
+       { "forwardx11", oForwardX11 },
+       { "forwardx11trusted", oForwardX11Trusted },
+       { "forwardx11timeout", oForwardX11Timeout },
+       { "exitonforwardfailure", oExitOnForwardFailure },
+       { "xauthlocation", oXAuthLocation },
+       { "gatewayports", oGatewayPorts },
+       { "useprivilegedport", oUsePrivilegedPort },
+       { "rhostsauthentication", oDeprecated },
+       { "passwordauthentication", oPasswordAuthentication },
+       { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
+       { "kbdinteractivedevices", oKbdInteractiveDevices },
+       { "useblacklistedkeys", oUseBlacklistedKeys },
+       { "rsaauthentication", oRSAAuthentication },
+       { "pubkeyauthentication", oPubkeyAuthentication },
+       { "dsaauthentication", oPubkeyAuthentication },             /* alias */
+       { "rhostsrsaauthentication", oRhostsRSAAuthentication },
+       { "hostbasedauthentication", oHostbasedAuthentication },
+       { "challengeresponseauthentication", oChallengeResponseAuthentication },
+       { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
+       { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
+       { "kerberosauthentication", oUnsupported },
+       { "kerberostgtpassing", oUnsupported },
+       { "afstokenpassing", oUnsupported },
+#if defined(GSSAPI)
+       { "gssapiauthentication", oGssAuthentication },
+       { "gssapikeyexchange", oGssKeyEx },
+       { "gssapidelegatecredentials", oGssDelegateCreds },
+       { "gssapitrustdns", oGssTrustDns },
+       { "gssapiclientidentity", oGssClientIdentity },
+       { "gssapiserveridentity", oGssServerIdentity },
+       { "gssapirenewalforcesrekey", oGssRenewalRekey },
+#else
+       { "gssapiauthentication", oUnsupported },
+       { "gssapikeyexchange", oUnsupported },
+       { "gssapidelegatecredentials", oUnsupported },
+       { "gssapitrustdns", oUnsupported },
+       { "gssapiclientidentity", oUnsupported },
+       { "gssapirenewalforcesrekey", oUnsupported },
+#endif
+       { "fallbacktorsh", oDeprecated },
+       { "usersh", oDeprecated },
+       { "identityfile", oIdentityFile },
+       { "identityfile2", oIdentityFile },                     /* obsolete */
+       { "identitiesonly", oIdentitiesOnly },
+       { "hostname", oHostName },
+       { "hostkeyalias", oHostKeyAlias },
+       { "proxycommand", oProxyCommand },
+       { "port", oPort },
+       { "cipher", oCipher },
+       { "ciphers", oCiphers },
+       { "macs", oMacs },
+       { "protocol", oProtocol },
+       { "remoteforward", oRemoteForward },
+       { "localforward", oLocalForward },
+       { "user", oUser },
+       { "host", oHost },
+       { "escapechar", oEscapeChar },
+       { "globalknownhostsfile", oGlobalKnownHostsFile },
+       { "globalknownhostsfile2", oDeprecated },
+       { "userknownhostsfile", oUserKnownHostsFile },
+       { "userknownhostsfile2", oDeprecated }, 
+       { "connectionattempts", oConnectionAttempts },
+       { "batchmode", oBatchMode },
+       { "checkhostip", oCheckHostIP },
+       { "stricthostkeychecking", oStrictHostKeyChecking },
+       { "compression", oCompression },
+       { "compressionlevel", oCompressionLevel },
+       { "tcpkeepalive", oTCPKeepAlive },
+       { "keepalive", oTCPKeepAlive },                         /* obsolete */
+       { "numberofpasswordprompts", oNumberOfPasswordPrompts },
+       { "loglevel", oLogLevel },
+       { "dynamicforward", oDynamicForward },
+       { "preferredauthentications", oPreferredAuthentications },
+       { "hostkeyalgorithms", oHostKeyAlgorithms },
+       { "bindaddress", oBindAddress },
+#ifdef ENABLE_PKCS11
+       { "smartcarddevice", oPKCS11Provider },
+       { "pkcs11provider", oPKCS11Provider },
+#else
+       { "smartcarddevice", oUnsupported },
+       { "pkcs11provider", oUnsupported },
+#endif
+       { "clearallforwardings", oClearAllForwardings },
+       { "enablesshkeysign", oEnableSSHKeysign },
+       { "verifyhostkeydns", oVerifyHostKeyDNS },
+       { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
+       { "rekeylimit", oRekeyLimit },
+       { "connecttimeout", oConnectTimeout },
+       { "addressfamily", oAddressFamily },
+       { "serveraliveinterval", oServerAliveInterval },
+       { "serveralivecountmax", oServerAliveCountMax },
+       { "sendenv", oSendEnv },
+       { "controlpath", oControlPath },
+       { "controlmaster", oControlMaster },
+       { "controlpersist", oControlPersist },
+       { "hashknownhosts", oHashKnownHosts },
+       { "tunnel", oTunnel },
+       { "tunneldevice", oTunnelDevice },
+       { "localcommand", oLocalCommand },
+       { "permitlocalcommand", oPermitLocalCommand },
+       { "visualhostkey", oVisualHostKey },
+       { "useroaming", oUseRoaming },
+#ifdef JPAKE
+       { "zeroknowledgepasswordauthentication",
+           oZeroKnowledgePasswordAuthentication },
+#else
+       { "zeroknowledgepasswordauthentication", oUnsupported },
+#endif
+       { "kexalgorithms", oKexAlgorithms },
+       { "ipqos", oIPQoS },
+       { "requesttty", oRequestTTY },
+       { "protocolkeepalives", oProtocolKeepAlives },
+       { "setuptimeout", oSetupTimeOut },
+
+       { NULL, oBadOption }
+};
+
+/*
+ * Adds a local TCP/IP port forward to options.  Never returns if there is an
+ * error.
+ */
+
+void
+add_local_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+#ifndef NO_IPPORT_RESERVED_CONCEPT
+       extern uid_t original_real_uid;
+       if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
+               fatal("Privileged ports can only be forwarded by root.");
+#endif
+       options->local_forwards = xrealloc(options->local_forwards,
+           options->num_local_forwards + 1,
+           sizeof(*options->local_forwards));
+       fwd = &options->local_forwards[options->num_local_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+}
+
+/*
+ * Adds a remote TCP/IP port forward to options.  Never returns if there is
+ * an error.
+ */
+
+void
+add_remote_forward(Options *options, const Forward *newfwd)
+{
+       Forward *fwd;
+
+       options->remote_forwards = xrealloc(options->remote_forwards,
+           options->num_remote_forwards + 1,
+           sizeof(*options->remote_forwards));
+       fwd = &options->remote_forwards[options->num_remote_forwards++];
+
+       fwd->listen_host = newfwd->listen_host;
+       fwd->listen_port = newfwd->listen_port;
+       fwd->connect_host = newfwd->connect_host;
+       fwd->connect_port = newfwd->connect_port;
+       fwd->allocated_port = 0;
+}
+
+static void
+clear_forwardings(Options *options)
+{
+       int i;
+
+       for (i = 0; i < options->num_local_forwards; i++) {
+               if (options->local_forwards[i].listen_host != NULL)
+                       xfree(options->local_forwards[i].listen_host);
+               xfree(options->local_forwards[i].connect_host);
+       }
+       if (options->num_local_forwards > 0) {
+               xfree(options->local_forwards);
+               options->local_forwards = NULL;
+       }
+       options->num_local_forwards = 0;
+       for (i = 0; i < options->num_remote_forwards; i++) {
+               if (options->remote_forwards[i].listen_host != NULL)
+                       xfree(options->remote_forwards[i].listen_host);
+               xfree(options->remote_forwards[i].connect_host);
+       }
+       if (options->num_remote_forwards > 0) {
+               xfree(options->remote_forwards);
+               options->remote_forwards = NULL;
+       }
+       options->num_remote_forwards = 0;
+       options->tun_open = SSH_TUNMODE_NO;
+}
+
+/*
+ * Returns the number of the token pointed to by cp or oBadOption.
+ */
+
+static OpCodes
+parse_token(const char *cp, const char *filename, int linenum)
+{
+       u_int i;
+
+       for (i = 0; keywords[i].name; i++)
+               if (strcasecmp(cp, keywords[i].name) == 0)
+                       return keywords[i].opcode;
+
+       error("%s: line %d: Bad configuration option: %s",
+           filename, linenum, cp);
+       return oBadOption;
+}
+
+/*
+ * Processes a single option line as used in the configuration files. This
+ * only sets those values that have not already been set.
+ */
+#define WHITESPACE " \t\r\n"
+
+int
+process_config_line(Options *options, const char *host,
+                   char *line, const char *filename, int linenum,
+                   int *activep)
+{
+       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+       char **cpptr, fwdarg[256];
+       u_int *uintptr, max_entries = 0;
+       int negated, opcode, *intptr, value, value2, scale;
+       LogLevel *log_level_ptr;
+       long long orig, val64;
+       size_t len;
+       Forward fwd;
+
+       /* Strip trailing whitespace */
+       for (len = strlen(line) - 1; len > 0; len--) {
+               if (strchr(WHITESPACE, line[len]) == NULL)
+                       break;
+               line[len] = '\0';
+       }
+
+       s = line;
+       /* Get the keyword. (Each line is supposed to begin with a keyword). */
+       if ((keyword = strdelim(&s)) == NULL)
+               return 0;
+       /* Ignore leading whitespace. */
+       if (*keyword == '\0')
+               keyword = strdelim(&s);
+       if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
+               return 0;
+
+       opcode = parse_token(keyword, filename, linenum);
+
+       switch (opcode) {
+       case oBadOption:
+               /* don't panic, but count bad options */
+               return -1;
+               /* NOTREACHED */
+       case oConnectTimeout:
+               intptr = &options->connection_timeout;
+parse_time:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing time value.",
+                           filename, linenum);
+               if ((value = convtime(arg)) == -1)
+                       fatal("%s line %d: invalid time value.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardAgent:
+               intptr = &options->forward_agent;
+parse_flag:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else
+                       fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oForwardX11:
+               intptr = &options->forward_x11;
+               goto parse_flag;
+
+       case oForwardX11Trusted:
+               intptr = &options->forward_x11_trusted;
+               goto parse_flag;
+       
+       case oForwardX11Timeout:
+               intptr = &options->forward_x11_timeout;
+               goto parse_time;
+
+       case oGatewayPorts:
+               intptr = &options->gateway_ports;
+               goto parse_flag;
+
+       case oExitOnForwardFailure:
+               intptr = &options->exit_on_forward_failure;
+               goto parse_flag;
+
+       case oUsePrivilegedPort:
+               intptr = &options->use_privileged_port;
+               goto parse_flag;
+
+       case oPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+
+       case oZeroKnowledgePasswordAuthentication:
+               intptr = &options->zero_knowledge_password_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveAuthentication:
+               intptr = &options->kbd_interactive_authentication;
+               goto parse_flag;
+
+       case oKbdInteractiveDevices:
+               charptr = &options->kbd_interactive_devices;
+               goto parse_string;
+
+       case oPubkeyAuthentication:
+               intptr = &options->pubkey_authentication;
+               goto parse_flag;
+
+       case oRSAAuthentication:
+               intptr = &options->rsa_authentication;
+               goto parse_flag;
+
+       case oRhostsRSAAuthentication:
+               intptr = &options->rhosts_rsa_authentication;
+               goto parse_flag;
+
+       case oHostbasedAuthentication:
+               intptr = &options->hostbased_authentication;
+               goto parse_flag;
+
+       case oChallengeResponseAuthentication:
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
+
+       case oUseBlacklistedKeys:
+               intptr = &options->use_blacklisted_keys;
+               goto parse_flag;
+
+       case oGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+
+       case oGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
+       case oGssDelegateCreds:
+               intptr = &options->gss_deleg_creds;
+               goto parse_flag;
+
+       case oGssTrustDns:
+               intptr = &options->gss_trust_dns;
+               goto parse_flag;
+
+       case oGssClientIdentity:
+               charptr = &options->gss_client_identity;
+               goto parse_string;
+
+       case oGssServerIdentity:
+               charptr = &options->gss_server_identity;
+               goto parse_string;
+
+       case oGssRenewalRekey:
+               intptr = &options->gss_renewal_rekey;
+               goto parse_flag;
+
+       case oBatchMode:
+               intptr = &options->batch_mode;
+               goto parse_flag;
+
+       case oCheckHostIP:
+               intptr = &options->check_host_ip;
+               goto parse_flag;
+
+       case oVerifyHostKeyDNS:
+               intptr = &options->verify_host_key_dns;
+               goto parse_yesnoask;
+
+       case oStrictHostKeyChecking:
+               intptr = &options->strict_host_key_checking;
+parse_yesnoask:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing yes/no/ask argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "ask") == 0)
+                       value = 2;
+               else
+                       fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCompression:
+               intptr = &options->compression;
+               goto parse_flag;
+
+       case oTCPKeepAlive:
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
+
+       case oNoHostAuthenticationForLocalhost:
+               intptr = &options->no_host_authentication_for_localhost;
+               goto parse_flag;
+
+       case oNumberOfPasswordPrompts:
+               intptr = &options->number_of_password_prompts;
+               goto parse_int;
+
+       case oCompressionLevel:
+               intptr = &options->compression_level;
+               goto parse_int;
+
+       case oRekeyLimit:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               orig = val64 = strtoll(arg, &endofnumber, 10);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               switch (toupper(*endofnumber)) {
+               case '\0':
+                       scale = 1;
+                       break;
+               case 'K':
+                       scale = 1<<10;
+                       break;
+               case 'M':
+                       scale = 1<<20;
+                       break;
+               case 'G':
+                       scale = 1<<30;
+                       break;
+               default:
+                       fatal("%.200s line %d: Invalid RekeyLimit suffix",
+                           filename, linenum);
+               }
+               val64 *= scale;
+               /* detect integer wrap and too-large limits */
+               if ((val64 / scale) != orig || val64 > UINT_MAX)
+                       fatal("%.200s line %d: RekeyLimit too large",
+                           filename, linenum);
+               if (val64 < 16)
+                       fatal("%.200s line %d: RekeyLimit too small",
+                           filename, linenum);
+               if (*activep && options->rekey_limit == -1)
+                       options->rekey_limit = (u_int32_t)val64;
+               break;
+
+       case oIdentityFile:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (*activep) {
+                       intptr = &options->num_identity_files;
+                       if (*intptr >= SSH_MAX_IDENTITY_FILES)
+                               fatal("%.200s line %d: Too many identity files specified (max %d).",
+                                   filename, linenum, SSH_MAX_IDENTITY_FILES);
+                       charptr = &options->identity_files[*intptr];
+                       *charptr = xstrdup(arg);
+                       *intptr = *intptr + 1;
+               }
+               break;
+
+       case oXAuthLocation:
+               charptr=&options->xauth_location;
+               goto parse_string;
+
+       case oUser:
+               charptr = &options->user;
+parse_string:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
+       case oGlobalKnownHostsFile:
+               cpptr = (char **)&options->system_hostfiles;
+               uintptr = &options->num_system_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+parse_char_array:
+               if (*activep && *uintptr == 0) {
+                       while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                               if ((*uintptr) >= max_entries)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               cpptr[(*uintptr)++] = xstrdup(arg);
+                       }
+               }
+               return 0;
+
+       case oUserKnownHostsFile:
+               cpptr = (char **)&options->user_hostfiles;
+               uintptr = &options->num_user_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+               goto parse_char_array;
+
+       case oHostName:
+               charptr = &options->hostname;
+               goto parse_string;
+
+       case oHostKeyAlias:
+               charptr = &options->host_key_alias;
+               goto parse_string;
+
+       case oPreferredAuthentications:
+               charptr = &options->preferred_authentications;
+               goto parse_string;
+
+       case oBindAddress:
+               charptr = &options->bind_address;
+               goto parse_string;
+
+       case oPKCS11Provider:
+               charptr = &options->pkcs11_provider;
+               goto parse_string;
+
+       case oProxyCommand:
+               charptr = &options->proxy_command;
+parse_command:
+               if (s == NULL)
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               len = strspn(s, WHITESPACE "=");
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(s + len);
+               return 0;
+
+       case oPort:
+               intptr = &options->port;
+parse_int:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] < '0' || arg[0] > '9')
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+
+               /* Octal, decimal, or hex format? */
+               value = strtol(arg, &endofnumber, 0);
+               if (arg == endofnumber)
+                       fatal("%.200s line %d: Bad number.", filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oConnectionAttempts:
+               intptr = &options->connection_attempts;
+               goto parse_int;
+
+       case oCipher:
+               intptr = &options->cipher;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = cipher_number(arg);
+               if (value == -1)
+                       fatal("%.200s line %d: Bad cipher '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oCiphers:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!ciphers_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->ciphers == NULL)
+                       options->ciphers = xstrdup(arg);
+               break;
+
+       case oMacs:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!mac_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->macs == NULL)
+                       options->macs = xstrdup(arg);
+               break;
+
+       case oKexAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
+               if (!kex_names_valid(arg))
+                       fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->kex_algorithms == NULL)
+                       options->kex_algorithms = xstrdup(arg);
+               break;
+
+       case oHostKeyAlgorithms:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (!key_names_valid2(arg))
+                       fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && options->hostkeyalgorithms == NULL)
+                       options->hostkeyalgorithms = xstrdup(arg);
+               break;
+
+       case oProtocol:
+               intptr = &options->protocol;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = proto_spec(arg);
+               if (value == SSH_PROTO_UNKNOWN)
+                       fatal("%.200s line %d: Bad protocol spec '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *intptr == SSH_PROTO_UNKNOWN)
+                       *intptr = value;
+               break;
+
+       case oLogLevel:
+               log_level_ptr = &options->log_level;
+               arg = strdelim(&s);
+               value = log_level_number(arg);
+               if (value == SYSLOG_LEVEL_NOT_SET)
+                       fatal("%.200s line %d: unsupported log level '%s'",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
+                       *log_level_ptr = (LogLevel) value;
+               break;
+
+       case oLocalForward:
+       case oRemoteForward:
+       case oDynamicForward:
+               arg = strdelim(&s);
+               if (arg == NULL || *arg == '\0')
+                       fatal("%.200s line %d: Missing port argument.",
+                           filename, linenum);
+
+               if (opcode == oLocalForward ||
+                   opcode == oRemoteForward) {
+                       arg2 = strdelim(&s);
+                       if (arg2 == NULL || *arg2 == '\0')
+                               fatal("%.200s line %d: Missing target argument.",
+                                   filename, linenum);
+
+                       /* construct a string for parse_forward */
+                       snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
+               } else if (opcode == oDynamicForward) {
+                       strlcpy(fwdarg, arg, sizeof(fwdarg));
+               }
+
+               if (parse_forward(&fwd, fwdarg,
+                   opcode == oDynamicForward ? 1 : 0,
+                   opcode == oRemoteForward ? 1 : 0) == 0)
+                       fatal("%.200s line %d: Bad forwarding specification.",
+                           filename, linenum);
+
+               if (*activep) {
+                       if (opcode == oLocalForward ||
+                           opcode == oDynamicForward)
+                               add_local_forward(options, &fwd);
+                       else if (opcode == oRemoteForward)
+                               add_remote_forward(options, &fwd);
+               }
+               break;
+
+       case oClearAllForwardings:
+               intptr = &options->clear_forwardings;
+               goto parse_flag;
+
+       case oHost:
+               *activep = 0;
+               arg2 = NULL;
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       negated = *arg == '!';
+                       if (negated)
+                               arg++;
+                       if (match_pattern(host, arg)) {
+                               if (negated) {
+                                       debug("%.200s line %d: Skipping Host "
+                                           "block because of negated match "
+                                           "for %.100s", filename, linenum,
+                                           arg);
+                                       *activep = 0;
+                                       break;
+                               }
+                               if (!*activep)
+                                       arg2 = arg; /* logged below */
+                               *activep = 1;
+                       }
+               }
+               if (*activep)
+                       debug("%.200s line %d: Applying options for %.100s",
+                           filename, linenum, arg2);
+               /* Avoid garbage check below, as strdelim is done. */
+               return 0;
+
+       case oEscapeChar:
+               intptr = &options->escape_char;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (arg[0] == '^' && arg[2] == 0 &&
+                   (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
+                       value = (u_char) arg[1] & 31;
+               else if (strlen(arg) == 1)
+                       value = (u_char) arg[0];
+               else if (strcmp(arg, "none") == 0)
+                       value = SSH_ESCAPECHAR_NONE;
+               else {
+                       fatal("%.200s line %d: Bad escape character.",
+                           filename, linenum);
+                       /* NOTREACHED */
+                       value = 0;      /* Avoid compiler warning. */
+               }
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oAddressFamily:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing address family.",
+                           filename, linenum);
+               intptr = &options->address_family;
+               if (strcasecmp(arg, "inet") == 0)
+                       value = AF_INET;
+               else if (strcasecmp(arg, "inet6") == 0)
+                       value = AF_INET6;
+               else if (strcasecmp(arg, "any") == 0)
+                       value = AF_UNSPEC;
+               else
+                       fatal("Unsupported AddressFamily \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oEnableSSHKeysign:
+               intptr = &options->enable_ssh_keysign;
+               goto parse_flag;
+
+       case oIdentitiesOnly:
+               intptr = &options->identities_only;
+               goto parse_flag;
+
+       case oServerAliveInterval:
+       case oProtocolKeepAlives: /* Debian-specific compatibility alias */
+       case oSetupTimeOut:       /* Debian-specific compatibility alias */
+               intptr = &options->server_alive_interval;
+               goto parse_time;
+
+       case oServerAliveCountMax:
+               intptr = &options->server_alive_count_max;
+               goto parse_int;
+
+       case oSendEnv:
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       if (strchr(arg, '=') != NULL)
+                               fatal("%s line %d: Invalid environment name.",
+                                   filename, linenum);
+                       if (!*activep)
+                               continue;
+                       if (options->num_send_env >= MAX_SEND_ENV)
+                               fatal("%s line %d: too many send env.",
+                                   filename, linenum);
+                       options->send_env[options->num_send_env++] =
+                           xstrdup(arg);
+               }
+               break;
+
+       case oControlPath:
+               charptr = &options->control_path;
+               goto parse_string;
+
+       case oControlMaster:
+               intptr = &options->control_master;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlMaster argument.",
+                           filename, linenum);
+               value = 0;      /* To avoid compiler warning... */
+               if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = SSHCTL_MASTER_YES;
+               else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = SSHCTL_MASTER_NO;
+               else if (strcmp(arg, "auto") == 0)
+                       value = SSHCTL_MASTER_AUTO;
+               else if (strcmp(arg, "ask") == 0)
+                       value = SSHCTL_MASTER_ASK;
+               else if (strcmp(arg, "autoask") == 0)
+                       value = SSHCTL_MASTER_AUTO_ASK;
+               else
+                       fatal("%.200s line %d: Bad ControlMaster argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oControlPersist:
+               /* no/false/yes/true, or a time spec */
+               intptr = &options->control_persist;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing ControlPersist"
+                           " argument.", filename, linenum);
+               value = 0;
+               value2 = 0;     /* timeout */
+               if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
+                       value = 0;
+               else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
+                       value = 1;
+               else if ((value2 = convtime(arg)) >= 0)
+                       value = 1;
+               else
+                       fatal("%.200s line %d: Bad ControlPersist argument.",
+                           filename, linenum);
+               if (*activep && *intptr == -1) {
+                       *intptr = value;
+                       options->control_persist_timeout = value2;
+               }
+               break;
+
+       case oHashKnownHosts:
+               intptr = &options->hash_known_hosts;
+               goto parse_flag;
+
+       case oTunnel:
+               intptr = &options->tun_open;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing yes/point-to-point/"
+                           "ethernet/no argument.", filename, linenum);
+               value = 0;      /* silence compiler */
+               if (strcasecmp(arg, "ethernet") == 0)
+                       value = SSH_TUNMODE_ETHERNET;
+               else if (strcasecmp(arg, "point-to-point") == 0)
+                       value = SSH_TUNMODE_POINTOPOINT;
+               else if (strcasecmp(arg, "yes") == 0)
+                       value = SSH_TUNMODE_DEFAULT;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = SSH_TUNMODE_NO;
+               else
+                       fatal("%s line %d: Bad yes/point-to-point/ethernet/"
+                           "no argument: %s", filename, linenum, arg);
+               if (*activep)
+                       *intptr = value;
+               break;
+
+       case oTunnelDevice:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               value = a2tun(arg, &value2);
+               if (value == SSH_TUNID_ERR)
+                       fatal("%.200s line %d: Bad tun device.", filename, linenum);
+               if (*activep) {
+                       options->tun_local = value;
+                       options->tun_remote = value2;
+               }
+               break;
+
+       case oLocalCommand:
+               charptr = &options->local_command;
+               goto parse_command;
+
+       case oPermitLocalCommand:
+               intptr = &options->permit_local_command;
+               goto parse_flag;
+
+       case oVisualHostKey:
+               intptr = &options->visual_host_key;
+               goto parse_flag;
+
+       case oIPQoS:
+               arg = strdelim(&s);
+               if ((value = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               arg = strdelim(&s);
+               if (arg == NULL)
+                       value2 = value;
+               else if ((value2 = parse_ipqos(arg)) == -1)
+                       fatal("%s line %d: Bad IPQoS value: %s",
+                           filename, linenum, arg);
+               if (*activep) {
+                       options->ip_qos_interactive = value;
+                       options->ip_qos_bulk = value2;
+               }
+               break;
+
+       case oUseRoaming:
+               intptr = &options->use_roaming;
+               goto parse_flag;
+
+       case oRequestTTY:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               intptr = &options->request_tty;
+               if (strcasecmp(arg, "yes") == 0)
+                       value = REQUEST_TTY_YES;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = REQUEST_TTY_NO;
+               else if (strcasecmp(arg, "force") == 0)
+                       value = REQUEST_TTY_FORCE;
+               else if (strcasecmp(arg, "auto") == 0)
+                       value = REQUEST_TTY_AUTO;
+               else
+                       fatal("Unsupported RequestTTY \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
+       case oDeprecated:
+               debug("%s line %d: Deprecated option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       case oUnsupported:
+               error("%s line %d: Unsupported option \"%s\"",
+                   filename, linenum, keyword);
+               return 0;
+
+       default:
+               fatal("process_config_line: Unimplemented opcode %d", opcode);
+       }
+
+       /* Check that there is no garbage at end of line. */
+       if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+               fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
+                   filename, linenum, arg);
+       }
+       return 0;
+}
+
+
+/*
+ * Reads the config file and modifies the options accordingly.  Options
+ * should already be initialized before this call.  This never returns if
+ * there is an error.  If the file does not exist, this returns 0.
+ */
+
+int
+read_config_file(const char *filename, const char *host, Options *options,
+    int checkperm)
+{
+       FILE *f;
+       char line[1024];
+       int active, linenum;
+       int bad_options = 0;
+
+       if ((f = fopen(filename, "r")) == NULL)
+               return 0;
+
+       if (checkperm) {
+               struct stat sb;
+
+               if (fstat(fileno(f), &sb) == -1)
+                       fatal("fstat %s: %s", filename, strerror(errno));
+               if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
+                   (sb.st_mode & 022) != 0))
+                       fatal("Bad owner or permissions on %s", filename);
+       }
+
+       debug("Reading configuration data %.200s", filename);
+
+       /*
+        * Mark that we are now processing the options.  This flag is turned
+        * on/off by Host specifications.
+        */
+       active = 1;
+       linenum = 0;
+       while (fgets(line, sizeof(line), f)) {
+               /* Update line number counter. */
+               linenum++;
+               if (process_config_line(options, host, line, filename, linenum, &active) != 0)
+                       bad_options++;
+       }
+       fclose(f);
+       if (bad_options > 0)
+               fatal("%s: terminating, %d bad configuration options",
+                   filename, bad_options);
+       return 1;
+}
+
+/*
+ * Initializes options to special values that indicate that they have not yet
+ * been set.  Read_config_file will only set options with this value. Options
+ * are processed in the following order: command line, user config file,
+ * system config file.  Last, fill_default_options is called.
+ */
+
+void
+initialize_options(Options * options)
+{
+       memset(options, 'X', sizeof(*options));
+       options->forward_agent = -1;
+       options->forward_x11 = -1;
+       options->forward_x11_trusted = -1;
+       options->forward_x11_timeout = -1;
+       options->exit_on_forward_failure = -1;
+       options->xauth_location = NULL;
+       options->gateway_ports = -1;
+       options->use_privileged_port = -1;
+       options->rsa_authentication = -1;
+       options->pubkey_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->gss_authentication = -1;
+       options->gss_keyex = -1;
+       options->gss_deleg_creds = -1;
+       options->gss_trust_dns = -1;
+       options->gss_renewal_rekey = -1;
+       options->gss_client_identity = NULL;
+       options->gss_server_identity = NULL;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->kbd_interactive_devices = NULL;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
+       options->use_blacklisted_keys = -1;
+       options->batch_mode = -1;
+       options->check_host_ip = -1;
+       options->strict_host_key_checking = -1;
+       options->compression = -1;
+       options->tcp_keep_alive = -1;
+       options->compression_level = -1;
+       options->port = -1;
+       options->address_family = -1;
+       options->connection_attempts = -1;
+       options->connection_timeout = -1;
+       options->number_of_password_prompts = -1;
+       options->cipher = -1;
+       options->ciphers = NULL;
+       options->macs = NULL;
+       options->kex_algorithms = NULL;
+       options->hostkeyalgorithms = NULL;
+       options->protocol = SSH_PROTO_UNKNOWN;
+       options->num_identity_files = 0;
+       options->hostname = NULL;
+       options->host_key_alias = NULL;
+       options->proxy_command = NULL;
+       options->user = NULL;
+       options->escape_char = -1;
+       options->num_system_hostfiles = 0;
+       options->num_user_hostfiles = 0;
+       options->local_forwards = NULL;
+       options->num_local_forwards = 0;
+       options->remote_forwards = NULL;
+       options->num_remote_forwards = 0;
+       options->clear_forwardings = -1;
+       options->log_level = SYSLOG_LEVEL_NOT_SET;
+       options->preferred_authentications = NULL;
+       options->bind_address = NULL;
+       options->pkcs11_provider = NULL;
+       options->enable_ssh_keysign = - 1;
+       options->no_host_authentication_for_localhost = - 1;
+       options->identities_only = - 1;
+       options->rekey_limit = - 1;
+       options->verify_host_key_dns = -1;
+       options->server_alive_interval = -1;
+       options->server_alive_count_max = -1;
+       options->num_send_env = 0;
+       options->control_path = NULL;
+       options->control_master = -1;
+       options->control_persist = -1;
+       options->control_persist_timeout = 0;
+       options->hash_known_hosts = -1;
+       options->tun_open = -1;
+       options->tun_local = -1;
+       options->tun_remote = -1;
+       options->local_command = NULL;
+       options->permit_local_command = -1;
+       options->use_roaming = -1;
+       options->visual_host_key = -1;
+       options->zero_knowledge_password_authentication = -1;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
+       options->request_tty = -1;
+}
+
+/*
+ * Called after processing other sources of option data, this fills those
+ * options for which no value has been specified with their default values.
+ */
+
+void
+fill_default_options(Options * options)
+{
+       int len;
+
+       if (options->forward_agent == -1)
+               options->forward_agent = 0;
+       if (options->forward_x11 == -1)
+               options->forward_x11 = 0;
+       if (options->forward_x11_trusted == -1)
+               options->forward_x11_trusted = 0;
+       if (options->forward_x11_timeout == -1)
+               options->forward_x11_timeout = 1200;
+       if (options->exit_on_forward_failure == -1)
+               options->exit_on_forward_failure = 0;
+       if (options->xauth_location == NULL)
+               options->xauth_location = _PATH_XAUTH;
+       if (options->gateway_ports == -1)
+               options->gateway_ports = 0;
+       if (options->use_privileged_port == -1)
+               options->use_privileged_port = 0;
+       if (options->rsa_authentication == -1)
+               options->rsa_authentication = 1;
+       if (options->pubkey_authentication == -1)
+               options->pubkey_authentication = 1;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
+       if (options->gss_deleg_creds == -1)
+               options->gss_deleg_creds = 0;
+       if (options->gss_trust_dns == -1)
+               options->gss_trust_dns = 0;
+       if (options->gss_renewal_rekey == -1)
+               options->gss_renewal_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+               options->kbd_interactive_authentication = 1;
+       if (options->rhosts_rsa_authentication == -1)
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
+       if (options->use_blacklisted_keys == -1)
+               options->use_blacklisted_keys = 0;
+       if (options->batch_mode == -1)
+               options->batch_mode = 0;
+       if (options->check_host_ip == -1)
+               options->check_host_ip = 1;
+       if (options->strict_host_key_checking == -1)
+               options->strict_host_key_checking = 2;  /* 2 is default */
+       if (options->compression == -1)
+               options->compression = 0;
+       if (options->tcp_keep_alive == -1)
+               options->tcp_keep_alive = 1;
+       if (options->compression_level == -1)
+               options->compression_level = 6;
+       if (options->port == -1)
+               options->port = 0;      /* Filled in ssh_connect. */
+       if (options->address_family == -1)
+               options->address_family = AF_UNSPEC;
+       if (options->connection_attempts == -1)
+               options->connection_attempts = 1;
+       if (options->number_of_password_prompts == -1)
+               options->number_of_password_prompts = 3;
+       /* Selected in ssh_login(). */
+       if (options->cipher == -1)
+               options->cipher = SSH_CIPHER_NOT_SET;
+       /* options->ciphers, default set in myproposals.h */
+       /* options->macs, default set in myproposals.h */
+       /* options->kex_algorithms, default set in myproposals.h */
+       /* options->hostkeyalgorithms, default set in myproposals.h */
+       if (options->protocol == SSH_PROTO_UNKNOWN)
+               options->protocol = SSH_PROTO_2;
+       if (options->num_identity_files == 0) {
+               if (options->protocol & SSH_PROTO_1) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
+               }
+               if (options->protocol & SSH_PROTO_2) {
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
+
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
+#ifdef OPENSSL_HAS_ECC
+                       len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
+                       options->identity_files[options->num_identity_files] =
+                           xmalloc(len);
+                       snprintf(options->identity_files[options->num_identity_files++],
+                           len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
+#endif
+               }
+       }
+       if (options->escape_char == -1)
+               options->escape_char = '~';
+       if (options->num_system_hostfiles == 0) {
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
+       }
+       if (options->num_user_hostfiles == 0) {
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE);
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE2);
+       }
+       if (options->log_level == SYSLOG_LEVEL_NOT_SET)
+               options->log_level = SYSLOG_LEVEL_INFO;
+       if (options->clear_forwardings == 1)
+               clear_forwardings(options);
+       if (options->no_host_authentication_for_localhost == - 1)
+               options->no_host_authentication_for_localhost = 0;
+       if (options->identities_only == -1)
+               options->identities_only = 0;
+       if (options->enable_ssh_keysign == -1)
+               options->enable_ssh_keysign = 0;
+       if (options->rekey_limit == -1)
+               options->rekey_limit = 0;
+       if (options->verify_host_key_dns == -1)
+               options->verify_host_key_dns = 0;
+       if (options->server_alive_interval == -1) {
+               /* in batch mode, default is 5mins */
+               if (options->batch_mode == 1)
+                       options->server_alive_interval = 300;
+               else
+                       options->server_alive_interval = 0;
+       }
+       if (options->server_alive_count_max == -1)
+               options->server_alive_count_max = 3;
+       if (options->control_master == -1)
+               options->control_master = 0;
+       if (options->control_persist == -1) {
+               options->control_persist = 0;
+               options->control_persist_timeout = 0;
+       }
+       if (options->hash_known_hosts == -1)
+               options->hash_known_hosts = 0;
+       if (options->tun_open == -1)
+               options->tun_open = SSH_TUNMODE_NO;
+       if (options->tun_local == -1)
+               options->tun_local = SSH_TUNID_ANY;
+       if (options->tun_remote == -1)
+               options->tun_remote = SSH_TUNID_ANY;
+       if (options->permit_local_command == -1)
+               options->permit_local_command = 0;
+       if (options->use_roaming == -1)
+               options->use_roaming = 1;
+       if (options->visual_host_key == -1)
+               options->visual_host_key = 0;
+       if (options->zero_knowledge_password_authentication == -1)
+               options->zero_knowledge_password_authentication = 0;
+       if (options->ip_qos_interactive == -1)
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
+       if (options->request_tty == -1)
+               options->request_tty = REQUEST_TTY_AUTO;
+       /* options->local_command should not be set by default */
+       /* options->proxy_command should not be set by default */
+       /* options->user will be set in the main program if appropriate */
+       /* options->hostname will be set in the main program if appropriate */
+       /* options->host_key_alias should not be set by default */
+       /* options->preferred_authentications will be set in ssh */
+}
+
+/*
+ * parse_forward
+ * parses a string containing a port forwarding specification of the form:
+ *   dynamicfwd == 0
+ *     [listenhost:]listenport:connecthost:connectport
+ *   dynamicfwd == 1
+ *     [listenhost:]listenport
+ * returns number of arguments parsed or zero on error
+ */
+int
+parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
+{
+       int i;
+       char *p, *cp, *fwdarg[4];
+
+       memset(fwd, '\0', sizeof(*fwd));
+
+       cp = p = xstrdup(fwdspec);
+
+       /* skip leading spaces */
+       while (isspace(*cp))
+               cp++;
+
+       for (i = 0; i < 4; ++i)
+               if ((fwdarg[i] = hpdelim(&cp)) == NULL)
+                       break;
+
+       /* Check for trailing garbage */
+       if (cp != NULL)
+               i = 0;  /* failure */
+
+       switch (i) {
+       case 1:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 2:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup("socks");
+               break;
+
+       case 3:
+               fwd->listen_host = NULL;
+               fwd->listen_port = a2port(fwdarg[0]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
+               fwd->connect_port = a2port(fwdarg[2]);
+               break;
+
+       case 4:
+               fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
+               fwd->listen_port = a2port(fwdarg[1]);
+               fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
+               fwd->connect_port = a2port(fwdarg[3]);
+               break;
+       default:
+               i = 0; /* failure */
+       }
+
+       xfree(p);
+
+       if (dynamicfwd) {
+               if (!(i == 1 || i == 2))
+                       goto fail_free;
+       } else {
+               if (!(i == 3 || i == 4))
+                       goto fail_free;
+               if (fwd->connect_port <= 0)
+                       goto fail_free;
+       }
+
+       if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
+               goto fail_free;
+
+       if (fwd->connect_host != NULL &&
+           strlen(fwd->connect_host) >= NI_MAXHOST)
+               goto fail_free;
+       if (fwd->listen_host != NULL &&
+           strlen(fwd->listen_host) >= NI_MAXHOST)
+               goto fail_free;
+
+
+       return (i);
+
+ fail_free:
+       if (fwd->connect_host != NULL) {
+               xfree(fwd->connect_host);
+               fwd->connect_host = NULL;
+       }
+       if (fwd->listen_host != NULL) {
+               xfree(fwd->listen_host);
+               fwd->listen_host = NULL;
+       }
+       return (0);
+}
diff --git a/.pc/user-group-modes.patch/ssh.1 b/.pc/user-group-modes.patch/ssh.1
new file mode 100644 (file)
index 0000000..2043acc
--- /dev/null
@@ -0,0 +1,1496 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh.1,v 1.320 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH 1
+.Os
+.Sh NAME
+.Nm ssh
+.Nd OpenSSH SSH client (remote login program)
+.Sh SYNOPSIS
+.Nm ssh
+.Bk -words
+.Op Fl 1246AaCfgKkMNnqsTtVvXxYy
+.Op Fl b Ar bind_address
+.Op Fl c Ar cipher_spec
+.Op Fl D Oo Ar bind_address : Oc Ns Ar port
+.Op Fl e Ar escape_char
+.Op Fl F Ar configfile
+.Op Fl I Ar pkcs11
+.Op Fl i Ar identity_file
+.Op Fl L Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl l Ar login_name
+.Op Fl m Ar mac_spec
+.Op Fl O Ar ctl_cmd
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Op Fl R Oo Ar bind_address : Oc Ns Ar port : Ns Ar host : Ns Ar hostport
+.Op Fl S Ar ctl_path
+.Op Fl W Ar host : Ns Ar port
+.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
+.Oo Ar user Ns @ Oc Ns Ar hostname
+.Op Ar command
+.Ek
+.Sh DESCRIPTION
+.Nm
+(SSH client) is a program for logging into a remote machine and for
+executing commands on a remote machine.
+It is intended to replace rlogin and rsh,
+and provide secure encrypted communications between
+two untrusted hosts over an insecure network.
+X11 connections and arbitrary TCP ports
+can also be forwarded over the secure channel.
+.Pp
+.Nm
+connects and logs into the specified
+.Ar hostname
+(with optional
+.Ar user
+name).
+The user must prove
+his/her identity to the remote machine using one of several methods
+depending on the protocol version used (see below).
+.Pp
+If
+.Ar command
+is specified,
+it is executed on the remote host instead of a login shell.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl 1
+Forces
+.Nm
+to try protocol version 1 only.
+.It Fl 2
+Forces
+.Nm
+to try protocol version 2 only.
+.It Fl 4
+Forces
+.Nm
+to use IPv4 addresses only.
+.It Fl 6
+Forces
+.Nm
+to use IPv6 addresses only.
+.It Fl A
+Enables forwarding of the authentication agent connection.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's
+.Ux Ns -domain
+socket) can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Fl a
+Disables forwarding of the authentication agent connection.
+.It Fl b Ar bind_address
+Use
+.Ar bind_address
+on the local machine as the source address
+of the connection.
+Only useful on systems with more than one address.
+.It Fl C
+Requests compression of all data (including stdin, stdout, stderr, and
+data for forwarded X11 and TCP connections).
+The compression algorithm is the same used by
+.Xr gzip 1 ,
+and the
+.Dq level
+can be controlled by the
+.Cm CompressionLevel
+option for protocol version 1.
+Compression is desirable on modem lines and other
+slow connections, but will only slow down things on fast networks.
+The default value can be set on a host-by-host basis in the
+configuration files; see the
+.Cm Compression
+option.
+.It Fl c Ar cipher_spec
+Selects the cipher specification for encrypting the session.
+.Pp
+Protocol version 1 allows specification of a single cipher.
+The supported values are
+.Dq 3des ,
+.Dq blowfish ,
+and
+.Dq des .
+.Ar 3des
+(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
+It is believed to be secure.
+.Ar blowfish
+is a fast block cipher; it appears very secure and is much faster than
+.Ar 3des .
+.Ar des
+is only supported in the
+.Nm
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.Pp
+For protocol version 2,
+.Ar cipher_spec
+is a comma-separated list of ciphers
+listed in order of preference.
+See the
+.Cm Ciphers
+keyword in
+.Xr ssh_config 5
+for more information.
+.It Fl D Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port
+.Sm on
+.Xc
+Specifies a local
+.Dq dynamic
+application-level port forwarding.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Nm
+will act as a SOCKS server.
+Only root can forward privileged ports.
+Dynamic port forwardings can also be specified in the configuration file.
+.Pp
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl e Ar escape_char
+Sets the escape character for sessions with a pty (default:
+.Ql ~ ) .
+The escape character is only recognized at the beginning of a line.
+The escape character followed by a dot
+.Pq Ql \&.
+closes the connection;
+followed by control-Z suspends the connection;
+and followed by itself sends the escape character once.
+Setting the character to
+.Dq none
+disables any escapes and makes the session fully transparent.
+.It Fl F Ar configfile
+Specifies an alternative per-user configuration file.
+If a configuration file is given on the command line,
+the system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+will be ignored.
+The default for the per-user configuration file is
+.Pa ~/.ssh/config .
+.It Fl f
+Requests
+.Nm
+to go to background just before command execution.
+This is useful if
+.Nm
+is going to ask for passwords or passphrases, but the user
+wants it in the background.
+This implies
+.Fl n .
+The recommended way to start X11 programs at a remote site is with
+something like
+.Ic ssh -f host xterm .
+.Pp
+If the
+.Cm ExitOnForwardFailure
+configuration option is set to
+.Dq yes ,
+then a client started with
+.Fl f
+will wait for all remote port forwards to be successfully established
+before placing itself in the background.
+.It Fl g
+Allows remote hosts to connect to local forwarded ports.
+.It Fl I Ar pkcs11
+Specify the PKCS#11 shared library
+.Nm
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Fl i Ar identity_file
+Selects a file from which the identity (private key) for
+public key authentication is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Identity files may also be specified on
+a per-host basis in the configuration file.
+It is possible to have multiple
+.Fl i
+options (and multiple identities specified in
+configuration files).
+.Nm
+will also try to load certificate information from the filename obtained
+by appending
+.Pa -cert.pub
+to identity filenames.
+.It Fl K
+Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI
+credentials to the server.
+.It Fl k
+Disables forwarding (delegation) of GSSAPI credentials to the server.
+.It Fl L Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the local (client) host is to be
+forwarded to the given host and port on the remote side.
+This works by allocating a socket to listen to
+.Ar port
+on the local side, optionally bound to the specified
+.Ar bind_address .
+Whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the remote machine.
+Port forwardings can also be specified in the configuration file.
+IPv6 addresses can be specified by enclosing the address in square brackets.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Fl l Ar login_name
+Specifies the user to log in as on the remote machine.
+This also may be specified on a per-host basis in the configuration file.
+.It Fl M
+Places the
+.Nm
+client into
+.Dq master
+mode for connection sharing.
+Multiple
+.Fl M
+options places
+.Nm
+into
+.Dq master
+mode with confirmation required before slave connections are accepted.
+Refer to the description of
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl m Ar mac_spec
+Additionally, for protocol version 2 a comma-separated list of MAC
+(message authentication code) algorithms can
+be specified in order of preference.
+See the
+.Cm MACs
+keyword for more information.
+.It Fl N
+Do not execute a remote command.
+This is useful for just forwarding ports
+(protocol version 2 only).
+.It Fl n
+Redirects stdin from
+.Pa /dev/null
+(actually, prevents reading from stdin).
+This must be used when
+.Nm
+is run in the background.
+A common trick is to use this to run X11 programs on a remote machine.
+For example,
+.Ic ssh -n shadows.cs.hut.fi emacs &
+will start an emacs on shadows.cs.hut.fi, and the X11
+connection will be automatically forwarded over an encrypted channel.
+The
+.Nm
+program will be put in the background.
+(This does not work if
+.Nm
+needs to ask for a password or passphrase; see also the
+.Fl f
+option.)
+.It Fl O Ar ctl_cmd
+Control an active connection multiplexing master process.
+When the
+.Fl O
+option is specified, the
+.Ar ctl_cmd
+argument is interpreted and passed to the master process.
+Valid commands are:
+.Dq check
+(check that the master process is running),
+.Dq forward
+(request forwardings without command execution),
+.Dq exit
+(request the master to exit), and
+.Dq stop
+(request the master to stop accepting further multiplexing requests).
+.It Fl o Ar option
+Can be used to give options in the format used in the configuration file.
+This is useful for specifying options for which there is no separate
+command-line flag.
+For full details of the options listed below, and their possible values, see
+.Xr ssh_config 5 .
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It AddressFamily
+.It BatchMode
+.It BindAddress
+.It ChallengeResponseAuthentication
+.It CheckHostIP
+.It Cipher
+.It Ciphers
+.It ClearAllForwardings
+.It Compression
+.It CompressionLevel
+.It ConnectionAttempts
+.It ConnectTimeout
+.It ControlMaster
+.It ControlPath
+.It DynamicForward
+.It EscapeChar
+.It ExitOnForwardFailure
+.It ForwardAgent
+.It ForwardX11
+.It ForwardX11Trusted
+.It GatewayPorts
+.It GlobalKnownHostsFile
+.It GSSAPIAuthentication
+.It GSSAPIDelegateCredentials
+.It HashKnownHosts
+.It Host
+.It HostbasedAuthentication
+.It HostKeyAlgorithms
+.It HostKeyAlias
+.It HostName
+.It IdentityFile
+.It IdentitiesOnly
+.It IPQoS
+.It KbdInteractiveDevices
+.It KexAlgorithms
+.It LocalCommand
+.It LocalForward
+.It LogLevel
+.It MACs
+.It NoHostAuthenticationForLocalhost
+.It NumberOfPasswordPrompts
+.It PasswordAuthentication
+.It PermitLocalCommand
+.It PKCS11Provider
+.It Port
+.It PreferredAuthentications
+.It Protocol
+.It ProxyCommand
+.It PubkeyAuthentication
+.It RekeyLimit
+.It RemoteForward
+.It RequestTTY
+.It RhostsRSAAuthentication
+.It RSAAuthentication
+.It SendEnv
+.It ServerAliveInterval
+.It ServerAliveCountMax
+.It StrictHostKeyChecking
+.It TCPKeepAlive
+.It Tunnel
+.It TunnelDevice
+.It UsePrivilegedPort
+.It User
+.It UserKnownHostsFile
+.It VerifyHostKeyDNS
+.It VisualHostKey
+.It XAuthLocation
+.El
+.It Fl p Ar port
+Port to connect to on the remote host.
+This can be specified on a
+per-host basis in the configuration file.
+.It Fl q
+Quiet mode.
+Causes most warning and diagnostic messages to be suppressed.
+.It Fl R Xo
+.Sm off
+.Oo Ar bind_address : Oc
+.Ar port : host : hostport
+.Sm on
+.Xc
+Specifies that the given port on the remote (server) host is to be
+forwarded to the given host and port on the local side.
+This works by allocating a socket to listen to
+.Ar port
+on the remote side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.Ar host
+port
+.Ar hostport
+from the local machine.
+.Pp
+Port forwardings can also be specified in the configuration file.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+IPv6 addresses can be specified by enclosing the address in square braces.
+.Pp
+By default, the listening socket on the server will be bound to the loopback
+interface only.
+This may be overridden by specifying a
+.Ar bind_address .
+An empty
+.Ar bind_address ,
+or the address
+.Ql * ,
+indicates that the remote socket should listen on all interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+When used together with
+.Ic -O forward
+the allocated port will be printed to the standard output.
+.It Fl S Ar ctl_path
+Specifies the location of a control socket for connection sharing,
+or the string
+.Dq none
+to disable connection sharing.
+Refer to the description of
+.Cm ControlPath
+and
+.Cm ControlMaster
+in
+.Xr ssh_config 5
+for details.
+.It Fl s
+May be used to request invocation of a subsystem on the remote system.
+Subsystems are a feature of the SSH2 protocol which facilitate the use
+of SSH as a secure transport for other applications (eg.\&
+.Xr sftp 1 ) .
+The subsystem is specified as the remote command.
+.It Fl T
+Disable pseudo-tty allocation.
+.It Fl t
+Force pseudo-tty allocation.
+This can be used to execute arbitrary
+screen-based programs on a remote machine, which can be very useful,
+e.g. when implementing menu services.
+Multiple
+.Fl t
+options force tty allocation, even if
+.Nm
+has no local tty.
+.It Fl V
+Display the version number and exit.
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in
+debugging connection, authentication, and configuration problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.It Fl W Ar host : Ns Ar port
+Requests that standard input and output on the client be forwarded to
+.Ar host
+on
+.Ar port
+over the secure channel.
+Implies
+.Fl N ,
+.Fl T ,
+.Cm ExitOnForwardFailure
+and
+.Cm ClearAllForwardings
+and works with Protocol version 2 only.
+.It Fl w Xo
+.Ar local_tun Ns Op : Ns Ar remote_tun
+.Xc
+Requests
+tunnel
+device forwarding with the specified
+.Xr tun 4
+devices between the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+See also the
+.Cm Tunnel
+and
+.Cm TunnelDevice
+directives in
+.Xr ssh_config 5 .
+If the
+.Cm Tunnel
+directive is unset, it is set to the default tunnel mode, which is
+.Dq point-to-point .
+.It Fl X
+Enables X11 forwarding.
+This can also be specified on a per-host basis in a configuration file.
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring.
+.Pp
+For this reason, X11 forwarding is subjected to X11 SECURITY extension
+restrictions by default.
+Please refer to the
+.Nm
+.Fl Y
+option and the
+.Cm ForwardX11Trusted
+directive in
+.Xr ssh_config 5
+for more information.
+.It Fl x
+Disables X11 forwarding.
+.It Fl Y
+Enables trusted X11 forwarding.
+Trusted X11 forwardings are not subjected to the X11 SECURITY extension
+controls.
+.It Fl y
+Send log information using the
+.Xr syslog 3
+system module.
+By default this information is sent to stderr.
+.El
+.Pp
+.Nm
+may additionally obtain configuration data from
+a per-user configuration file and a system-wide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Sh AUTHENTICATION
+The OpenSSH SSH client supports SSH protocols 1 and 2.
+The default is to use protocol 2 only,
+though this can be changed via the
+.Cm Protocol
+option in
+.Xr ssh_config 5
+or the
+.Fl 1
+and
+.Fl 2
+options (see above).
+Both protocols support similar authentication methods,
+but protocol 2 is the default since
+it provides additional mechanisms for confidentiality
+(the traffic is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour)
+and integrity (hmac-md5, hmac-sha1,
+hmac-sha2-256, hmac-sha2-512,
+umac-64, hmac-ripemd160).
+Protocol 1 lacks a strong mechanism for ensuring the
+integrity of the connection.
+.Pp
+The methods available for authentication are:
+GSSAPI-based authentication,
+host-based authentication,
+public key authentication,
+challenge-response authentication,
+and password authentication.
+Authentication methods are tried in the order specified above,
+though protocol 2 has a configuration option to change the default order:
+.Cm PreferredAuthentications .
+.Pp
+Host-based authentication works as follows:
+If the machine the user logs in from is listed in
+.Pa /etc/hosts.equiv
+or
+.Pa /etc/shosts.equiv
+on the remote machine, and the user names are
+the same on both sides, or if the files
+.Pa ~/.rhosts
+or
+.Pa ~/.shosts
+exist in the user's home directory on the
+remote machine and contain a line containing the name of the client
+machine and the name of the user on that machine, the user is
+considered for login.
+Additionally, the server
+.Em must
+be able to verify the client's
+host key (see the description of
+.Pa /etc/ssh/ssh_known_hosts
+and
+.Pa ~/.ssh/known_hosts ,
+below)
+for login to be permitted.
+This authentication method closes security holes due to IP
+spoofing, DNS spoofing, and routing spoofing.
+[Note to the administrator:
+.Pa /etc/hosts.equiv ,
+.Pa ~/.rhosts ,
+and the rlogin/rsh protocol in general, are inherently insecure and should be
+disabled if security is desired.]
+.Pp
+Public key authentication works as follows:
+The scheme is based on public-key cryptography,
+using cryptosystems
+where encryption and decryption are done using separate keys,
+and it is unfeasible to derive the decryption key from the encryption key.
+The idea is that each user creates a public/private
+key pair for authentication purposes.
+The server knows the public key, and only the user knows the private key.
+.Nm
+implements public key authentication protocol automatically,
+using one of the DSA, ECDSA or RSA algorithms.
+Protocol 1 is restricted to using only RSA keys,
+but protocol 2 may use any.
+The
+.Sx HISTORY
+section of
+.Xr ssl 8
+contains a brief discussion of the DSA and RSA algorithms.
+.Pp
+The file
+.Pa ~/.ssh/authorized_keys
+lists the public keys that are permitted for logging in.
+When the user logs in, the
+.Nm
+program tells the server which key pair it would like to use for
+authentication.
+The client proves that it has access to the private key
+and the server checks that the corresponding public key
+is authorized to accept the account.
+.Pp
+The user creates his/her key pair by running
+.Xr ssh-keygen 1 .
+This stores the private key in
+.Pa ~/.ssh/identity
+(protocol 1),
+.Pa ~/.ssh/id_dsa
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa
+(protocol 2 RSA)
+and stores the public key in
+.Pa ~/.ssh/identity.pub
+(protocol 1),
+.Pa ~/.ssh/id_dsa.pub
+(protocol 2 DSA),
+.Pa ~/.ssh/id_ecdsa.pub
+(protocol 2 ECDSA),
+or
+.Pa ~/.ssh/id_rsa.pub
+(protocol 2 RSA)
+in the user's home directory.
+The user should then copy the public key
+to
+.Pa ~/.ssh/authorized_keys
+in his/her home directory on the remote machine.
+The
+.Pa authorized_keys
+file corresponds to the conventional
+.Pa ~/.rhosts
+file, and has one key
+per line, though the lines can be very long.
+After this, the user can log in without giving the password.
+.Pp
+A variation on public key authentication
+is available in the form of certificate authentication:
+instead of a set of public/private keys,
+signed certificates are used.
+This has the advantage that a single trusted certification authority
+can be used in place of many public/private keys.
+See the
+.Sx CERTIFICATES
+section of
+.Xr ssh-keygen 1
+for more information.
+.Pp
+The most convenient way to use public key or certificate authentication
+may be with an authentication agent.
+See
+.Xr ssh-agent 1
+for more information.
+.Pp
+Challenge-response authentication works as follows:
+The server sends an arbitrary
+.Qq challenge
+text, and prompts for a response.
+Protocol 2 allows multiple challenges and responses;
+protocol 1 is restricted to just one challenge/response.
+Examples of challenge-response authentication include
+BSD Authentication (see
+.Xr login.conf 5 )
+and PAM (some non-OpenBSD systems).
+.Pp
+Finally, if other authentication methods fail,
+.Nm
+prompts the user for a password.
+The password is sent to the remote
+host for checking; however, since all communications are encrypted,
+the password cannot be seen by someone listening on the network.
+.Pp
+.Nm
+automatically maintains and checks a database containing
+identification for all hosts it has ever been used with.
+Host keys are stored in
+.Pa ~/.ssh/known_hosts
+in the user's home directory.
+Additionally, the file
+.Pa /etc/ssh/ssh_known_hosts
+is automatically checked for known hosts.
+Any new hosts are automatically added to the user's file.
+If a host's identification ever changes,
+.Nm
+warns about this and disables password authentication to prevent
+server spoofing or man-in-the-middle attacks,
+which could otherwise be used to circumvent the encryption.
+The
+.Cm StrictHostKeyChecking
+option can be used to control logins to machines whose
+host key is not known or has changed.
+.Pp
+When the user's identity has been accepted by the server, the server
+either executes the given command, or logs into the machine and gives
+the user a normal shell on the remote machine.
+All communication with
+the remote command or shell will be automatically encrypted.
+.Pp
+If a pseudo-terminal has been allocated (normal login session), the
+user may use the escape characters noted below.
+.Pp
+If no pseudo-tty has been allocated,
+the session is transparent and can be used to reliably transfer binary data.
+On most systems, setting the escape character to
+.Dq none
+will also make the session transparent even if a tty is used.
+.Pp
+The session terminates when the command or shell on the remote
+machine exits and all X11 and TCP connections have been closed.
+.Sh ESCAPE CHARACTERS
+When a pseudo-terminal has been requested,
+.Nm
+supports a number of functions through the use of an escape character.
+.Pp
+A single tilde character can be sent as
+.Ic ~~
+or by following the tilde by a character other than those described below.
+The escape character must always follow a newline to be interpreted as
+special.
+The escape character can be changed in configuration files using the
+.Cm EscapeChar
+configuration directive or on the command line by the
+.Fl e
+option.
+.Pp
+The supported escapes (assuming the default
+.Ql ~ )
+are:
+.Bl -tag -width Ds
+.It Cm ~.
+Disconnect.
+.It Cm ~^Z
+Background
+.Nm .
+.It Cm ~#
+List forwarded connections.
+.It Cm ~&
+Background
+.Nm
+at logout when waiting for forwarded connection / X11 sessions to terminate.
+.It Cm ~?
+Display a list of escape characters.
+.It Cm ~B
+Send a BREAK to the remote system
+(only useful for SSH protocol version 2 and if the peer supports it).
+.It Cm ~C
+Open command line.
+Currently this allows the addition of port forwardings using the
+.Fl L ,
+.Fl R
+and
+.Fl D
+options (see above).
+It also allows the cancellation of existing remote port-forwardings
+using
+.Sm off
+.Fl KR Oo Ar bind_address : Oc Ar port .
+.Sm on
+.Ic !\& Ns Ar command
+allows the user to execute a local command if the
+.Ic PermitLocalCommand
+option is enabled in
+.Xr ssh_config 5 .
+Basic help is available, using the
+.Fl h
+option.
+.It Cm ~R
+Request rekeying of the connection
+(only useful for SSH protocol version 2 and if the peer supports it).
+.El
+.Sh TCP FORWARDING
+Forwarding of arbitrary TCP connections over the secure channel can
+be specified either on the command line or in a configuration file.
+One possible application of TCP forwarding is a secure connection to a
+mail server; another is going through firewalls.
+.Pp
+In the example below, we look at encrypting communication between
+an IRC client and server, even though the IRC server does not directly
+support encrypted communications.
+This works as follows:
+the user connects to the remote host using
+.Nm ,
+specifying a port to be used to forward connections
+to the remote server.
+After that it is possible to start the service which is to be encrypted
+on the client machine,
+connecting to the same local port,
+and
+.Nm
+will encrypt and forward the connection.
+.Pp
+The following example tunnels an IRC session from client machine
+.Dq 127.0.0.1
+(localhost)
+to remote server
+.Dq server.example.com :
+.Bd -literal -offset 4n
+$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
+$ irc -c '#users' -p 1234 pinky 127.0.0.1
+.Ed
+.Pp
+This tunnels a connection to IRC server
+.Dq server.example.com ,
+joining channel
+.Dq #users ,
+nickname
+.Dq pinky ,
+using port 1234.
+It doesn't matter which port is used,
+as long as it's greater than 1023
+(remember, only root can open sockets on privileged ports)
+and doesn't conflict with any ports already in use.
+The connection is forwarded to port 6667 on the remote server,
+since that's the standard port for IRC services.
+.Pp
+The
+.Fl f
+option backgrounds
+.Nm
+and the remote command
+.Dq sleep 10
+is specified to allow an amount of time
+(10 seconds, in the example)
+to start the service which is to be tunnelled.
+If no connections are made within the time specified,
+.Nm
+will exit.
+.Sh X11 FORWARDING
+If the
+.Cm ForwardX11
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl X ,
+.Fl x ,
+and
+.Fl Y
+options above)
+and the user is using X11 (the
+.Ev DISPLAY
+environment variable is set), the connection to the X11 display is
+automatically forwarded to the remote side in such a way that any X11
+programs started from the shell (or command) will go through the
+encrypted channel, and the connection to the real X server will be made
+from the local machine.
+The user should not manually set
+.Ev DISPLAY .
+Forwarding of X11 connections can be
+configured on the command line or in configuration files.
+.Pp
+The
+.Ev DISPLAY
+value set by
+.Nm
+will point to the server machine, but with a display number greater than zero.
+This is normal, and happens because
+.Nm
+creates a
+.Dq proxy
+X server on the server machine for forwarding the
+connections over the encrypted channel.
+.Pp
+.Nm
+will also automatically set up Xauthority data on the server machine.
+For this purpose, it will generate a random authorization cookie,
+store it in Xauthority on the server, and verify that any forwarded
+connections carry this cookie and replace it by the real cookie when
+the connection is opened.
+The real authentication cookie is never
+sent to the server machine (and no cookies are sent in the plain).
+.Pp
+If the
+.Cm ForwardAgent
+variable is set to
+.Dq yes
+(or see the description of the
+.Fl A
+and
+.Fl a
+options above) and
+the user is using an authentication agent, the connection to the agent
+is automatically forwarded to the remote side.
+.Sh VERIFYING HOST KEYS
+When connecting to a server for the first time,
+a fingerprint of the server's public key is presented to the user
+(unless the option
+.Cm StrictHostKeyChecking
+has been disabled).
+Fingerprints can be determined using
+.Xr ssh-keygen 1 :
+.Pp
+.Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
+.Pp
+If the fingerprint is already known, it can be matched
+and the key can be accepted or rejected.
+Because of the difficulty of comparing host keys
+just by looking at hex strings,
+there is also support to compare host keys visually,
+using
+.Em random art .
+By setting the
+.Cm VisualHostKey
+option to
+.Dq yes ,
+a small ASCII graphic gets displayed on every login to a server, no matter
+if the session itself is interactive or not.
+By learning the pattern a known server produces, a user can easily
+find out that the host key has changed when a completely different pattern
+is displayed.
+Because these patterns are not unambiguous however, a pattern that looks
+similar to the pattern remembered only gives a good probability that the
+host key is the same, not guaranteed proof.
+.Pp
+To get a listing of the fingerprints along with their random art for
+all known hosts, the following command line can be used:
+.Pp
+.Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts
+.Pp
+If the fingerprint is unknown,
+an alternative method of verification is available:
+SSH fingerprints verified by DNS.
+An additional resource record (RR),
+SSHFP,
+is added to a zonefile
+and the connecting client is able to match the fingerprint
+with that of the key presented.
+.Pp
+In this example, we are connecting a client to a server,
+.Dq host.example.com .
+The SSHFP resource records should first be added to the zonefile for
+host.example.com:
+.Bd -literal -offset indent
+$ ssh-keygen -r host.example.com.
+.Ed
+.Pp
+The output lines will have to be added to the zonefile.
+To check that the zone is answering fingerprint queries:
+.Pp
+.Dl $ dig -t SSHFP host.example.com
+.Pp
+Finally the client connects:
+.Bd -literal -offset indent
+$ ssh -o "VerifyHostKeyDNS ask" host.example.com
+[...]
+Matching host key fingerprint found in DNS.
+Are you sure you want to continue connecting (yes/no)?
+.Ed
+.Pp
+See the
+.Cm VerifyHostKeyDNS
+option in
+.Xr ssh_config 5
+for more information.
+.Sh SSH-BASED VIRTUAL PRIVATE NETWORKS
+.Nm
+contains support for Virtual Private Network (VPN) tunnelling
+using the
+.Xr tun 4
+network pseudo-device,
+allowing two networks to be joined securely.
+The
+.Xr sshd_config 5
+configuration option
+.Cm PermitTunnel
+controls whether the server supports this,
+and at what level (layer 2 or 3 traffic).
+.Pp
+The following example would connect client network 10.0.50.0/24
+with remote network 10.0.99.0/24 using a point-to-point connection
+from 10.1.1.1 to 10.1.1.2,
+provided that the SSH server running on the gateway to the remote network,
+at 192.168.1.15, allows it.
+.Pp
+On the client:
+.Bd -literal -offset indent
+# ssh -f -w 0:1 192.168.1.15 true
+# ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
+# route add 10.0.99.0/24 10.1.1.2
+.Ed
+.Pp
+On the server:
+.Bd -literal -offset indent
+# ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
+# route add 10.0.50.0/24 10.1.1.1
+.Ed
+.Pp
+Client access may be more finely tuned via the
+.Pa /root/.ssh/authorized_keys
+file (see below) and the
+.Cm PermitRootLogin
+server option.
+The following entry would permit connections on
+.Xr tun 4
+device 1 from user
+.Dq jane
+and on tun device 2 from user
+.Dq john ,
+if
+.Cm PermitRootLogin
+is set to
+.Dq forced-commands-only :
+.Bd -literal -offset 2n
+tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane
+tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john
+.Ed
+.Pp
+Since an SSH-based setup entails a fair amount of overhead,
+it may be more suited to temporary setups,
+such as for wireless VPNs.
+More permanent VPNs are better provided by tools such as
+.Xr ipsecctl 8
+and
+.Xr isakmpd 8 .
+.Sh ENVIRONMENT
+.Nm
+will normally set the following environment variables:
+.Bl -tag -width "SSH_ORIGINAL_COMMAND"
+.It Ev DISPLAY
+The
+.Ev DISPLAY
+variable indicates the location of the X11 server.
+It is automatically set by
+.Nm
+to point to a value of the form
+.Dq hostname:n ,
+where
+.Dq hostname
+indicates the host where the shell runs, and
+.Sq n
+is an integer \*(Ge 1.
+.Nm
+uses this special value to forward X11 connections over the secure
+channel.
+The user should normally not set
+.Ev DISPLAY
+explicitly, as that
+will render the X11 connection insecure (and will require the user to
+manually copy any required authorization cookies).
+.It Ev HOME
+Set to the path of the user's home directory.
+.It Ev LOGNAME
+Synonym for
+.Ev USER ;
+set for compatibility with systems that use this variable.
+.It Ev MAIL
+Set to the path of the user's mailbox.
+.It Ev PATH
+Set to the default
+.Ev PATH ,
+as specified when compiling
+.Nm .
+.It Ev SSH_ASKPASS
+If
+.Nm
+needs a passphrase, it will read the passphrase from the current
+terminal if it was run from a terminal.
+If
+.Nm
+does not have a terminal associated with it but
+.Ev DISPLAY
+and
+.Ev SSH_ASKPASS
+are set, it will execute the program specified by
+.Ev SSH_ASKPASS
+and open an X11 window to read the passphrase.
+This is particularly useful when calling
+.Nm
+from a
+.Pa .xsession
+or related script.
+(Note that on some machines it
+may be necessary to redirect the input from
+.Pa /dev/null
+to make this work.)
+.It Ev SSH_AUTH_SOCK
+Identifies the path of a
+.Ux Ns -domain
+socket used to communicate with the agent.
+.It Ev SSH_CONNECTION
+Identifies the client and server ends of the connection.
+The variable contains
+four space-separated values: client IP address, client port number,
+server IP address, and server port number.
+.It Ev SSH_ORIGINAL_COMMAND
+This variable contains the original command line if a forced command
+is executed.
+It can be used to extract the original arguments.
+.It Ev SSH_TTY
+This is set to the name of the tty (path to the device) associated
+with the current shell or command.
+If the current session has no tty,
+this variable is not set.
+.It Ev TZ
+This variable is set to indicate the present time zone if it
+was set when the daemon was started (i.e. the daemon passes the value
+on to new connections).
+.It Ev USER
+Set to the name of the user logging in.
+.El
+.Pp
+Additionally,
+.Nm
+reads
+.Pa ~/.ssh/environment ,
+and adds lines of the format
+.Dq VARNAME=value
+to the environment if the file exists and users are allowed to
+change their environment.
+For more information, see the
+.Cm PermitUserEnvironment
+option in
+.Xr sshd_config 5 .
+.Sh FILES
+.Bl -tag -width Ds -compact
+.It Pa ~/.rhosts
+This file is used for host-based authentication (see above).
+On some machines this file may need to be
+world-readable if the user's home directory is on an NFS partition,
+because
+.Xr sshd 8
+reads it as root.
+Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else.
+The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.Pp
+.It Pa ~/.shosts
+This file is used in exactly the same way as
+.Pa .rhosts ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa ~/.ssh/
+This directory is the default location for all user-specific configuration
+and authentication information.
+There is no general requirement to keep the entire contents of this directory
+secret, but the recommended permissions are read/write/execute for the user,
+and not accessible by others.
+.Pp
+.It Pa ~/.ssh/authorized_keys
+Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as
+this user.
+The format of this file is described in the
+.Xr sshd 8
+manual page.
+This file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.Pp
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+.Pp
+.It Pa ~/.ssh/environment
+Contains additional definitions for environment variables; see
+.Sx ENVIRONMENT ,
+above.
+.Pp
+.It Pa ~/.ssh/identity
+.It Pa ~/.ssh/id_dsa
+.It Pa ~/.ssh/id_ecdsa
+.It Pa ~/.ssh/id_rsa
+Contains the private key for authentication.
+These files
+contain sensitive data and should be readable by the user but not
+accessible by others (read/write/execute).
+.Nm
+will simply ignore a private key file if it is accessible by others.
+It is possible to specify a passphrase when
+generating the key which will be used to encrypt the
+sensitive part of this file using 3DES.
+.Pp
+.It Pa ~/.ssh/identity.pub
+.It Pa ~/.ssh/id_dsa.pub
+.It Pa ~/.ssh/id_ecdsa.pub
+.It Pa ~/.ssh/id_rsa.pub
+Contains the public key for authentication.
+These files are not
+sensitive and can (but need not) be readable by anyone.
+.Pp
+.It Pa ~/.ssh/known_hosts
+Contains a list of host keys for all hosts the user has logged into
+that are not already in the systemwide list of known host keys.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa ~/.ssh/rc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is
+started.
+See the
+.Xr sshd 8
+manual page for more information.
+.Pp
+.It Pa /etc/hosts.equiv
+This file is for host-based authentication (see above).
+It should only be writable by root.
+.Pp
+.It Pa /etc/shosts.equiv
+This file is used in exactly the same way as
+.Pa hosts.equiv ,
+but allows host-based authentication without permitting login with
+rlogin/rsh.
+.Pp
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+The file format and configuration options are described in
+.Xr ssh_config 5 .
+.Pp
+.It Pa /etc/ssh/ssh_host_key
+.It Pa /etc/ssh/ssh_host_dsa_key
+.It Pa /etc/ssh/ssh_host_ecdsa_key
+.It Pa /etc/ssh/ssh_host_rsa_key
+These three files contain the private parts of the host keys
+and are used for host-based authentication.
+If protocol version 1 is used,
+.Nm
+must be setuid root, since the host key is readable only by root.
+For protocol version 2,
+.Nm
+uses
+.Xr ssh-keysign 8
+to access the host keys,
+eliminating the requirement that
+.Nm
+be setuid root when host-based authentication is used.
+By default
+.Nm
+is not setuid root.
+.Pp
+.It Pa /etc/ssh/ssh_known_hosts
+Systemwide list of known host keys.
+This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization.
+It should be world-readable.
+See
+.Xr sshd 8
+for further details of the format of this file.
+.Pp
+.It Pa /etc/ssh/sshrc
+Commands in this file are executed by
+.Nm
+when the user logs in, just before the user's shell (or command) is started.
+See the
+.Xr sshd 8
+manual page for more information.
+.El
+.Sh EXIT STATUS
+.Nm
+exits with the exit status of the remote command or with 255
+if an error occurred.
+.Sh SEE ALSO
+.Xr scp 1 ,
+.Xr sftp 1 ,
+.Xr ssh-add 1 ,
+.Xr ssh-agent 1 ,
+.Xr ssh-keygen 1 ,
+.Xr ssh-keyscan 1 ,
+.Xr ssh-vulnkey 1 ,
+.Xr tun 4 ,
+.Xr hosts.equiv 5 ,
+.Xr ssh_config 5 ,
+.Xr ssh-keysign 8 ,
+.Xr sshd 8
+.Rs
+.%R RFC 4250
+.%T "The Secure Shell (SSH) Protocol Assigned Numbers"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4251
+.%T "The Secure Shell (SSH) Protocol Architecture"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4252
+.%T "The Secure Shell (SSH) Authentication Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4253
+.%T "The Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4254
+.%T "The Secure Shell (SSH) Connection Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4255
+.%T "Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4256
+.%T "Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4335
+.%T "The Secure Shell (SSH) Session Channel Break Extension"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4344
+.%T "The Secure Shell (SSH) Transport Layer Encryption Modes"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4345
+.%T "Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4419
+.%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
+.%D 2006
+.Re
+.Rs
+.%R RFC 4716
+.%T "The Secure Shell (SSH) Public Key File Format"
+.%D 2006
+.Re
+.Rs
+.%R RFC 5656
+.%T "Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer"
+.%D 2009
+.Re
+.Rs
+.%T "Hash Visualization: a New Technique to improve Real-World Security"
+.%A A. Perrig
+.%A D. Song
+.%D 1999
+.%O "International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)"
+.Re
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/.pc/user-group-modes.patch/ssh_config.5 b/.pc/user-group-modes.patch/ssh_config.5
new file mode 100644 (file)
index 0000000..4b81b5a
--- /dev/null
@@ -0,0 +1,1363 @@
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\"                    All rights reserved
+.\"
+.\" As far as I am concerned, the code I have written for this software
+.\" can be used freely for any purpose.  Any derived versions of this
+.\" software must be clearly marked as such, and if the derived work is
+.\" incompatible with the protocol description in the RFC file, it must be
+.\" called by a name other than "ssh" or "Secure Shell".
+.\"
+.\" Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
+.\" Copyright (c) 1999 Aaron Campbell.  All rights reserved.
+.\" Copyright (c) 1999 Theo de Raadt.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
+.Dt SSH_CONFIG 5
+.Os
+.Sh NAME
+.Nm ssh_config
+.Nd OpenSSH SSH client configuration files
+.Sh SYNOPSIS
+.Nm ~/.ssh/config
+.Nm /etc/ssh/ssh_config
+.Sh DESCRIPTION
+.Xr ssh 1
+obtains configuration data from the following sources in
+the following order:
+.Pp
+.Bl -enum -offset indent -compact
+.It
+command-line options
+.It
+user's configuration file
+.Pq Pa ~/.ssh/config
+.It
+system-wide configuration file
+.Pq Pa /etc/ssh/ssh_config
+.El
+.Pp
+For each parameter, the first obtained value
+will be used.
+The configuration files contain sections separated by
+.Dq Host
+specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification.
+The matched host name is the one given on the command line.
+.Pp
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.Pp
+The configuration file has the following format:
+.Pp
+Empty lines and lines starting with
+.Ql #
+are comments.
+Otherwise a line is of the format
+.Dq keyword arguments .
+Configuration options may be separated by whitespace or
+optional whitespace and exactly one
+.Ql = ;
+the latter format is useful to avoid the need to quote whitespace
+when specifying configuration options using the
+.Nm ssh ,
+.Nm scp ,
+and
+.Nm sftp
+.Fl o
+option.
+Arguments may optionally be enclosed in double quotes
+.Pq \&"
+in order to represent arguments containing spaces.
+.Pp
+The possible
+keywords and their meanings are as follows (note that
+keywords are case-insensitive and arguments are case-sensitive):
+.Bl -tag -width Ds
+.It Cm Host
+Restricts the following declarations (up to the next
+.Cm Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword.
+If more than one pattern is provided, they should be separated by whitespace.
+A single
+.Ql *
+as a pattern can be used to provide global
+defaults for all hosts.
+The host is the
+.Ar hostname
+argument given on the command line (i.e. the name is not converted to
+a canonicalized host name before matching).
+.Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm AddressFamily
+Specifies which address family to use when connecting.
+Valid arguments are
+.Dq any ,
+.Dq inet
+(use IPv4 only), or
+.Dq inet6
+(use IPv6 only).
+.It Cm BatchMode
+If set to
+.Dq yes ,
+passphrase/password querying will be disabled.
+In addition, the
+.Cm ServerAliveInterval
+option will be set to 300 seconds by default.
+This option is useful in scripts and other batch jobs where no user
+is present to supply the password,
+and where it is desirable to detect a broken network swiftly.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm BindAddress
+Use the specified address on the local machine as the source address of
+the connection.
+Only useful on systems with more than one address.
+Note that this option does not work if
+.Cm UsePrivilegedPort
+is set to
+.Dq yes .
+.It Cm ChallengeResponseAuthentication
+Specifies whether to use challenge-response authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm CheckHostIP
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will additionally check the host IP address in the
+.Pa known_hosts
+file.
+This allows ssh to detect if a host key changed due to DNS spoofing.
+If the option is set to
+.Dq no ,
+the check will not be executed.
+The default is
+.Dq yes .
+.It Cm Cipher
+Specifies the cipher to use for encrypting the session
+in protocol version 1.
+Currently,
+.Dq blowfish ,
+.Dq 3des ,
+and
+.Dq des
+are supported.
+.Ar des
+is only supported in the
+.Xr ssh 1
+client for interoperability with legacy protocol 1 implementations
+that do not support the
+.Ar 3des
+cipher.
+Its use is strongly discouraged due to cryptographic weaknesses.
+The default is
+.Dq 3des .
+.It Cm Ciphers
+Specifies the ciphers allowed for protocol version 2
+in order of preference.
+Multiple ciphers must be comma-separated.
+The supported ciphers are
+.Dq 3des-cbc ,
+.Dq aes128-cbc ,
+.Dq aes192-cbc ,
+.Dq aes256-cbc ,
+.Dq aes128-ctr ,
+.Dq aes192-ctr ,
+.Dq aes256-ctr ,
+.Dq arcfour128 ,
+.Dq arcfour256 ,
+.Dq arcfour ,
+.Dq blowfish-cbc ,
+and
+.Dq cast128-cbc .
+The default is:
+.Bd -literal -offset 3n
+aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
+aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
+aes256-cbc,arcfour
+.Ed
+.It Cm ClearAllForwardings
+Specifies that all local, remote, and dynamic port forwardings
+specified in the configuration files or on the command line be
+cleared.
+This option is primarily useful when used from the
+.Xr ssh 1
+command line to clear port forwardings set in
+configuration files, and is automatically set by
+.Xr scp 1
+and
+.Xr sftp 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm Compression
+Specifies whether to use compression.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm CompressionLevel
+Specifies the compression level to use if compression is enabled.
+The argument must be an integer from 1 (fast) to 9 (slow, best).
+The default level is 6, which is good for most applications.
+The meaning of the values is the same as in
+.Xr gzip 1 .
+Note that this option applies to protocol version 1 only.
+.It Cm ConnectionAttempts
+Specifies the number of tries (one per second) to make before exiting.
+The argument must be an integer.
+This may be useful in scripts if the connection sometimes fails.
+The default is 1.
+.It Cm ConnectTimeout
+Specifies the timeout (in seconds) used when connecting to the
+SSH server, instead of using the default system TCP timeout.
+This value is used only when the target is down or really unreachable,
+not when it refuses the connection.
+.It Cm ControlMaster
+Enables the sharing of multiple sessions over a single network connection.
+When set to
+.Dq yes ,
+.Xr ssh 1
+will listen for connections on a control socket specified using the
+.Cm ControlPath
+argument.
+Additional sessions can connect to this socket using the same
+.Cm ControlPath
+with
+.Cm ControlMaster
+set to
+.Dq no
+(the default).
+These sessions will try to reuse the master instance's network connection
+rather than initiating new ones, but will fall back to connecting normally
+if the control socket does not exist, or is not listening.
+.Pp
+Setting this to
+.Dq ask
+will cause ssh
+to listen for control connections, but require confirmation using the
+.Ev SSH_ASKPASS
+program before they are accepted (see
+.Xr ssh-add 1
+for details).
+If the
+.Cm ControlPath
+cannot be opened,
+ssh will continue without connecting to a master instance.
+.Pp
+X11 and
+.Xr ssh-agent 1
+forwarding is supported over these multiplexed connections, however the
+display and agent forwarded will be the one belonging to the master
+connection i.e. it is not possible to forward multiple displays or agents.
+.Pp
+Two additional options allow for opportunistic multiplexing: try to use a
+master connection but fall back to creating a new one if one does not already
+exist.
+These options are:
+.Dq auto
+and
+.Dq autoask .
+The latter requires confirmation like the
+.Dq ask
+option.
+.It Cm ControlPath
+Specify the path to the control socket used for connection sharing as described
+in the
+.Cm ControlMaster
+section above or the string
+.Dq none
+to disable connection sharing.
+In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
+.Ql %l
+will be substituted by the local host name (including any domain name),
+.Ql %h
+will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
+.Ql %p
+the port,
+.Ql %r
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
+It is recommended that any
+.Cm ControlPath
+used for opportunistic connection sharing include
+at least %h, %p, and %r.
+This ensures that shared connections are uniquely identified.
+.It Cm ControlPersist
+When used in conjunction with
+.Cm ControlMaster ,
+specifies that the master connection should remain open
+in the background (waiting for future client connections)
+after the initial client connection has been closed.
+If set to
+.Dq no ,
+then the master connection will not be placed into the background,
+and will close as soon as the initial client connection is closed.
+If set to
+.Dq yes ,
+then the master connection will remain in the background indefinitely
+(until killed or closed via a mechanism such as the
+.Xr ssh 1
+.Dq Fl O No exit
+option).
+If set to a time in seconds, or a time in any of the formats documented in
+.Xr sshd_config 5 ,
+then the backgrounded master connection will automatically terminate
+after it has remained idle (with no client connections) for the
+specified time.
+.It Cm DynamicForward
+Specifies that a TCP port on the local machine be forwarded
+over the secure channel, and the application
+protocol is then used to determine where to connect to from the
+remote machine.
+.Pp
+The argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port .
+.Sm on
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.Pp
+Currently the SOCKS4 and SOCKS5 protocols are supported, and
+.Xr ssh 1
+will act as a SOCKS server.
+Multiple forwardings may be specified, and
+additional forwardings can be given on the command line.
+Only the superuser can forward privileged ports.
+.It Cm EnableSSHKeysign
+Setting this option to
+.Dq yes
+in the global client configuration file
+.Pa /etc/ssh/ssh_config
+enables the use of the helper program
+.Xr ssh-keysign 8
+during
+.Cm HostbasedAuthentication .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option should be placed in the non-hostspecific section.
+See
+.Xr ssh-keysign 8
+for more information.
+.It Cm EscapeChar
+Sets the escape character (default:
+.Ql ~ ) .
+The escape character can also
+be set on the command line.
+The argument should be a single character,
+.Ql ^
+followed by a letter, or
+.Dq none
+to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.It Cm ExitOnForwardFailure
+Specifies whether
+.Xr ssh 1
+should terminate the connection if it cannot set up all requested
+dynamic, tunnel, local, and remote port forwardings.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+Agent forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the agent's Unix-domain socket)
+can access the local agent through the forwarded connection.
+An attacker cannot obtain key material from the agent,
+however they can perform operations on the keys that enable them to
+authenticate using the identities loaded into the agent.
+.It Cm ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.Ev DISPLAY
+set.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.Pp
+X11 forwarding should be enabled with caution.
+Users with the ability to bypass file permissions on the remote host
+(for the user's X11 authorization database)
+can access the local X11 display through the forwarded connection.
+An attacker may then be able to perform activities such as keystroke monitoring
+if the
+.Cm ForwardX11Trusted
+option is also enabled.
+.It Cm ForwardX11Timeout
+Specify a timeout for untrusted X11 forwarding
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5 .
+X11 connections received by
+.Xr ssh 1
+after this time will be refused.
+The default is to disable untrusted X11 forwarding after twenty minutes has
+elapsed.
+.It Cm ForwardX11Trusted
+If this option is set to
+.Dq yes ,
+remote X11 clients will have full access to the original X11 display.
+.Pp
+If this option is set to
+.Dq no ,
+remote X11 clients will be considered untrusted and prevented
+from stealing or tampering with data belonging to trusted X11
+clients.
+Furthermore, the
+.Xr xauth 1
+token used for the session will be set to expire after 20 minutes.
+Remote clients will be refused access after this time.
+.Pp
+The default is
+.Dq no .
+.Pp
+See the X11 SECURITY extension specification for full details on
+the restrictions imposed on untrusted clients.
+.It Cm GatewayPorts
+Specifies whether remote hosts are allowed to connect to local
+forwarded ports.
+By default,
+.Xr ssh 1
+binds local port forwardings to the loopback address.
+This prevents other remote hosts from connecting to forwarded ports.
+.Cm GatewayPorts
+can be used to specify that ssh
+should bind local port forwardings to the wildcard address,
+thus allowing remote hosts to connect to forwarded ports.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm GlobalKnownHostsFile
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
+.It Cm GSSAPIAuthentication
+Specifies whether user authentication based on GSSAPI is allowed.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
+.It Cm GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when 
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
+.It Cm GSSAPIDelegateCredentials
+Forward (delegate) credentials to the server.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI.
+.It Cm HashKnownHosts
+Indicates that
+.Xr ssh 1
+should hash host names and addresses when they are added to
+.Pa ~/.ssh/known_hosts .
+These hashed names may be used normally by
+.Xr ssh 1
+and
+.Xr sshd 8 ,
+but they do not reveal identifying information should the file's contents
+be disclosed.
+The default is
+.Dq no .
+Note that existing names and addresses in known hosts files
+will not be converted automatically,
+but may be manually hashed using
+.Xr ssh-keygen 1 .
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 2 only and
+is similar to
+.Cm RhostsRSAAuthentication .
+.It Cm HostKeyAlgorithms
+Specifies the protocol version 2 host key algorithms
+that the client wants to use in order of preference.
+The default for this option is:
+.Bd -literal -offset 3n
+ecdsa-sha2-nistp256-cert-v01@openssh.com,
+ecdsa-sha2-nistp384-cert-v01@openssh.com,
+ecdsa-sha2-nistp521-cert-v01@openssh.com,
+ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
+ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
+ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+ssh-rsa,ssh-dss
+.Ed
+.Pp
+If hostkeys are known for the destination host then this default is modified
+to prefer their algorithms.
+.It Cm HostKeyAlias
+Specifies an alias that should be used instead of the
+real host name when looking up or saving the host key
+in the host key database files.
+This option is useful for tunneling SSH connections
+or for multiple servers running on a single host.
+.It Cm HostName
+Specifies the real host name to log into.
+This can be used to specify nicknames or abbreviations for hosts.
+If the hostname contains the character sequence
+.Ql %h ,
+then this will be replaced with the host name specified on the command line
+(this is useful for manipulating unqualified names).
+The default is the name given on the command line.
+Numeric IP addresses are also permitted (both on the command line and in
+.Cm HostName
+specifications).
+.It Cm IdentitiesOnly
+Specifies that
+.Xr ssh 1
+should only use the authentication identity files configured in the
+.Nm
+files,
+even if
+.Xr ssh-agent 1
+offers more identities.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+This option is intended for situations where ssh-agent
+offers many different identities.
+The default is
+.Dq no .
+.It Cm IdentityFile
+Specifies a file from which the user's DSA, ECDSA or DSA authentication
+identity is read.
+The default is
+.Pa ~/.ssh/identity
+for protocol version 1, and
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/id_ecdsa
+and
+.Pa ~/.ssh/id_rsa
+for protocol version 2.
+Additionally, any identities represented by the authentication agent
+will be used for authentication.
+.Xr ssh 1
+will try to load certificate information from the filename obtained by
+appending
+.Pa -cert.pub
+to the path of a specified
+.Cm IdentityFile .
+.Pp
+The file name may use the tilde
+syntax to refer to a user's home directory or one of the following
+escape characters:
+.Ql %d
+(local user's home directory),
+.Ql %u
+(local user name),
+.Ql %l
+(local host name),
+.Ql %h
+(remote host name) or
+.Ql %r
+(remote user name).
+.Pp
+It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
+.It Cm IPQoS
+Specifies the IPv4 type-of-service or DSCP class for connections.
+Accepted values are
+.Dq af11 ,
+.Dq af12 ,
+.Dq af13 ,
+.Dq af14 ,
+.Dq af22 ,
+.Dq af23 ,
+.Dq af31 ,
+.Dq af32 ,
+.Dq af33 ,
+.Dq af41 ,
+.Dq af42 ,
+.Dq af43 ,
+.Dq cs0 ,
+.Dq cs1 ,
+.Dq cs2 ,
+.Dq cs3 ,
+.Dq cs4 ,
+.Dq cs5 ,
+.Dq cs6 ,
+.Dq cs7 ,
+.Dq ef ,
+.Dq lowdelay ,
+.Dq throughput ,
+.Dq reliability ,
+or a numeric value.
+This option may take one or two arguments, separated by whitespace.
+If one argument is specified, it is used as the packet class unconditionally.
+If two values are specified, the first is automatically selected for
+interactive sessions and the second for non-interactive sessions.
+The default is
+.Dq lowdelay
+for interactive sessions and
+.Dq throughput
+for non-interactive sessions.
+.It Cm KbdInteractiveAuthentication
+Specifies whether to use keyboard-interactive authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm KbdInteractiveDevices
+Specifies the list of methods to use in keyboard-interactive authentication.
+Multiple method names must be comma-separated.
+The default is to use the server specified list.
+The methods available vary depending on what the server supports.
+For an OpenSSH server,
+it may be zero or more of:
+.Dq bsdauth ,
+.Dq pam ,
+and
+.Dq skey .
+.It Cm KexAlgorithms
+Specifies the available KEX (Key Exchange) algorithms.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
+diffie-hellman-group-exchange-sha256,
+diffie-hellman-group-exchange-sha1,
+diffie-hellman-group14-sha1,
+diffie-hellman-group1-sha1
+.Ed
+.It Cm LocalCommand
+Specifies a command to execute on the local machine after successfully
+connecting to the server.
+The command string extends to the end of the line, and is executed with
+the user's shell.
+The following escape character substitutions will be performed:
+.Ql %d
+(local user's home directory),
+.Ql %h
+(remote host name),
+.Ql %l
+(local host name),
+.Ql %n
+(host name as provided on the command line),
+.Ql %p
+(remote port),
+.Ql %r
+(remote user name) or
+.Ql %u
+(local user name).
+.Pp
+The command is run synchronously and does not have access to the
+session of the
+.Xr ssh 1
+that spawned it.
+It should not be used for interactive commands.
+.Pp
+This directive is ignored unless
+.Cm PermitLocalCommand
+has been enabled.
+.It Cm LocalForward
+Specifies that a TCP port on the local machine be forwarded over
+the secure channel to the specified host and port from the remote machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional forwardings can be
+given on the command line.
+Only the superuser can forward privileged ports.
+By default, the local port is bound in accordance with the
+.Cm GatewayPorts
+setting.
+However, an explicit
+.Ar bind_address
+may be used to bind the connection to a specific address.
+The
+.Ar bind_address
+of
+.Dq localhost
+indicates that the listening port be bound for local use only, while an
+empty address or
+.Sq *
+indicates that the port should be available from all interfaces.
+.It Cm LogLevel
+Gives the verbosity level that is used when logging messages from
+.Xr ssh 1 .
+The possible values are:
+QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
+The default is INFO.
+DEBUG and DEBUG1 are equivalent.
+DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm MACs
+Specifies the MAC (message authentication code) algorithms
+in order of preference.
+The MAC algorithm is used in protocol version 2
+for data integrity protection.
+Multiple algorithms must be comma-separated.
+The default is:
+.Bd -literal -offset indent
+hmac-md5,hmac-sha1,umac-64@openssh.com,
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
+.Ed
+.It Cm NoHostAuthenticationForLocalhost
+This option can be used if the home directory is shared across machines.
+In this case localhost will refer to a different machine on each of
+the machines and the user will get many warnings about changed host keys.
+However, this option disables host authentication for localhost.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is to check the host key for localhost.
+.It Cm NumberOfPasswordPrompts
+Specifies the number of password prompts before giving up.
+The argument to this keyword must be an integer.
+The default is 3.
+.It Cm PasswordAuthentication
+Specifies whether to use password authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+.It Cm PermitLocalCommand
+Allow local command execution via the
+.Ic LocalCommand
+option or using the
+.Ic !\& Ns Ar command
+escape sequence in
+.Xr ssh 1 .
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+.It Cm PKCS11Provider
+Specifies which PKCS#11 provider to use.
+The argument to this keyword is the PKCS#11 shared library
+.Xr ssh 1
+should use to communicate with a PKCS#11 token providing the user's
+private RSA key.
+.It Cm Port
+Specifies the port number to connect on the remote host.
+The default is 22.
+.It Cm PreferredAuthentications
+Specifies the order in which the client should try protocol 2
+authentication methods.
+This allows a client to prefer one method (e.g.\&
+.Cm keyboard-interactive )
+over another method (e.g.\&
+.Cm password ) .
+The default is:
+.Bd -literal -offset indent
+gssapi-with-mic,hostbased,publickey,
+keyboard-interactive,password
+.Ed
+.It Cm Protocol
+Specifies the protocol versions
+.Xr ssh 1
+should support in order of preference.
+The possible values are
+.Sq 1
+and
+.Sq 2 .
+Multiple versions must be comma-separated.
+When this option is set to
+.Dq 2,1
+.Nm ssh
+will try version 2 and fall back to version 1
+if version 2 is not available.
+The default is
+.Sq 2 .
+.It Cm ProxyCommand
+Specifies the command to use to connect to the server.
+The command
+string extends to the end of the line, and is executed with
+the user's shell.
+In the command string, any occurrence of
+.Ql %h
+will be substituted by the host name to
+connect,
+.Ql %p
+by the port, and
+.Ql %r
+by the remote user name.
+The command can be basically anything,
+and should read from its standard input and write to its standard output.
+It should eventually connect an
+.Xr sshd 8
+server running on some machine, or execute
+.Ic sshd -i
+somewhere.
+Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+Setting the command to
+.Dq none
+disables this option entirely.
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
+.Pp
+This directive is useful in conjunction with
+.Xr nc 1
+and its proxy support.
+For example, the following directive would connect via an HTTP proxy at
+192.0.2.0:
+.Bd -literal -offset 3n
+ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
+.Ed
+.It Cm PubkeyAuthentication
+Specifies whether to try public key authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq yes .
+This option applies to protocol version 2 only.
+.It Cm RekeyLimit
+Specifies the maximum amount of data that may be transmitted before the
+session key is renegotiated.
+The argument is the number of bytes, with an optional suffix of
+.Sq K ,
+.Sq M ,
+or
+.Sq G
+to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
+The default is between
+.Sq 1G
+and
+.Sq 4G ,
+depending on the cipher.
+This option applies to protocol version 2 only.
+.It Cm RemoteForward
+Specifies that a TCP port on the remote machine be forwarded over
+the secure channel to the specified host and port from the local machine.
+The first argument must be
+.Sm off
+.Oo Ar bind_address : Oc Ar port
+.Sm on
+and the second argument must be
+.Ar host : Ns Ar hostport .
+IPv6 addresses can be specified by enclosing addresses in square brackets.
+Multiple forwardings may be specified, and additional
+forwardings can be given on the command line.
+Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+.Pp
+If the
+.Ar port
+argument is
+.Ql 0 ,
+the listen port will be dynamically allocated on the server and reported
+to the client at run time.
+.Pp
+If the
+.Ar bind_address
+is not specified, the default is to only bind to loopback addresses.
+If the
+.Ar bind_address
+is
+.Ql *
+or an empty string, then the forwarding is requested to listen on all
+interfaces.
+Specifying a remote
+.Ar bind_address
+will only succeed if the server's
+.Cm GatewayPorts
+option is enabled (see
+.Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
+.It Cm RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+This option applies to protocol version 1 only and requires
+.Xr ssh 1
+to be setuid root.
+.It Cm RSAAuthentication
+Specifies whether to try RSA authentication.
+The argument to this keyword must be
+.Dq yes
+or
+.Dq no .
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 1 only.
+.It Cm SendEnv
+Specifies what variables from the local
+.Xr environ 7
+should be sent to the server.
+Note that environment passing is only supported for protocol 2.
+The server must also support it, and the server must be configured to
+accept these environment variables.
+Refer to
+.Cm AcceptEnv
+in
+.Xr sshd_config 5
+for how to configure the server.
+Variables are specified by name, which may contain wildcard characters.
+Multiple environment variables may be separated by whitespace or spread
+across multiple
+.Cm SendEnv
+directives.
+The default is not to send any environment variables.
+.Pp
+See
+.Sx PATTERNS
+for more information on patterns.
+.It Cm ServerAliveCountMax
+Sets the number of server alive messages (see below) which may be
+sent without
+.Xr ssh 1
+receiving any messages back from the server.
+If this threshold is reached while server alive messages are being sent,
+ssh will disconnect from the server, terminating the session.
+It is important to note that the use of server alive messages is very
+different from
+.Cm TCPKeepAlive
+(below).
+The server alive messages are sent through the encrypted channel
+and therefore will not be spoofable.
+The TCP keepalive option enabled by
+.Cm TCPKeepAlive
+is spoofable.
+The server alive mechanism is valuable when the client or
+server depend on knowing when a connection has become inactive.
+.Pp
+The default value is 3.
+If, for example,
+.Cm ServerAliveInterval
+(see below) is set to 15 and
+.Cm ServerAliveCountMax
+is left at the default, if the server becomes unresponsive,
+ssh will disconnect after approximately 45 seconds.
+This option applies to protocol version 2 only; in protocol version
+1 there is no mechanism to request a response from the server to the
+server alive messages, so disconnection is the responsibility of the TCP
+stack.
+.It Cm ServerAliveInterval
+Sets a timeout interval in seconds after which if no data has been received
+from the server,
+.Xr ssh 1
+will send a message through the encrypted
+channel to request a response from the server.
+The default
+is 0, indicating that these messages will not be sent to the server,
+or 300 if the
+.Cm BatchMode
+option is set.
+This option applies to protocol version 2 only.
+.Cm ProtocolKeepAlives
+and
+.Cm SetupTimeOut
+are Debian-specific compatibility aliases for this option.
+.It Cm StrictHostKeyChecking
+If this flag is set to
+.Dq yes ,
+.Xr ssh 1
+will never automatically add host keys to the
+.Pa ~/.ssh/known_hosts
+file, and refuses to connect to hosts whose host key has changed.
+This provides maximum protection against trojan horse attacks,
+though it can be annoying when the
+.Pa /etc/ssh/ssh_known_hosts
+file is poorly maintained or when connections to new hosts are
+frequently made.
+This option forces the user to manually
+add all new hosts.
+If this flag is set to
+.Dq no ,
+ssh will automatically add new host keys to the
+user known hosts files.
+If this flag is set to
+.Dq ask ,
+new host keys
+will be added to the user known host files only after the user
+has confirmed that is what they really want to do, and
+ssh will refuse to connect to hosts whose host key has changed.
+The host keys of
+known hosts will be verified automatically in all cases.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq ask .
+.It Cm TCPKeepAlive
+Specifies whether the system should send TCP keepalive messages to the
+other side.
+If they are sent, death of the connection or crash of one
+of the machines will be properly noticed.
+This option only uses TCP keepalives (as opposed to using ssh level
+keepalives), so takes a long time to notice when the connection dies.
+As such, you probably want
+the
+.Cm ServerAliveInterval
+option as well.
+However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+.Pp
+The default is
+.Dq yes
+(to send TCP keepalive messages), and the client will notice
+if the network goes down or the remote host dies.
+This is important in scripts, and many users want it too.
+.Pp
+To disable TCP keepalive messages, the value should be set to
+.Dq no .
+.It Cm Tunnel
+Request
+.Xr tun 4
+device forwarding between the client and the server.
+The argument must be
+.Dq yes ,
+.Dq point-to-point
+(layer 3),
+.Dq ethernet
+(layer 2),
+or
+.Dq no .
+Specifying
+.Dq yes
+requests the default tunnel mode, which is
+.Dq point-to-point .
+The default is
+.Dq no .
+.It Cm TunnelDevice
+Specifies the
+.Xr tun 4
+devices to open on the client
+.Pq Ar local_tun
+and the server
+.Pq Ar remote_tun .
+.Pp
+The argument must be
+.Sm off
+.Ar local_tun Op : Ar remote_tun .
+.Sm on
+The devices may be specified by numerical ID or the keyword
+.Dq any ,
+which uses the next available tunnel device.
+If
+.Ar remote_tun
+is not specified, it defaults to
+.Dq any .
+The default is
+.Dq any:any .
+.It Cm UseBlacklistedKeys
+Specifies whether
+.Xr ssh 1
+should use keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 )
+for authentication.
+If
+.Dq yes ,
+then attempts to use compromised keys for authentication will be logged but
+accepted.
+It is strongly recommended that this be used only to install new authorized
+keys on the remote system, and even then only with the utmost care.
+If
+.Dq no ,
+then attempts to use compromised keys for authentication will be prevented.
+The default is
+.Dq no .
+.It Cm UsePrivilegedPort
+Specifies whether to use a privileged port for outgoing connections.
+The argument must be
+.Dq yes
+or
+.Dq no .
+The default is
+.Dq no .
+If set to
+.Dq yes ,
+.Xr ssh 1
+must be setuid root.
+Note that this option must be set to
+.Dq yes
+for
+.Cm RhostsRSAAuthentication
+with older servers.
+.It Cm User
+Specifies the user to log in as.
+This can be useful when a different user name is used on different machines.
+This saves the trouble of
+having to remember to give the user name on the command line.
+.It Cm UserKnownHostsFile
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
+.It Cm VerifyHostKeyDNS
+Specifies whether to verify the remote key using DNS and SSHFP resource
+records.
+If this option is set to
+.Dq yes ,
+the client will implicitly trust keys that match a secure fingerprint
+from DNS.
+Insecure fingerprints will be handled as if this option was set to
+.Dq ask .
+If this option is set to
+.Dq ask ,
+information on fingerprint match will be displayed, but the user will still
+need to confirm new host keys according to the
+.Cm StrictHostKeyChecking
+option.
+The argument must be
+.Dq yes ,
+.Dq no ,
+or
+.Dq ask .
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.Pp
+See also
+.Sx VERIFYING HOST KEYS
+in
+.Xr ssh 1 .
+.It Cm VisualHostKey
+If this flag is set to
+.Dq yes ,
+an ASCII art representation of the remote host key fingerprint is
+printed in addition to the hex fingerprint string at login and
+for unknown host keys.
+If this flag is set to
+.Dq no ,
+no fingerprint strings are printed at login and
+only the hex fingerprint string will be printed for unknown host keys.
+The default is
+.Dq no .
+.It Cm XAuthLocation
+Specifies the full pathname of the
+.Xr xauth 1
+program.
+The default is
+.Pa /usr/X11R6/bin/xauth .
+.El
+.Sh PATTERNS
+A
+.Em pattern
+consists of zero or more non-whitespace characters,
+.Sq *
+(a wildcard that matches zero or more characters),
+or
+.Sq ?\&
+(a wildcard that matches exactly one character).
+For example, to specify a set of declarations for any host in the
+.Dq .co.uk
+set of domains,
+the following pattern could be used:
+.Pp
+.Dl Host *.co.uk
+.Pp
+The following pattern
+would match any host in the 192.168.0.[0-9] network range:
+.Pp
+.Dl Host 192.168.0.?
+.Pp
+A
+.Em pattern-list
+is a comma-separated list of patterns.
+Patterns within pattern-lists may be negated
+by preceding them with an exclamation mark
+.Pq Sq !\& .
+For example,
+to allow a key to be used from anywhere within an organisation
+except from the
+.Dq dialup
+pool,
+the following entry (in authorized_keys) could be used:
+.Pp
+.Dl from=\&"!*.dialup.example.com,*.example.com\&"
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/config
+This is the per-user configuration file.
+The format of this file is described above.
+This file is used by the SSH client.
+Because of the potential for abuse, this file must have strict permissions:
+read/write for the user, and not accessible by others.
+.It Pa /etc/ssh/ssh_config
+Systemwide configuration file.
+This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file.
+This file must be world-readable.
+.El
+.Sh SEE ALSO
+.Xr ssh 1
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
diff --git a/ChangeLog.gssapi b/ChangeLog.gssapi
new file mode 100644 (file)
index 0000000..f117a33
--- /dev/null
@@ -0,0 +1,113 @@
+20110101
+  - Finally update for OpenSSH 5.6p1
+  - Add GSSAPIServerIdentity option from Jim Basney
+20100308
+  - [ Makefile.in, key.c, key.h ]
+    Updates for OpenSSH 5.4p1
+  - [ servconf.c ]
+    Include GSSAPI options in the sshd -T configuration dump, and flag
+    some older configuration options as being unsupported. Thanks to Colin 
+    Watson.
+  -
+
+20100124
+  - [ sshconnect2.c ]
+    Adapt to deal with additional element in Authmethod structure. Thanks to
+    Colin Watson
+
+20090615
+  - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
+      sshd.c ]
+    Fix issues identified by Greg Hudson following a code review
+       Check return value of gss_indicate_mechs
+       Protect GSSAPI calls in monitor, so they can only be used if enabled
+       Check return values of bignum functions in key exchange
+       Use BN_clear_free to clear other side's DH value
+       Make ssh_gssapi_id_kex more robust
+       Only configure kex table pointers if GSSAPI is enabled
+       Don't leak mechanism list, or gss mechanism list
+       Cast data.length before printing
+       If serverkey isn't provided, use an empty string, rather than NULL
+
+20090201
+  - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
+      ssh_config.5 sshconnet2.c ]
+    Add support for the GSSAPIClientIdentity option, which allows the user
+    to specify which GSSAPI identity to use to contact a given server
+
+20080404
+  - [ gss-serv.c ]
+    Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
+    been omitted from a previous version of this patch. Reported by Borislav
+    Stoichkov
+
+20070317
+  - [ gss-serv-krb5.c ]
+    Remove C99ism, where new_ccname was being declared in the middle of a 
+    function
+
+20061220
+  - [ servconf.c ]
+    Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and 
+    documented, behaviour. Reported by Dan Watson.
+
+20060910
+  - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
+      ssh-gss.h ]
+    add support for gss-group14-sha1 key exchange mechanisms
+  - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
+    Add GSSAPIStrictAcceptorCheck option to allow the disabling of
+    acceptor principal checking on multi-homed machines.
+    <Bugzilla #928>
+  - [ sshd_config ssh_config ]
+    Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
+    configuration files
+  - [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
+    Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
+    Limit length of error messages displayed by client
+
+20060909
+  - [ gss-genr.c gss-serv.c ]
+    move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
+    only, where they belong 
+    <Bugzilla #1225>
+
+20060829
+  - [ gss-serv-krb5.c ]
+    Fix CCAPI credentials cache name when creating KRB5CCNAME environment 
+    variable
+
+20060828
+  - [ gss-genr.c ]
+    Avoid Heimdal context freeing problem
+    <Fixed upstream 20060829>
+
+20060818
+  - [ gss-genr.c ssh-gss.h sshconnect2.c ]
+    Make sure that SPENGO is disabled 
+    <Bugzilla #1218 - Fixed upstream 20060818>
+
+20060421
+  - [ gssgenr.c, sshconnect2.c ]
+    a few type changes (signed versus unsigned, int versus size_t) to
+    fix compiler errors/warnings 
+    (from jbasney AT ncsa.uiuc.edu)
+  - [ kexgssc.c, sshconnect2.c ]
+    fix uninitialized variable warnings
+    (from jbasney AT ncsa.uiuc.edu)
+  - [ gssgenr.c ]
+    pass oid to gss_display_status (helpful when using GSSAPI mechglue)
+    (from jbasney AT ncsa.uiuc.edu)
+    <Bugzilla #1220 >
+  - [ gss-serv-krb5.c ]
+    #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
+    (from jbasney AT ncsa.uiuc.edu)
+    <Fixed upstream 20060304>
+  - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c 
+    add client-side GssapiKeyExchange option
+    (from jbasney AT ncsa.uiuc.edu)
+  - [ sshconnect2.c ]
+    add support for GssapiTrustDns option for gssapi-with-mic
+    (from jbasney AT ncsa.uiuc.edu)
+    <gssapi-with-mic support is Bugzilla #1008>
index 3be3aa6..7406aef 100644 (file)
@@ -26,6 +26,7 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
 SFTP_SERVER=$(libexecdir)/sftp-server
 SSH_KEYSIGN=$(libexecdir)/ssh-keysign
 SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
+SSH_DATADIR=$(datadir)/ssh
 PRIVSEP_PATH=@PRIVSEP_PATH@
 SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
 STRIP_OPT=@STRIP_OPT@
@@ -38,6 +39,7 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \
        -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
        -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
        -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
+       -D_PATH_SSH_DATADIR=\"$(SSH_DATADIR)\" \
 
 CC=@CC@
 LD=@LD@
@@ -59,7 +61,7 @@ LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
 EXEEXT=@EXEEXT@
 MANFMT=@MANFMT@
 
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-vulnkey$(EXEEXT)
 
 LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
        canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
@@ -70,6 +72,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
        atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
        monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
        kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
+       kexgssc.o \
        msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
        schnorr.o ssh-pkcs11.o
 
@@ -86,14 +89,14 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
        auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
        monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
        auth-krb5.o \
-       auth2-gss.o gss-serv.o gss-serv-krb5.o \
+       auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
        loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
        sftp-server.o sftp-common.o \
        roaming_common.o roaming_serv.o \
        sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
 
-MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
-MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
+MANPAGES       = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-vulnkey.1.out sshd_config.5.out ssh_config.5.out
+MANPAGES_IN    = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-vulnkey.1 sshd_config.5 ssh_config.5
 MANTYPE                = @MANTYPE@
 
 CONFIGFILES=sshd_config.out ssh_config.out moduli.out
@@ -170,6 +173,9 @@ sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o s
 sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
        $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
 
+ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o
+       $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
 # test driver for the loginrec code - not built by default
 logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
        $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
@@ -258,6 +264,7 @@ install-files:
        $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
        $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
        $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey$(EXEEXT) $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
        $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
        $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
        $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
@@ -268,14 +275,16 @@ install-files:
        $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
        $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
        $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       ln -s ../$(mansubdir)8/sshd.8 $(DESTDIR)$(mandir)/$(mansubdir)5/authorized_keys.5
        $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
        $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
        $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
        $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
        -rm -f $(DESTDIR)$(bindir)/slogin
-       ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+       ln -s ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
        -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
-       ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+       ln -s ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
 
 install-sysconf:
        if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
@@ -353,6 +362,7 @@ uninstall:
        -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
        -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
        -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
        -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
        -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
        -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
@@ -365,6 +375,7 @@ uninstall:
        -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
        -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
        -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
        -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
        -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
        -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
index d019fe2..8219133 100644 (file)
@@ -170,8 +170,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
 
        len = strlen(authctxt->krb5_ticket_file) + 6;
        authctxt->krb5_ccname = xmalloc(len);
+#ifdef USE_CCAPI
+       snprintf(authctxt->krb5_ccname, len, "API:%s",
+           authctxt->krb5_ticket_file);
+#else
        snprintf(authctxt->krb5_ccname, len, "FILE:%s",
            authctxt->krb5_ticket_file);
+#endif
 
 #ifdef USE_PAM
        if (options.use_pam)
@@ -226,15 +231,22 @@ krb5_cleanup_proc(Authctxt *authctxt)
 #ifndef HEIMDAL
 krb5_error_code
 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
-       int tmpfd, ret;
+       int ret;
        char ccname[40];
        mode_t old_umask;
+#ifdef USE_CCAPI
+       char cctemplate[] = "API:krb5cc_%d";
+#else
+       char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
+       int tmpfd;
+#endif
 
        ret = snprintf(ccname, sizeof(ccname),
-           "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
+           cctemplate, geteuid());
        if (ret < 0 || (size_t)ret >= sizeof(ccname))
                return ENOMEM;
 
+#ifndef USE_CCAPI
        old_umask = umask(0177);
        tmpfd = mkstemp(ccname + strlen("FILE:"));
        umask(old_umask);
@@ -249,6 +261,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
                return errno;
        }
        close(tmpfd);
+#endif
 
        return (krb5_cc_resolve(ctx, ccname, ccache));
 }
index eae45cf..8d1ef0a 100644 (file)
@@ -58,9 +58,20 @@ int forced_tun_device = -1;
 /* "principals=" option. */
 char *authorized_principals = NULL;
 
+/* Throttle log messages. */
+int logged_from_hostip = 0;
+int logged_cert_hostip = 0;
+
 extern ServerOptions options;
 
 void
+auth_start_parse_options(void)
+{
+       logged_from_hostip = 0;
+       logged_cert_hostip = 0;
+}
+
+void
 auth_clear_options(void)
 {
        no_agent_forwarding_flag = 0;
@@ -288,10 +299,13 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                                /* FALLTHROUGH */
                        case 0:
                                xfree(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);
+                               if (!logged_from_hostip) {
+                                       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);
+                                       logged_from_hostip = 1;
+                               }
                                auth_debug_add("Your host '%.200s' is not "
                                    "permitted to use this key for login.",
                                    remote_host);
@@ -526,11 +540,14 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
                                        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);
+                                       if (!logged_cert_hostip) {
+                                               logit("Authentication tried for %.100s "
+                                                   "with valid certificate but not "
+                                                   "from a permitted host "
+                                                   "(ip=%.200s).", pw->pw_name,
+                                                   remote_ip);
+                                               logged_cert_hostip = 1;
+                                       }
                                        auth_debug_add("Your address '%.200s' "
                                            "is not permitted to use this "
                                            "certificate for login.",
index 7455c94..a3f0a02 100644 (file)
@@ -33,6 +33,7 @@ extern int forced_tun_device;
 extern int key_is_cert_authority;
 extern char *authorized_principals;
 
+void   auth_start_parse_options(void);
 int    auth_parse_options(struct passwd *, char *, char *, u_long);
 void   auth_clear_options(void);
 int    auth_cert_options(Key *, struct passwd *);
index b21a0f4..891ec32 100644 (file)
@@ -44,7 +44,7 @@ auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
 {
        HostStatus host_status;
 
-       if (auth_key_is_revoked(client_host_key))
+       if (auth_key_is_revoked(client_host_key, 0))
                return 0;
 
        /* Check if we would accept it using rhosts authentication. */
index 06ae7f0..f202787 100644 (file)
@@ -256,8 +256,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
                return 0;
        }
        if (options.strict_modes &&
-           ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
-           (st.st_mode & 022) != 0)) {
+           !secure_permissions(&st, pw->pw_uid)) {
                logit("Rhosts authentication refused for %.100s: "
                    "bad ownership or modes for home directory.", pw->pw_name);
                auth_debug_add("Rhosts authentication refused for %.100s: "
@@ -283,8 +282,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
                 * allowing access to their account by anyone.
                 */
                if (options.strict_modes &&
-                   ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
-                   (st.st_mode & 022) != 0)) {
+                   !secure_permissions(&st, pw->pw_uid)) {
                        logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
                            pw->pw_name, buf);
                        auth_debug_add("Bad file modes for %.200s", buf);
index 4ab46cd..99c4e88 100644 (file)
@@ -175,6 +175,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file,
        if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
                return 0;
 
+       auth_start_parse_options();
+
        /*
         * Go though the accepted keys, looking for the current key.  If
         * found, perform a challenge-response dialog to verify that the
@@ -233,7 +235,7 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file,
                            file, linenum, BN_num_bits(key->rsa->n), bits);
 
                /* Never accept a revoked key */
-               if (auth_key_is_revoked(key))
+               if (auth_key_is_revoked(key, 0))
                        break;
 
                /* We have found the desired key. */
diff --git a/auth.c b/auth.c
index cd95da9..3e8fe57 100644 (file)
--- a/auth.c
+++ b/auth.c
@@ -59,6 +59,7 @@
 #include "servconf.h"
 #include "key.h"
 #include "hostfile.h"
+#include "authfile.h"
 #include "auth.h"
 #include "auth-options.h"
 #include "canohost.h"
@@ -379,8 +380,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
                user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
                if (options.strict_modes &&
                    (stat(user_hostfile, &st) == 0) &&
-                   ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
-                   (st.st_mode & 022) != 0)) {
+                   !secure_permissions(&st, pw->pw_uid)) {
                        logit("Authentication refused for %.100s: "
                            "bad owner or modes for %.200s",
                            pw->pw_name, user_hostfile);
@@ -441,8 +441,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
 
        /* check the open file to avoid races */
        if (fstat(fileno(f), &st) < 0 ||
-           (st.st_uid != 0 && st.st_uid != uid) ||
-           (st.st_mode & 022) != 0) {
+           !secure_permissions(&st, uid)) {
                snprintf(err, errlen, "bad ownership or modes for file %s",
                    buf);
                return -1;
@@ -457,8 +456,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
                strlcpy(buf, cp, sizeof(buf));
 
                if (stat(buf, &st) < 0 ||
-                   (st.st_uid != 0 && st.st_uid != uid) ||
-                   (st.st_mode & 022) != 0) {
+                   !secure_permissions(&st, uid)) {
                        snprintf(err, errlen,
                            "bad ownership or modes for directory %s", buf);
                        return -1;
@@ -606,10 +604,34 @@ getpwnamallow(const char *user)
 
 /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
 int
-auth_key_is_revoked(Key *key)
+auth_key_is_revoked(Key *key, int hostkey)
 {
        char *key_fp;
 
+       if (blacklisted_key(key, &key_fp) == 1) {
+               if (options.permit_blacklisted_keys) {
+                       if (hostkey)
+                               error("Host key %s blacklisted (see "
+                                   "ssh-vulnkey(1)); continuing anyway",
+                                   key_fp);
+                       else
+                               logit("Public key %s from %s blacklisted (see "
+                                   "ssh-vulnkey(1)); continuing anyway",
+                                   key_fp, get_remote_ipaddr());
+                       xfree(key_fp);
+               } else {
+                       if (hostkey)
+                               error("Host key %s blacklisted (see "
+                                   "ssh-vulnkey(1))", key_fp);
+                       else
+                               logit("Public key %s from %s blacklisted (see "
+                                   "ssh-vulnkey(1))",
+                                   key_fp, get_remote_ipaddr());
+                       xfree(key_fp);
+                       return 1;
+               }
+       }
+
        if (options.revoked_keys_file == NULL)
                return 0;
 
diff --git a/auth.h b/auth.h
index 0d786c4..568212f 100644 (file)
--- a/auth.h
+++ b/auth.h
@@ -59,6 +59,7 @@ struct Authctxt {
        char            *service;
        struct passwd   *pw;            /* set if 'valid' */
        char            *style;
+       char            *role;
        void            *kbdintctxt;
        void            *jpake_ctx;
 #ifdef BSD_AUTH
@@ -173,7 +174,7 @@ char        *authorized_principals_file(struct passwd *);
 
 FILE   *auth_openkeyfile(const char *, struct passwd *, int);
 FILE   *auth_openprincipals(const char *, struct passwd *, int);
-int     auth_key_is_revoked(Key *);
+int     auth_key_is_revoked(Key *, int);
 
 HostStatus
 check_key_in_hostfiles(struct passwd *, Key *, const char *,
diff --git a/auth1.c b/auth1.c
index cc85aec..9079b73 100644 (file)
--- a/auth1.c
+++ b/auth1.c
@@ -383,7 +383,7 @@ void
 do_authentication(Authctxt *authctxt)
 {
        u_int ulen;
-       char *user, *style = NULL;
+       char *user, *style = NULL, *role = NULL;
 
        /* Get the name of the user that we wish to log in as. */
        packet_read_expect(SSH_CMSG_USER);
@@ -392,11 +392,17 @@ do_authentication(Authctxt *authctxt)
        user = packet_get_cstring(&ulen);
        packet_check_eom();
 
+       if ((role = strchr(user, '/')) != NULL)
+               *role++ = '\0';
+
        if ((style = strchr(user, ':')) != NULL)
                *style++ = '\0';
+       else if (role && (style = strchr(role, ':')) != NULL)
+               *style++ = '\0';
 
        authctxt->user = user;
        authctxt->style = style;
+       authctxt->role = role;
 
        /* Verify that the user is a valid user. */
        if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
index 0d59b21..7dc87db 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_errtok(int, u_int32_t, void *);
 
+/* 
+ * The 'gssapi_keyex' userauth mechanism.
+ */
+static int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+       int authenticated = 0;
+       Buffer b;
+       gss_buffer_desc mic, gssbuf;
+       u_int len;
+
+       mic.value = packet_get_string(&len);
+       mic.length = len;
+
+       packet_check_eom();
+
+       ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
+           "gssapi-keyex");
+
+       gssbuf.value = buffer_ptr(&b);
+       gssbuf.length = buffer_len(&b);
+
+       /* gss_kex_context is NULL with privsep, so we can't check it here */
+       if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
+           &gssbuf, &mic))))
+               authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+                   authctxt->pw));
+       
+       buffer_free(&b);
+       xfree(mic.value);
+
+       return (authenticated);
+}
+
 /*
  * We only support those mechanisms that we know about (ie ones that we know
  * how to check local user kuserok and the like)
@@ -244,7 +278,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
 
        packet_check_eom();
 
-       authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+       authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+           authctxt->pw));
 
        authctxt->postponed = 0;
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
@@ -279,7 +314,8 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
        gssbuf.length = buffer_len(&b);
 
        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
-               authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+               authenticated = 
+                   PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
        else
                logit("GSSAPI MIC check failed");
 
@@ -294,6 +330,12 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
        userauth_finish(authctxt, authenticated, "gssapi-with-mic");
 }
 
+Authmethod method_gsskeyex = {
+       "gssapi-keyex",
+       userauth_gsskeyex,
+       &options.gss_authentication
+};
+
 Authmethod method_gssapi = {
        "gssapi-with-mic",
        userauth_gssapi,
index cdf442f..7006315 100644 (file)
@@ -146,7 +146,7 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
        int len;
        char *fp;
 
-       if (auth_key_is_revoked(key))
+       if (auth_key_is_revoked(key, 0))
                return 0;
 
        resolvedname = get_canonical_hostname(options.use_dns);
index 137887e..a1d31e9 100644 (file)
@@ -211,6 +211,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
                restore_uid();
                return 0;
        }
+       auth_start_parse_options();
        while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
                /* Skip leading whitespace. */
                for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
@@ -280,6 +281,8 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
        found_key = 0;
        found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
 
+       auth_start_parse_options();
+
        while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
                char *cp, *key_options = NULL;
 
@@ -416,6 +419,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
        if (key_cert_check_authority(key, 0, 1,
            principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
                goto fail_reason;
+       auth_start_parse_options();
        if (auth_cert_options(key, pw) != 0)
                goto out;
 
@@ -439,9 +443,10 @@ user_key_allowed(struct passwd *pw, Key *key)
        u_int success, i;
        char *file;
 
-       if (auth_key_is_revoked(key))
+       if (auth_key_is_revoked(key, 0))
                return 0;
-       if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+       if (key_is_cert(key) &&
+           auth_key_is_revoked(key->cert->signature_key, 0))
                return 0;
 
        success = user_cert_trusted_ca(pw, key);
diff --git a/auth2.c b/auth2.c
index c06c95f..52acf46 100644 (file)
--- a/auth2.c
+++ b/auth2.c
@@ -69,6 +69,7 @@ extern Authmethod method_passwd;
 extern Authmethod method_kbdint;
 extern Authmethod method_hostbased;
 #ifdef GSSAPI
+extern Authmethod method_gsskeyex;
 extern Authmethod method_gssapi;
 #endif
 #ifdef JPAKE
@@ -79,6 +80,7 @@ Authmethod *authmethods[] = {
        &method_none,
        &method_pubkey,
 #ifdef GSSAPI
+       &method_gsskeyex,
        &method_gssapi,
 #endif
 #ifdef JPAKE
@@ -215,7 +217,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
 {
        Authctxt *authctxt = ctxt;
        Authmethod *m = NULL;
-       char *user, *service, *method, *style = NULL;
+       char *user, *service, *method, *style = NULL, *role = NULL;
        int authenticated = 0;
 
        if (authctxt == NULL)
@@ -227,8 +229,13 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
        debug("userauth-request for user %s service %s method %s", user, service, method);
        debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
 
+       if ((role = strchr(user, '/')) != NULL)
+               *role++ = 0;
+
        if ((style = strchr(user, ':')) != NULL)
                *style++ = 0;
+       else if (role && (style = strchr(role, ':')) != NULL)
+               *style++ = '\0';
 
        if (authctxt->attempt++ == 0) {
                /* setup auth context */
@@ -252,8 +259,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
                    use_privsep ? " [net]" : "");
                authctxt->service = xstrdup(service);
                authctxt->style = style ? xstrdup(style) : NULL;
+               authctxt->role = role ? xstrdup(role) : NULL;
                if (use_privsep)
-                       mm_inform_authserv(service, style);
+                       mm_inform_authserv(service, style, role);
                userauth_banner();
        } else if (strcmp(user, authctxt->user) != 0 ||
            strcmp(service, authctxt->service) != 0) {
index 1d7e53c..e5fe0b8 100644 (file)
@@ -68,6 +68,7 @@
 #include "rsa.h"
 #include "misc.h"
 #include "atomicio.h"
+#include "pathnames.h"
 
 #define MAX_KEY_FILE_SIZE      (1024 * 1024)
 
@@ -944,3 +945,140 @@ key_in_file(Key *key, const char *filename, int strict_type)
        return ret;
 }
 
+/* Scan a blacklist of known-vulnerable keys in blacklist_file. */
+static int
+blacklisted_key_in_file(Key *key, const char *blacklist_file, char **fp)
+{
+       int fd = -1;
+       char *dgst_hex = NULL;
+       char *dgst_packed = NULL, *p;
+       int i;
+       size_t line_len;
+       struct stat st;
+       char buf[256];
+       off_t start, lower, upper;
+       int ret = 0;
+
+       debug("Checking blacklist file %s", blacklist_file);
+       fd = open(blacklist_file, O_RDONLY);
+       if (fd < 0) {
+               ret = -1;
+               goto out;
+       }
+
+       dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+       /* Remove all colons */
+       dgst_packed = xcalloc(1, strlen(dgst_hex) + 1);
+       for (i = 0, p = dgst_packed; dgst_hex[i]; i++)
+               if (dgst_hex[i] != ':')
+                       *p++ = dgst_hex[i];
+       /* Only compare least-significant 80 bits (to keep the blacklist
+        * size down)
+        */
+       line_len = strlen(dgst_packed + 12);
+       if (line_len > 32)
+               goto out;
+
+       /* Skip leading comments */
+       start = 0;
+       for (;;) {
+               ssize_t r;
+               char *newline;
+
+               r = atomicio(read, fd, buf, sizeof(buf));
+               if (r <= 0)
+                       goto out;
+               if (buf[0] != '#')
+                       break;
+
+               newline = memchr(buf, '\n', sizeof(buf));
+               if (!newline)
+                       goto out;
+               start += newline + 1 - buf;
+               if (lseek(fd, start, SEEK_SET) < 0)
+                       goto out;
+       }
+
+       /* Initialise binary search record numbers */
+       if (fstat(fd, &st) < 0)
+               goto out;
+       lower = 0;
+       upper = (st.st_size - start) / (line_len + 1);
+
+       while (lower != upper) {
+               off_t cur;
+               int cmp;
+
+               cur = lower + (upper - lower) / 2;
+
+               /* Read this line and compare to digest; this is
+                * overflow-safe since cur < max(off_t) / (line_len + 1) */
+               if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
+                       break;
+               if (atomicio(read, fd, buf, line_len) != line_len)
+                       break;
+               cmp = memcmp(buf, dgst_packed + 12, line_len);
+               if (cmp < 0) {
+                       if (cur == lower)
+                               break;
+                       lower = cur;
+               } else if (cmp > 0) {
+                       if (cur == upper)
+                               break;
+                       upper = cur;
+               } else {
+                       debug("Found %s in blacklist", dgst_hex);
+                       ret = 1;
+                       break;
+               }
+       }
+
+out:
+       if (dgst_packed)
+               xfree(dgst_packed);
+       if (ret != 1 && dgst_hex) {
+               xfree(dgst_hex);
+               dgst_hex = NULL;
+       }
+       if (fp)
+               *fp = dgst_hex;
+       if (fd >= 0)
+               close(fd);
+       return ret;
+}
+
+/*
+ * Scan blacklists of known-vulnerable keys. If a vulnerable key is found,
+ * its fingerprint is returned in *fp, unless fp is NULL.
+ */
+int
+blacklisted_key(Key *key, char **fp)
+{
+       Key *public;
+       char *blacklist_file;
+       int ret, ret2;
+
+       public = key_demote(key);
+       if (public->type == KEY_RSA1)
+               public->type = KEY_RSA;
+
+       xasprintf(&blacklist_file, "%s.%s-%u",
+           _PATH_BLACKLIST, key_type(public), key_size(public));
+       ret = blacklisted_key_in_file(public, blacklist_file, fp);
+       xfree(blacklist_file);
+       if (ret > 0) {
+               key_free(public);
+               return ret;
+       }
+
+       xasprintf(&blacklist_file, "%s.%s-%u",
+           _PATH_BLACKLIST_CONFIG, key_type(public), key_size(public));
+       ret2 = blacklisted_key_in_file(public, blacklist_file, fp);
+       xfree(blacklist_file);
+       if (ret2 > ret)
+               ret = ret2;
+
+       key_free(public);
+       return ret;
+}
+
index 78349be..3f2bdcb 100644 (file)
@@ -28,4 +28,6 @@ Key   *key_load_private_pem(int, int, const char *, char **);
 int     key_perm_ok(int, const char *);
 int     key_in_file(Key *, const char *, int);
 
+int     blacklisted_key(Key *key, char **fp);
+
 #endif
index c19b01f..18a85c5 100644 (file)
 #include "msg.h"
 #include "roaming.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* import options */
 extern Options options;
 
@@ -541,16 +545,21 @@ client_global_request_reply(int type, u_int32_t seq, void *ctxt)
 static void
 server_alive_check(void)
 {
-       if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
-               logit("Timeout, server %s not responding.", host);
-               cleanup_exit(255);
+       if (compat20) {
+               if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
+                       logit("Timeout, server %s not responding.", host);
+                       cleanup_exit(255);
+               }
+               packet_start(SSH2_MSG_GLOBAL_REQUEST);
+               packet_put_cstring("keepalive@openssh.com");
+               packet_put_char(1);     /* boolean: want reply */
+               packet_send();
+               /* Insert an empty placeholder to maintain ordering */
+               client_register_global_confirm(NULL, NULL);
+       } else {
+               packet_send_ignore(0);
+               packet_send();
        }
-       packet_start(SSH2_MSG_GLOBAL_REQUEST);
-       packet_put_cstring("keepalive@openssh.com");
-       packet_put_char(1);     /* boolean: want reply */
-       packet_send();
-       /* Insert an empty placeholder to maintain ordering */
-       client_register_global_confirm(NULL, NULL);
 }
 
 /*
@@ -610,7 +619,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
         */
 
        timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
-       if (options.server_alive_interval > 0 && compat20)
+       if (options.server_alive_interval > 0)
                timeout_secs = options.server_alive_interval;
        set_control_persist_exit_time();
        if (control_persist_exit_time > 0) {
@@ -1508,6 +1517,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
                /* Do channel operations unless rekeying in progress. */
                if (!rekeying) {
                        channel_after_select(readset, writeset);
+
+#ifdef GSSAPI
+                       if (options.gss_renewal_rekey &&
+                           ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) {
+                               debug("credentials updated - forcing rekey");
+                               need_rekeying = 1;
+                       }
+#endif
+
                        if (need_rekeying || packet_need_rekeying()) {
                                debug("need rekeying");
                                xxx_kex->done = 0;
@@ -1601,8 +1619,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
                exit_status = 0;
        }
 
-       if (received_signal)
-               fatal("Killed by signal %d.", (int) received_signal);
+       if (received_signal) {
+               debug("Killed by signal %d.", (int) received_signal);
+               cleanup_exit((int) received_signal + 128);
+       }
 
        /*
         * In interactive mode (with pseudo tty) display a message indicating
index baf0011..ff651cc 100644 (file)
 /* Use btmp to log bad logins */
 #undef USE_BTMP
 
+/* platform uses an in-memory credentials cache */
+#undef USE_CCAPI
+
 /* Use libedit for sftp */
 #undef USE_LIBEDIT
 
 /* Use PIPES instead of a socketpair() */
 #undef USE_PIPES
 
+/* platform has the Security Authorization Session API */
+#undef USE_SECURITY_SESSION_API
+
 /* Define if you have Solaris process contracts */
 #undef USE_SOLARIS_PROCESS_CONTRACTS
 
index 43c4372..c15fdc3 100755 (executable)
--- a/configure
+++ b/configure
@@ -6521,6 +6521,63 @@ $as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h
 
 $as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
 
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have the Security Authorization Session API" >&5
+$as_echo_n "checking if we have the Security Authorization Session API... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <Security/AuthSession.h>
+int
+main ()
+{
+SessionCreate(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_use_security_session_api="yes"
+
+$as_echo "#define USE_SECURITY_SESSION_API 1" >>confdefs.h
+
+                LIBS="$LIBS -framework Security"
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  ac_cv_use_security_session_api="no"
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have an in-memory credentials cache" >&5
+$as_echo_n "checking if we have an in-memory credentials cache... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <Kerberos/Kerberos.h>
+int
+main ()
+{
+cc_context_t c;
+                (void) cc_initialize (&c, 0, NULL, NULL);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define USE_CCAPI 1" >>confdefs.h
+
+                LIBS="$LIBS -framework Security"
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+                if test "x$ac_cv_use_security_session_api" = "xno"; then
+                       as_fn_error $? "*** Need a security framework to use the credentials cache API ***" "$LINENO" 5
+               fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
        ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default"
 if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then :
index 7a91527..58da1f1 100644 (file)
@@ -515,6 +515,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
            [Use tunnel device compatibility to OpenBSD])
        AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
            [Prepend the address family to IP tunnel traffic])
+       AC_MSG_CHECKING([if we have the Security Authorization Session API])
+       AC_TRY_COMPILE([#include <Security/AuthSession.h>],
+               [SessionCreate(0, 0);],
+               [ac_cv_use_security_session_api="yes"
+                AC_DEFINE([USE_SECURITY_SESSION_API], [1], 
+                       [platform has the Security Authorization Session API])
+                LIBS="$LIBS -framework Security"
+                AC_MSG_RESULT([yes])],
+               [ac_cv_use_security_session_api="no"
+                AC_MSG_RESULT([no])])
+       AC_MSG_CHECKING([if we have an in-memory credentials cache])
+       AC_TRY_COMPILE(
+               [#include <Kerberos/Kerberos.h>],
+               [cc_context_t c;
+                (void) cc_initialize (&c, 0, NULL, NULL);],
+               [AC_DEFINE([USE_CCAPI], [1], 
+                       [platform uses an in-memory credentials cache])
+                LIBS="$LIBS -framework Security"
+                AC_MSG_RESULT([yes])
+                if test "x$ac_cv_use_security_session_api" = "xno"; then
+                       AC_MSG_ERROR([*** Need a security framework to use the credentials cache API ***])
+               fi],
+               [AC_MSG_RESULT([no])]
+       )
        m4_pattern_allow([AU_IPv])
        AC_CHECK_DECL([AU_IPv4], [], 
            AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
index 9d97c30..04b3a11 100644 (file)
@@ -209,6 +209,8 @@ main(int argc, char **argv)
 
        gtk_init(&argc, &argv);
 
+       gtk_window_set_default_icon_from_file ("/usr/share/pixmaps/ssh-askpass-gnome.png", NULL);
+
        if (argc > 1) {
                message = g_strjoinv(" ", argv + 1);
        } else {
diff --git a/debian/NEWS b/debian/NEWS
new file mode 100644 (file)
index 0000000..7a67e15
--- /dev/null
@@ -0,0 +1,42 @@
+openssh (1:5.4p1-2) unstable; urgency=low
+
+  Smartcard support is now available using PKCS#11 tokens.  If you were
+  previously using an unofficial build of Debian's OpenSSH package with
+  OpenSC-based smartcard support added, then note that commands like
+  'ssh-add -s 0' will no longer work; you need to use 'ssh-add -s
+  /usr/lib/opensc-pkcs11.so' instead.
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 10 Apr 2010 01:08:59 +0100
+
+openssh (1:3.8.1p1-9) experimental; urgency=low
+
+  The ssh package has been split into openssh-client and openssh-server. If
+  you had previously requested that the sshd server should not be run, then
+  that request will still be honoured. However, the recommended approach is
+  now to remove the openssh-server package if you do not want to run sshd.
+  You can remove the old /etc/ssh/sshd_not_to_be_run marker file after doing
+  that.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  2 Aug 2004 20:48:54 +0100
+
+openssh (1:3.5p1-1) unstable; urgency=low
+
+  This version of OpenSSH disables the environment option for public keys by
+  default, in order to avoid certain attacks (for example, LD_PRELOAD). If
+  you are using this option in an authorized_keys file, beware that the keys
+  in question will no longer work until the option is removed.
+
+  To re-enable this option, set "PermitUserEnvironment yes" in
+  /etc/ssh/sshd_config after the upgrade is complete, taking note of the
+  warning in the sshd_config(5) manual page.
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 26 Oct 2002 19:41:51 +0100
+
+openssh (1:3.0.1p1-1) unstable; urgency=high
+
+  As of version 3, OpenSSH no longer uses separate files for ssh1 and ssh2
+  keys. This means the authorized_keys2 and known_hosts2 files are no longer
+  needed. They will still be read in order to maintain backward
+  compatibility.
+
+ -- Matthew Vernon <matthew@debian.org>  Thu, 28 Nov 2001 17:43:01 +0000
diff --git a/debian/README.Debian b/debian/README.Debian
new file mode 100644 (file)
index 0000000..f37cce4
--- /dev/null
@@ -0,0 +1,234 @@
+OpenSSH for Debian
+------------------
+
+UPGRADE ISSUES
+==============
+
+Privilege Separation
+--------------------
+
+As of 3.3, openssh has employed privilege separation to reduce the
+quantity of code that runs as root, thereby reducing the impact of
+some security holes in sshd. This now also works properly with PAM.
+
+Privilege separation is turned on by default, so, if you decide you
+want it turned off, you need to add "UsePrivilegeSeparation no" to
+/etc/ssh/sshd_config.
+
+PermitRootLogin set to yes
+--------------------------
+
+This is now the default setting (in line with upstream), and people
+who asked for an automatically-generated configuration file when
+upgrading from potato (or on a new install) will have this setting in
+their /etc/ssh/sshd_config file.
+
+Should you wish to change this setting, edit /etc/ssh/sshd_config, and
+change:
+PermitRootLogin yes
+to:
+PermitRootLogin no
+
+Having PermitRootLogin set to yes means that an attacker that knows
+the root password can ssh in directly (without having to go via a user
+account). If you set it to no, then they must compromise a normal user
+account. In the vast majority of cases, this does not give added
+security; remember that any account you su to root from is equivalent
+to root - compromising this account gives an attacker access to root
+easily. If you only ever log in as root from the physical console,
+then you probably want to set this value to no.
+
+As an aside, PermitRootLogin can also be set to "without-password" or
+"forced-commands-only" - see sshd(8) for more details.
+
+DO NOT FILE BUG REPORTS SAYING YOU THINK THIS DEFAULT IS INCORRECT!
+
+The argument above is somewhat condensed; I have had this discussion
+at great length with many people. If you think the default is
+incorrect, and feel strongly enough to want to argue about it, then
+send email to debian-ssh@lists.debian.org. I will close bug reports
+claiming the default is incorrect.
+
+SSH now uses protocol 2 by default
+----------------------------------
+
+This means all your keyfiles you used for protocol version 1 need to
+be re-generated. The server keys are done automatically, but for RSA
+authentication, please read the ssh-keygen manpage.
+
+If you have an automatically generated configuration file, and decide
+at a later stage that you do want to support protocol version 1 (not
+recommended, but note that the ssh client shipped with Debian potato
+only supported protocol version 1), then you need to do the following:
+
+Change /etc/ssh/sshd_config such that:
+Protocol 2
+becomes:
+Protocol 2,1
+Also add the line:
+HostKey /etc/ssh/ssh_host_key
+
+If you do not already have an RSA1 host key in /etc/ssh/ssh_host_key,
+you will need to generate one. To do so, run this command as root:
+
+  ssh-keygen -f /etc/ssh/ssh_host_key -N '' -t rsa1
+
+As of openssh-server 1:4.1p1-2, the option to support protocol version 1
+is no longer available via debconf. You must edit the configuration file
+instead.
+
+X11 Forwarding
+--------------
+
+ssh's default for ForwardX11 has been changed to ``no'' because it has
+been pointed out that logging into remote systems administered by
+untrusted people is likely to open you up to X11 attacks, so you
+should have to actively decide that you trust the remote machine's
+root, before enabling X11.  I strongly recommend that you do this on a
+machine-by-machine basis, rather than just enabling it in the default
+host settings.
+
+In order for X11 forwarding to work, you need to install xauth on the
+server. In Debian this is in the xbase-clients package.
+
+As of OpenSSH 3.1, the remote $DISPLAY uses localhost by default to reduce
+the security risks of X11 forwarding. Look up X11UseLocalhost in
+sshd_config(8) if this is a problem.
+
+OpenSSH 3.8 invented ForwardX11Trusted, which when set to no causes the
+ssh client to create an untrusted X cookie so that attacks on the
+forwarded X11 connection can't become attacks on X clients on the remote
+machine. However, this has some problems in implementation - notably a
+very short timeout of the untrusted cookie - breaks large numbers of
+existing setups, and generally seems immature. The Debian package
+therefore sets the default for this option to "yes" (in ssh itself,
+rather than in ssh_config).
+
+Fallback to RSH
+---------------
+
+The default for this setting has been changed from Yes to No, for
+security reasons, and to stop the delay attempting to rsh to machines
+that don't offer the service.  Simply switch it back on in either
+/etc/ssh/ssh_config or ~/.ssh/config for those machines that you need
+it for.
+
+Setgid ssh-agent and environment variables
+------------------------------------------
+
+As of version 1:3.5p1-1, ssh-agent is installed setgid to prevent ptrace()
+attacks retrieving private key material. This has the side-effect of causing
+glibc to remove certain environment variables which might have security
+implications for set-id programs, including LD_PRELOAD, LD_LIBRARY_PATH, and
+TMPDIR.
+
+If you need to set any of these environment variables, you will need to do
+so in the program exec()ed by ssh-agent. This may involve creating a small
+wrapper script.
+
+Symlink Hostname invocation
+---------------------------
+
+This version of ssh no longer includes support for invoking ssh with the
+hostname as the name of the file run.  People wanting this support should
+use the ssh-argv0 script.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+OTHER ISSUES
+============
+
+/usr/bin/ssh not SUID
+---------------------
+
+Due to Debian bug #164325, RhostsRSAAuthentication can only be used if ssh
+is SUID.  Until this is fixed, if that is a problem, use:
+
+   dpkg-statoverride
+
+or if that's also missing, use this:
+
+   chown root.root /usr/bin/ssh
+   chmod 04755 /usr/bin/ssh
+
+Authorization Forwarding
+------------------------
+
+Similarly, root on a remote server could make use of your ssh-agent
+(while you're logged into their machine) to obtain access to machines
+which trust your keys.  This feature is therefore disabled by default.
+You should only re-enable it for those hosts (in your ~/.ssh/config or
+/etc/ssh/ssh_config) where you are confident that the remote machine
+is not a threat.
+
+Problems logging in with RSA authentication
+-------------------------------------------
+
+If you have trouble logging in with RSA authentication then the
+problem is probably caused by the fact that you have your home
+directory writable by group, as well as user (this is the default on
+Debian systems).
+
+Depending upon other settings on your system (i.e. other users being
+in your group) this could open a security hole, so you will need to
+make your home directory writable only by yourself.  Run this command,
+as yourself:
+
+  chmod g-w ~/
+
+to remove group write permissions.  If you use ssh-copy-id to install your
+keys, it does this for you.
+
+-L option of ssh nonfree
+------------------------
+
+non-free ssh supported the usage of the option -L to use a non privileged
+port for scp. This option will not be supported by scp from openssh.
+
+Please use instead scp -o "UsePrivilegedPort=no" as documented in the
+manpage to scp itself.
+
+Problem logging in because of TCP-Wrappers
+------------------------------------------
+
+ssh is compiled with support for tcp-wrappers. So if you can no longer
+log into your system, please check that /etc/hosts.allow and /etc/hosts.deny
+are configured so that ssh is not blocked.
+
+Kerberos support
+----------------
+
+ssh is now compiled with Kerberos support. Unfortunately, privilege
+separation is incompatible with Kerberos support for SSH protocol 1 and
+parts of the support for protocol 2; you may need to run kinit after logging
+in.
+
+Interoperability between scp and the ssh.com SSH server
+-------------------------------------------------------
+
+In version 2 and greater of the commercial SSH server produced by SSH
+Communications Security, scp was changed to use SFTP (SSH2's file transfer
+protocol) instead of the traditional rcp-over-ssh, thereby breaking
+compatibility. The OpenSSH developers regard this as a bug in the ssh.com
+server, and do not currently intend to change OpenSSH's scp to match.
+
+Workarounds for this problem are to install scp1 on the server (scp2 will
+fall back to it), to use sftp, or to use some other transfer mechanism such
+as rsync-over-ssh or tar-over-ssh.
+
+Running sshd from inittab
+-------------------------
+
+Some people find it useful to run the sshd server from inittab, to make sure
+that it always stays running. To do this, stop sshd ('/etc/init.d/ssh
+stop'), add the following line to /etc/inittab, and run 'telinit q':
+
+  ss:2345:respawn:/usr/sbin/sshd -D
+
+If you do this, note that you will need to stop sshd being started in the
+normal way ('rm -f /etc/rc[2345].d/S16ssh') and that you will need to
+restart this sshd manually on upgrades.
+
+-- 
+Matthew Vernon <matthew@debian.org>
+Colin Watson <cjwatson@debian.org>
diff --git a/debian/README.compromised-keys b/debian/README.compromised-keys
new file mode 100644 (file)
index 0000000..7a9cb76
--- /dev/null
@@ -0,0 +1,167 @@
+The following instructions relate to CVE-2008-0166. They were prepared by
+Matt Zimmerman, assisted by Colin Watson.
+
+== What Happened ==
+
+A weakness has been discovered in the random number generator used by OpenSSL
+on Debian and Ubuntu systems.  As a result of this weakness, certain encryption
+keys are much more common than they should be, such that an attacker could
+guess the key through a brute-force attack given minimal knowledge of the
+system.  This particularly affects the use of encryption keys in OpenSSH,
+OpenVPN and SSL certificates.
+
+This vulnerability only affects operating systems which (like Ubuntu) are based
+on Debian.  However, other systems can be indirectly affected if weak keys are
+imported into them.
+
+We consider this an extremely serious vulnerability, and urge all users to act
+immediately to secure their systems.
+
+== Who is affected ==
+
+Systems which are running any of the following releases:
+
+ * Debian 4.0 (etch)
+ * Ubuntu 7.04 (Feisty)
+ * Ubuntu 7.10 (Gutsy)
+ * Ubuntu 8.04 LTS (Hardy)
+ * Ubuntu "Intrepid Ibex" (development): libssl <= 0.9.8g-8
+
+and have openssh-server installed or have been used to create an OpenSSH key or
+X.509 (SSL) certificate.
+
+All OpenSSH and X.509 keys generated on such systems must be considered
+untrustworthy, regardless of the system on which they are used, even after the
+update has been applied.
+
+This includes the automatically generated host keys used by OpenSSH, which are
+the basis for its server spoofing and man-in-the-middle protection.
+
+The specific package versions affected are:
+
+ * Debian 4.0: libssl <= 0.9.8c-4etch3
+ * Ubuntu 7.04: libssl <= 0.9.8c-4ubuntu0.2
+ * Ubuntu 7.10: libssl <= 0.9.8e-5ubuntu3.1
+ * Ubuntu 8.04: libssl <= 0.9.8g-4ubuntu3
+
+== What to do if you are affected ==
+
+OpenSSH:
+
+1. Install the security updates
+
+   Once the update is applied, weak user keys will be automatically rejected
+   where possible (though they cannot be detected in all cases).  If you are
+   using such keys for user authentication, they will immediately stop working
+   and will need to be replaced (see step 3).
+   
+   OpenSSH host keys can be automatically regenerated when the OpenSSH security
+   update is applied.  The update will prompt for confirmation before taking
+   this step.
+   
+2. Update OpenSSH known_hosts files
+
+   The regeneration of host keys will cause a warning to be displayed when
+   connecting to the system using SSH until the host key is updated in the
+   known_hosts file.  The warning will look like this:
+
+   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+   @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
+   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+   IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
+   Someone could be eavesdropping on you right now (man-in-the-middle attack)!
+   It is also possible that the RSA host key has just been changed.
+
+   In this case, the host key has simply been changed, and you should update
+   the relevant known_hosts file as indicated in the error message.
+
+3. Check all OpenSSH user keys
+
+   The safest course of action is to regenerate all OpenSSH user keys,
+   except where it can be established to a high degree of certainty that the
+   key was generated on an unaffected system.
+
+   Check whether your key is affected by running the ssh-vulnkey tool, included
+   in the security update.  By default, ssh-vulnkey will check the standard
+   location for user keys (~/.ssh/id_rsa, ~/.ssh/id_dsa and ~/.ssh/identity),
+   your authorized_keys file (~/.ssh/authorized_keys and
+   ~/.ssh/authorized_keys2), and the system's host keys
+   (/etc/ssh/ssh_host_dsa_key and /etc/ssh/ssh_host_rsa_key).
+
+   To check all your own keys, assuming they are in the standard
+   locations (~/.ssh/id_rsa, ~/.ssh/id_dsa, or ~/.ssh/identity):
+
+     ssh-vulnkey
+
+   To check all keys on your system:
+
+     sudo ssh-vulnkey -a
+
+   To check a key in a non-standard location:
+
+     ssh-vulnkey /path/to/key
+
+   If ssh-vulnkey says "Unknown (no blacklist information)", then it has no
+   information about whether that key is affected.  If in doubt, destroy the
+   key and generate a new one.
+
+4. Regenerate any affected user keys
+
+   OpenSSH keys used for user authentication must be manually regenerated,
+   including those which may have since been transferred to a different system
+   after being generated.
+
+   New keys can be generated using ssh-keygen, e.g.:
+
+   $ ssh-keygen 
+   Generating public/private rsa key pair.
+   Enter file in which to save the key (/home/user/.ssh/id_rsa): 
+   Enter passphrase (empty for no passphrase): 
+   Enter same passphrase again: 
+   Your identification has been saved in /home/user/.ssh/id_rsa.
+   Your public key has been saved in /home/user/.ssh/id_rsa.pub.
+   The key fingerprint is:
+   00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 user@host
+
+5. Update authorized_keys files (if necessary)
+
+   Once the user keys have been regenerated, the relevant public keys must
+   be propagated to any authorized_keys files on remote systems.  Be sure to
+   delete the affected key.
+
+OpenSSL:
+
+1. Install the security update
+
+2. Create new certificates to replace any server or client certificates in use
+   on the system
+
+3. If certificates have been generated for use on other systems, they must be
+   found and replaced as well.
+
+== Removing openssh-blacklist ==
+
+For the moment, the openssh-server package depends on openssh-blacklist, in
+order that the blacklist is deployed to the maximum possible number of
+systems to reduce the potential spread of worms exploiting this
+vulnerability. We acknowledge that this may be inconvenient for some small
+systems, but nevertheless feel that this was the best course of action.
+
+If you absolutely need to remove the blacklist from your system, then you
+can run the following commands to substitute a fake package for
+openssh-blacklist:
+
+  sudo apt-get install equivs
+  equivs-control openssh-blacklist.ctl
+  sed -i 's/^Package:.*/Package: openssh-blacklist/' openssh-blacklist.ctl
+  sed -i 's/^# Version:.*/Version: 9:1.0/' openssh-blacklist.ctl
+  equivs-build openssh-blacklist.ctl
+  sudo dpkg -i openssh-blacklist_1.0_all.deb
+
+Be warned: this circumvents a security measure for the sake of disk space.
+You should only do this if you have no other option, and if you are certain
+that no compromised keys will ever be generated on or copied onto this
+system.
+
+Once a sufficient amount of time and number of releases have passed, the
+openssh-blacklist package will be phased out.
diff --git a/debian/README.source b/debian/README.source
new file mode 100644 (file)
index 0000000..cf28fbd
--- /dev/null
@@ -0,0 +1,223 @@
+Debian OpenSSH source package handling
+======================================
+
+The Debian package of OpenSSH is maintained in Bazaar
+(http://bazaar-vcs.org/, or the 'bzr' package in Debian). You will need at
+least version 1.16.1; the version in Debian testing as of the time of
+writing (2009-12-21) is fine, or you can use the version in lenny-backports.
+URLs are as follows:
+
+  Anonymous branch: http://anonscm.debian.org/bzr/pkg-ssh/openssh/trunk
+  Web browsing:     http://anonscm.debian.org/loggerhead/pkg-ssh/openssh/trunk
+  Authenticated, for developers with commit access only:
+                    bzr+ssh://bzr.debian.org/bzr/pkg-ssh/openssh/trunk
+
+Although it's possible that I may use something like bzr-loom in the future
+to better manage things like the Kerberos/GSSAPI patch, right now there's no
+funny business and all that developers need to do is:
+
+  # To check out:
+  bzr co bzr+ssh://bzr.debian.org/bzr/pkg-ssh/openssh/trunk openssh
+
+  # To update:
+  bzr up
+
+  # To edit:
+  # hack hack hack, and 'bzr add' any new files
+  debcommit # or bzr commit
+  # note that this pushes automatically; you can use 'bzr unbind' to
+  # temporarily prevent this, or 'bzr branch' to create a local branch which
+  # you can merge later
+
+  # To release:
+  dch -r && debcommit -r
+
+If you have lots of branches, you'll probably want to use a shared
+repository to save space. Run 'bzr init-repo .' in an ancestor directory of
+all your OpenSSH working directories. For example, I have a shared
+repository in ~/src/debian/openssh/, upstream checkouts in
+~/src/debian/openssh/upstream/, and my own working trees in
+~/src/debian/openssh/trunk/.
+
+Patch handling
+--------------
+
+This package uses quilt to manage all modifications to the upstream source.
+Changes are stored in the source package as diffs in debian/patches and
+applied automatically by dpkg-source when the source package is extracted.
+
+To configure quilt to use debian/patches instead of patches, you want either
+to export QUILT_PATCHES=debian/patches in your environment or use this
+snippet in your ~/.quiltrc:
+
+    for where in ./ ../ ../../ ../../../ ../../../../ ../../../../../; do
+        if [ -e ${where}debian/rules -a -d ${where}debian/patches ]; then
+                export QUILT_PATCHES=debian/patches
+                break
+        fi
+    done
+
+After unpacking the source package, all patches will be applied, and you can
+use quilt normally.
+
+If you check out the source code from bzr, then all patches will be applied,
+but you will need to inform quilt of this manually.  Do this by running:
+
+    debian/rules quilt-setup
+
+To add a new set of changes, first run quilt push -a, and then run:
+
+    quilt new <patch>
+
+where <patch> is a descriptive name for the patch, used as the filename in
+debian/patches.  Then, for every file that will be modified by this patch,
+run:
+
+    quilt add <file>
+
+before editing those files.  You must tell quilt with quilt add what files
+will be part of the patch before making changes or quilt will not work
+properly.  After editing the files, run:
+
+    quilt refresh
+
+to save the results as a patch.
+
+Alternately, if you already have an external patch and you just want to add
+it to the build system, run quilt push -a and then:
+
+    quilt import -P <patch> /path/to/patch
+    quilt push -a
+
+(add -p 0 to quilt import if needed). <patch> as above is the filename to
+use in debian/patches.  The last quilt push -a will apply the patch to make
+sure it works properly.
+
+To remove an existing patch from the list of patches that will be applied,
+run:
+
+    quilt delete <patch>
+
+You may need to run quilt pop -a to unapply patches first before running
+this command.
+
+You should only commit changes to bzr with all patches applied, i.e. after
+'quilt push -a'.
+
+Merging new upstream releases
+-----------------------------
+
+(Most developers will not need to read this section.)
+
+Thanks to the import from Portable OpenSSH CVS provided by Launchpad
+(https://code.launchpad.net/~vcs-imports/openssh/main, accessible by the
+shortcut 'lp:openssh' from the bzr client), the Debian branch is a true DVCS
+branch from upstream. This is a worthwhile property, but preserving it does
+take a little bit of work.
+
+Launchpad only imports CVS HEAD, but upstream sometimes produces releases
+from a branch. We use the same software used by Launchpad to import the
+branch as well, but a few small hacks are necessary to do good branch
+imports. In Bazaar, it's important that the same file in different branches
+should have the same file-id, otherwise merge attempts will try to delete
+and re-add the file which usually doesn't work out very well. Occasionally a
+file is added to CVS HEAD and then also added to a branch, and cscvs isn't
+quite smart enough to spot this and copy over the file-id. We need to help
+it out.
+
+To fetch the necessary code:
+
+  bzr branch lp:~cjwatson/launchpad-cscvs/openssh-branch-imports
+  # or 'bzr pull' in the appropriate directory to update this, if you
+  # already have a copy
+
+To import a branch, V_5_3 in this example:
+
+  export PATH="/path/to/cscvs/openssh-branch-imports:$PATH"
+  export PYTHONPATH=/path/to/cscvs/openssh-branch-imports/modules:/path/to/cscvs/openssh-branch-imports
+  # in a CVS checkout of :ext:anoncvs@anoncvs.mindrot.org:/cvs module
+  # openssh:
+  cscvs cache -b
+  # or 'cscvs cache -u' if you've done this before and want to update
+  cvs up -rV_5_3
+
+  # Now we need to get a few bits of information from cscvs' cache.
+  sqlite CVS/Catalog.sqlite
+  sqlite> select csnum,log from changeset where branch = 'V_5_3' order by startdate;
+  # There will be a solid block of "Creation of branch V_5_3" changesets at
+  # the start; look for the first revision *after* this. Substitute this in
+  # the following wherever you see "CSX".
+  sqlite> select revision,filename from revision where branch = 'V_5_3' and csnum >= CSX and revision not like '%.%.%' order by filename;
+  # Anything listed here will need to be added to the openssh_ids dictionary
+  # in modules/CVS/StorageLayer.py in cscvs. Please send Colin Watson a
+  # patch if you do this.
+
+  # Next, look up the branchpoint revision in the main bzr import (bzr
+  # branch lp:openssh). It's usually easiest to just look it up by commit
+  # message and double-check the timestamp. Substitute this revision number
+  # for "BPR" in the following. /path/to/openssh/main is wherever you've
+  # checked out lp:openssh.
+  bzr branch -rBPR /path/to/openssh/main /path/to/openssh/5.3
+  # If you're using Bazaar signed commits with a GPG agent, make sure that
+  # your agent has seen your passphrase recently. Now you can start the
+  # actual import!
+  cscvs -D4 totla -SC V_5_3.CSX: /path/to/openssh/5.3
+  # If this fails at the end with a "directories differ" message, you may
+  # have forgotten to switch your CVS checkout to the appropriate branch
+  # with 'cvs up -r...' above. Otherwise you'll have to debug this for
+  # yourself. It's also worth double-checking that any files added to the
+  # branch have file-ids matching those on the trunk, using 'bzr ls -R
+  # --show-ids'.
+
+Now we have a Bazaar branch corresponding to what's in CVS. Previous such
+branches are available from Launchpad, for reference purposes:
+
+  https://code.launchpad.net/openssh
+
+However, upstream releases involve a 'make distprep' step as well to
+construct the tarball, and we need to import the results of this as well to
+get a clean package.
+
+Start by unpacking the upstream tarball (remember to check its GPG signature
+first!). Copy the .bzr directory from the upstream branch you prepared
+earlier. Now we have another branch, but with a working tree corresponding
+to the upstream tarball. Modifications and deletions are handled
+automatically, but we need to handle additions explicitly to make sure
+file-ids are correct (see above). Run:
+
+  bzr add --file-ids-from=/path/to/openssh/debian/trunk
+  bzr st --show-ids
+  # compare this with 'bzr ls --show-ids' in the Debian trunk to make sure
+  # the result will be mergeable
+  bzr ci -m 'Import 5.3p1 tarball'
+
+Add a parent revision for the previous tarball branch, to make it easier for
+bzr to compute accurate merges.
+
+  bzr log -n0 /path/to/openssh/debian/trunk | less
+  # find revision number for previous tarball import, hence 'PREVIOUS'
+  bzr merge -rPREVIOUS /path/to/openssh/debian/trunk
+  # merge history only, no file changes
+  bzr revert .
+  bzr ci -m 'add 5.2p1 tarball parent revision'
+  bzr tag upstream-5.3p1
+
+Next, merge this into the gssapi branch
+(bzr+ssh://bzr.debian.org/bzr/pkg-ssh/openssh/gssapi/). For this branch, we
+want to ignore the normal results of merging and take only the patch from
+http://www.sxw.org.uk/computing/patches/openssh.html; of course such a patch
+needs to exist first! To do this, run this in the gssapi branch:
+
+  bzr merge /path/to/openssh/tarball/branch
+  bzr revert -rrevno:-1:/path/to/openssh/tarball/branch .
+  patch -p1 </path/to/openssh/gssapi/patch
+  bzr add --file-ids-from=/path/to/openssh/debian/trunk
+  # you may need to deal with applying configure.ac changes to configure
+  # here
+  bzr ci -m 'import openssh-5.3p1-gsskex-all-20100124.patch'
+
+You should now be able to 'bzr merge' from the gssapi branch into the Debian
+trunk, resolve conflicts, and commit. If you see lots of "Contents conflict"
+messages, you may have got the file-ids wrong. Once you've committed the
+merge, you can throw away the tarball branch, as all its history will have
+been incorporated.
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..c811b9b
--- /dev/null
@@ -0,0 +1,3281 @@
+openssh (1:5.9p1-1) unstable; urgency=low
+
+  * New upstream release (http://www.openssh.org/txt/release-5.9).
+    - Introduce sandboxing of the pre-auth privsep child using an optional
+      sshd_config(5) "UsePrivilegeSeparation=sandbox" mode that enables
+      mandatory restrictions on the syscalls the privsep child can perform.
+    - Add new SHA256-based HMAC transport integrity modes from
+      http://www.ietf.org/id/draft-dbider-sha2-mac-for-ssh-02.txt.
+    - The pre-authentication sshd(8) privilege separation slave process now
+      logs via a socket shared with the master process, avoiding the need to
+      maintain /dev/log inside the chroot (closes: #75043, #429243,
+      #599240).
+    - ssh(1) now warns when a server refuses X11 forwarding (closes:
+      #504757).
+    - sshd_config(5)'s AuthorizedKeysFile now accepts multiple paths,
+      separated by whitespace (closes: #76312).  The authorized_keys2
+      fallback is deprecated but documented (closes: #560156).
+    - ssh(1) and sshd(8): set IPv6 traffic class from IPQoS, as well as IPv4
+      ToS/DSCP (closes: #498297).
+    - ssh-add(1) now accepts keys piped from standard input.  E.g. "ssh-add
+      - < /path/to/key" (closes: #229124).
+    - Clean up lost-passphrase text in ssh-keygen(1) (closes: #444691).
+    - Say "required" rather than "recommended" in unprotected-private-key
+      warning (LP: #663455).
+  * Update OpenSSH FAQ to revision 1.112.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 07 Sep 2011 23:46:00 +0100
+
+openssh (1:5.8p1-7) unstable; urgency=low
+
+  * Only recommend ssh-import-id when built on Ubuntu (closes: #635887).
+  * Use 'dpkg-vendor --derives-from Ubuntu' to detect Ubuntu systems rather
+    than 'lsb_release -is' so that Ubuntu derivatives behave the same way as
+    Ubuntu itself.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 29 Jul 2011 14:27:52 +0100
+
+openssh (1:5.8p1-6) unstable; urgency=low
+
+  * openssh-client and openssh-server Suggests: monkeysphere.
+  * Quieten logs when multiple from= restrictions are used in different
+    authorized_keys lines for the same key; it's still not ideal, but at
+    least you'll only get one log entry per key (closes: #630606).
+  * Merge from Ubuntu (Dustin Kirkland):
+    - openssh-server Recommends: ssh-import-id (no-op in Debian since that
+      package doesn't exist there, but this reduces the Ubuntu delta).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 28 Jul 2011 17:10:18 +0100
+
+openssh (1:5.8p1-5) unstable; urgency=low
+
+  * Drop openssh-server's dependency on openssh-blacklist to a
+    recommendation (closes: #622604).
+  * Update Vcs-* fields and README.source for Alioth changes.
+  * Backport from upstream:
+    - Make hostbased auth with ECDSA keys work correctly (closes: #633368).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 24 Jul 2011 11:06:47 +0100
+
+openssh (1:5.8p1-4) unstable; urgency=low
+
+  * Drop hardcoded dependencies on libssl0.9.8 and libcrypto0.9.8-udeb,
+    since the required minimum versions are rather old now anyway and
+    openssl has bumped its SONAME (thanks, Julien Cristau; closes: #620828).
+  * Remove unreachable code from openssh-server.postinst.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 04 Apr 2011 15:56:18 +0100
+
+openssh (1:5.8p1-3) unstable; urgency=low
+
+  * Correct ssh-keygen instruction in the changelog for 1:5.7p1-1 (thanks,
+    Joel Stanley).
+  * Allow ssh-add to read from FIFOs (thanks, Daniel Kahn Gillmor; closes:
+    #614897).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 18 Mar 2011 16:42:42 +0000
+
+openssh (1:5.8p1-2) unstable; urgency=low
+
+  * Upload to unstable.
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 08 Feb 2011 10:59:17 +0000
+
+openssh (1:5.8p1-1) experimental; urgency=low
+
+  * New upstream release (http://www.openssh.org/txt/release-5.8):
+    - Fix stack information leak in legacy certificate signing
+      (http://www.openssh.com/txt/legacy-cert.adv).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 05 Feb 2011 11:13:11 +0000
+
+openssh (1:5.7p1-2) experimental; urgency=low
+
+  * Fix crash in ssh_selinux_setfscreatecon when SELinux is disabled
+    (LP: #708571).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 27 Jan 2011 12:14:17 +0000
+
+openssh (1:5.7p1-1) experimental; urgency=low
+
+  * New upstream release (http://www.openssh.org/txt/release-5.7):
+    - Implement Elliptic Curve Cryptography modes for key exchange (ECDH)
+      and host/user keys (ECDSA) as specified by RFC5656.  ECDH and ECDSA
+      offer better performance than plain DH and DSA at the same equivalent
+      symmetric key length, as well as much shorter keys.
+    - sftp(1)/sftp-server(8): add a protocol extension to support a hard
+      link operation.  It is available through the "ln" command in the
+      client.  The old "ln" behaviour of creating a symlink is available
+      using its "-s" option or through the preexisting "symlink" command.
+    - scp(1): Add a new -3 option to scp: Copies between two remote hosts
+      are transferred through the local host (closes: #508613).
+    - ssh(1): "atomically" create the listening mux socket by binding it on
+      a temporary name and then linking it into position after listen() has
+      succeeded.  This allows the mux clients to determine that the server
+      socket is either ready or stale without races (closes: #454784).
+      Stale server sockets are now automatically removed (closes: #523250).
+    - ssh(1): install a SIGCHLD handler to reap expired child process
+      (closes: #594687).
+    - ssh(1)/ssh-agent(1): honour $TMPDIR for client xauth and ssh-agent
+      temporary directories (closes: #357469, although only if you arrange
+      for ssh-agent to actually see $TMPDIR since the setgid bit will cause
+      it to be stripped off).
+  * Update to current GSSAPI patch from
+    http://www.sxw.org.uk/computing/patches/openssh-5.7p1-gsskex-all-20110125.patch:
+    - Add GSSAPIServerIdentity option.
+  * Generate ECDSA host keys on fresh installations.  Upgraders who wish to
+    add such host keys should manually add 'HostKey
+    /etc/ssh/ssh_host_ecdsa_key' to /etc/ssh/sshd_config and run 'ssh-keygen
+    -q -f /etc/ssh/ssh_host_ecdsa_key -N "" -t ecdsa'.
+  * Build-depend on libssl-dev (>= 0.9.8g) to ensure sufficient ECC support.
+  * Backport SELinux build fix from CVS.
+  * Rearrange selinux-role.patch so that it links properly given this
+    SELinux build fix.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 26 Jan 2011 23:48:02 +0000
+
+openssh (1:5.6p1-3) experimental; urgency=low
+
+  * Drop override for desktop-file-but-no-dh_desktop-call, which Lintian no
+    longer issues.
+  * Merge 1:5.5p1-6.
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 30 Dec 2010 11:48:00 +0000
+
+openssh (1:5.6p1-2) experimental; urgency=low
+
+  * Backport upstream patch to install a SIGCHLD handler to reap expired ssh
+    child processes, preventing lots of zombies when using ControlPersist
+    (closes: #594687).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 26 Oct 2010 14:46:40 +0100
+
+openssh (1:5.6p1-1) experimental; urgency=low
+
+  * New upstream release (http://www.openssh.com/txt/release-5.6):
+    - Added a ControlPersist option to ssh_config(5) that automatically
+      starts a background ssh(1) multiplex master when connecting.  This
+      connection can stay alive indefinitely, or can be set to automatically
+      close after a user-specified duration of inactivity (closes: #335697,
+      #350898, #454787, #500573, #550262).
+    - Support AuthorizedKeysFile, AuthorizedPrincipalsFile,
+      HostbasedUsesNameFromPacketOnly, and PermitTunnel in sshd_config(5)
+      Match blocks (closes: #549858).
+    - sftp(1): fix ls in working directories that contain globbing
+      characters in their pathnames (LP: #530714).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 24 Aug 2010 00:37:54 +0100
+
+openssh (1:5.5p1-6) unstable; urgency=low
+
+  * Touch /var/run/sshd/.placeholder in the preinst so that /var/run/sshd,
+    which is intentionally no longer shipped in the openssh-server package
+    due to /var/run often being a temporary directory, is not removed on
+    upgrade (closes: #575582).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 26 Dec 2010 18:09:29 +0000
+
+openssh (1:5.5p1-5) unstable; urgency=low
+
+  * Use an architecture wildcard for libselinux1-dev (closes: #591740).
+  * debconf template translations:
+    - Update Danish (thanks, Joe Hansen; closes: #592800).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 23 Aug 2010 22:59:03 +0100
+
+openssh (1:5.5p1-4) unstable; urgency=low
+
+  [ Sebastian Andrzej Siewior ]
+  * Add powerpcspe to architecture list for libselinux1-dev build-dependency
+    (closes: #579843).
+
+  [ Colin Watson ]
+  * Allow ~/.ssh/authorized_keys and other secure files to be
+    group-writable, provided that the group in question contains only the
+    file's owner; this extends a patch previously applied to ~/.ssh/config
+    (closes: #581919).
+  * Check primary group memberships as well as supplementary group
+    memberships, and only allow group-writability by groups with exactly one
+    member, as zero-member groups are typically used by setgid binaries
+    rather than being user-private groups (closes: #581697).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 22 May 2010 23:37:20 +0100
+
+openssh (1:5.5p1-3) unstable; urgency=low
+
+  * Discard error messages while checking whether rsh, rlogin, and rcp
+    alternatives exist (closes: #579285).
+  * Drop IDEA key check; I don't think it works properly any more due to
+    textual changes in error output, it's only relevant for direct upgrades
+    from truly ancient versions, and it breaks upgrades if
+    /etc/ssh/ssh_host_key can't be loaded (closes: #579570).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 28 Apr 2010 22:12:47 +0100
+
+openssh (1:5.5p1-2) unstable; urgency=low
+
+  * Use dh_installinit -n, since our maintainer scripts already handle this
+    more carefully (thanks, Julien Cristau).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 17 Apr 2010 12:55:56 +0100
+
+openssh (1:5.5p1-1) unstable; urgency=low
+
+  * New upstream release:
+    - Unbreak sshd_config's AuthorizedKeysFile option for $HOME-relative
+      paths.
+    - Include a language tag when sending a protocol 2 disconnection
+      message.
+    - Make logging of certificates used for user authentication more clear
+      and consistent between CAs specified using TrustedUserCAKeys and
+      authorized_keys.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 16 Apr 2010 10:27:30 +0100
+
+openssh (1:5.4p1-2) unstable; urgency=low
+
+  * Borrow patch from Fedora to add DNSSEC support: if glibc 2.11 is
+    installed, the host key is published in an SSHFP RR secured with DNSSEC,
+    and VerifyHostKeyDNS=yes, then ssh will no longer prompt for host key
+    verification (closes: #572049).
+  * Convert to dh(1), and use dh_installdocs --link-doc.
+  * Drop lpia support, since Ubuntu no longer supports this architecture.
+  * Use dh_install more effectively.
+  * Add a NEWS.Debian entry about changes in smartcard support relative to
+    previous unofficial builds (closes: #231472).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 10 Apr 2010 01:08:59 +0100
+
+openssh (1:5.4p1-1) unstable; urgency=low
+
+  * New upstream release (LP: #535029).
+    - After a transition period of about 10 years, this release disables SSH
+      protocol 1 by default.  Clients and servers that need to use the
+      legacy protocol must explicitly enable it in ssh_config / sshd_config
+      or on the command-line.
+    - Remove the libsectok/OpenSC-based smartcard code and add support for
+      PKCS#11 tokens.  This support is enabled by default in the Debian
+      packaging, since it now doesn't involve additional library
+      dependencies (closes: #231472, LP: #16918).
+    - Add support for certificate authentication of users and hosts using a
+      new, minimal OpenSSH certificate format (closes: #482806).
+    - Added a 'netcat mode' to ssh(1): "ssh -W host:port ...".
+    - Add the ability to revoke keys in sshd(8) and ssh(1).  (For the Debian
+      package, this overlaps with the key blacklisting facility added in
+      openssh 1:4.7p1-9, but with different file formats and slightly
+      different scopes; for the moment, I've roughly merged the two.)
+    - Various multiplexing improvements, including support for requesting
+      port-forwardings via the multiplex protocol (closes: #360151).
+    - Allow setting an explicit umask on the sftp-server(8) commandline to
+      override whatever default the user has (closes: #496843).
+    - Many sftp client improvements, including tab-completion, more options,
+      and recursive transfer support for get/put (LP: #33378).  The old
+      mget/mput commands never worked properly and have been removed
+      (closes: #270399, #428082).
+    - Do not prompt for a passphrase if we fail to open a keyfile, and log
+      the reason why the open failed to debug (closes: #431538).
+    - Prevent sftp from crashing when given a "-" without a command.  Also,
+      allow whitespace to follow a "-" (closes: #531561).
+
+  * Fix 'debian/rules quilt-setup' to avoid writing .orig files if some
+    patches apply with offsets.
+  * Include debian/ssh-askpass-gnome.png in the Debian tarball now that
+    we're using a source format that permits this, rather than messing
+    around with uudecode.
+  * Drop compatibility with the old gssapi mechanism used in ssh-krb5 <<
+    3.8.1p1-1.  Simon Wilkinson refused this patch since the old gssapi
+    mechanism was removed due to a serious security hole, and since these
+    versions of ssh-krb5 are no longer security-supported by Debian I don't
+    think there's any point keeping client compatibility for them.
+  * Fix substitution of ETC_PAM_D_SSH, following the rename in 1:4.7p1-4.
+  * Hardcode the location of xauth to /usr/bin/xauth rather than
+    /usr/bin/X11/xauth (thanks, Aron Griffis; closes: #575725, LP: #8440).
+    xauth no longer depends on x11-common, so we're no longer guaranteed to
+    have the /usr/bin/X11 symlink available.  I was taking advantage of the
+    /usr/bin/X11 symlink to smooth X's move to /usr/bin, but this is far
+    enough in the past now that it's probably safe to just use /usr/bin.
+  * Remove SSHD_OOM_ADJUST configuration.  sshd now unconditionally makes
+    itself non-OOM-killable, and doesn't require configuration to avoid log
+    spam in virtualisation containers (closes: #555625).
+  * Drop Debian-specific removal of OpenSSL version check.  Upstream ignores
+    the two patchlevel nybbles now, which is sufficient to address the
+    original reason this change was introduced, and it appears that any
+    change in the major/minor/fix nybbles would involve a new libssl package
+    name.  (We'd still lose if the status nybble were ever changed, but that
+    would mean somebody had packaged a development/beta version rather than
+    a proper release, which doesn't appear to be normal practice.)
+  * Drop most of our "LogLevel SILENT" (-qq) patch.  This was originally
+    introduced to match the behaviour of non-free SSH, in which -q does not
+    suppress fatal errors, but matching the behaviour of OpenSSH upstream is
+    much more important nowadays.  We no longer document that -q does not
+    suppress fatal errors (closes: #280609).  Migrate "LogLevel SILENT" to
+    "LogLevel QUIET" in sshd_config on upgrade.
+  * Policy version 3.8.4:
+    - Add a Homepage field.
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 06 Apr 2010 22:38:31 +0100
+
+openssh (1:5.3p1-3) unstable; urgency=low
+
+  * Convert to source format 3.0 (quilt).
+  * Update README.source to match, and add a 'quilt-setup' target to
+    debian/rules for the benefit of those checking out the package from
+    revision control.
+  * All patches are now maintained separately and tagged according to DEP-3.
+  * Add GSSAPIStoreCredentialsOnRekey to 'sshd -T' configuration dump.
+  * Remove documentation of building for Debian 3.0 in README.Debian.
+    Support for this was removed in 1:4.7p1-2.
+  * Remove obsolete header from README.Debian dating from when people
+    expected non-free SSH.
+  * Update copyright years for GSSAPI patch.
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 28 Feb 2010 01:35:53 +0000
+
+openssh (1:5.3p1-2) unstable; urgency=low
+
+  * Link with -Wl,--as-needed (closes: #560155).
+  * Install upstream sshd_config as an example (closes: #415008).
+  * Use dh_lintian.
+  * Honour DEB_BUILD_OPTIONS=nocheck.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 22 Feb 2010 12:43:24 +0000
+
+openssh (1:5.3p1-1) unstable; urgency=low
+
+  * New upstream release.
+  * Update to GSSAPI patch from
+    http://www.sxw.org.uk/computing/patches/openssh-5.3p1-gsskex-all-20100124.patch.
+  * Backport from upstream:
+    - Do not fall back to adding keys without constraints (ssh-add -c / -t
+      ...) when the agent refuses the constrained add request. This was a
+      useful migration measure back in 2002 when constraints were new, but
+      just adds risk now (LP: #209447).
+  * Drop change from 1:3.8p1-3 to avoid setresuid() and setresgid() system
+    calls.  This only applied to Linux 2.2, which it's no longer feasible to
+    run anyway (see 1:5.2p1-2 changelog).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 26 Jan 2010 11:55:29 +0000
+
+openssh (1:5.2p1-2) unstable; urgency=low
+
+  [ Colin Watson ]
+  * Backport from upstream:
+    - After sshd receives a SIGHUP, ignore subsequent HUPs while sshd
+      re-execs itself.  Prevents two HUPs in quick succession from resulting
+      in sshd dying (LP: #497781).
+    - Output a debug if we can't open an existing keyfile (LP: #505301).
+  * Use host compiler for ssh-askpass-gnome when cross-compiling.
+  * Don't run tests when cross-compiling.
+  * Drop change from 1:3.6.1p2-5 to disable cmsg_type check for file
+    descriptor passing when running on Linux 2.0.  The previous stable
+    release of Debian dropped support for Linux 2.4, let alone 2.0, so this
+    very likely has no remaining users depending on it.
+
+  [ Kees Cook ]
+  * Implement DebianBanner server configuration flag that can be set to "no"
+    to allow sshd to run without the Debian-specific extra version in the
+    initial protocol handshake (closes: #562048).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 16 Jan 2010 01:28:58 +0000
+
+openssh (1:5.2p1-1) unstable; urgency=low
+
+  * New upstream release (closes: #536182). Yes, I know 5.3p1 has been out
+    for a while, but there's no GSSAPI patch available for it yet.
+    - Change the default cipher order to prefer the AES CTR modes and the
+      revised "arcfour256" mode to CBC mode ciphers that are susceptible to
+      CPNI-957037 "Plaintext Recovery Attack Against SSH".
+    - Add countermeasures to mitigate CPNI-957037-style attacks against the
+      SSH protocol's use of CBC-mode ciphers. Upon detection of an invalid
+      packet length or Message Authentication Code, ssh/sshd will continue
+      reading up to the maximum supported packet length rather than
+      immediately terminating the connection. This eliminates most of the
+      known differences in behaviour that leaked information about the
+      plaintext of injected data which formed the basis of this attack
+      (closes: #506115, LP: #379329).
+    - ForceCommand directive now accepts commandline arguments for the
+      internal-sftp server (closes: #524423, LP: #362511).
+    - Add AllowAgentForwarding to available Match keywords list (closes:
+      #540623).
+    - Make ssh(1) send the correct channel number for
+      SSH2_MSG_CHANNEL_SUCCESS and SSH2_MSG_CHANNEL_FAILURE messages to
+      avoid triggering 'Non-public channel' error messages on sshd(8) in
+      openssh-5.1.
+    - Avoid printing 'Non-public channel' warnings in sshd(8), since the
+      ssh(1) has sent incorrect channel numbers since ~2004 (this reverts a
+      behaviour introduced in openssh-5.1; closes: #496017).
+    - Disable nonfunctional ssh(1) ~C escape handler in multiplex slave
+      connections (closes: #507541).
+    - Fix "whitepsace" typo in ssh_config(5) (closes: #514313, LP: #303835).
+  * Update to GSSAPI patch from
+    http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch,
+    including cascading credentials support (LP: #416958).
+  * Use x11.pc when compiling/linking gnome-ssh-askpass2 (closes: #555951).
+  * Moved to bzr.debian.org; add Vcs-Bzr and Vcs-Browser control fields.
+  * Add debian/README.source with instructions on bzr handling.
+  * Make ChrootDirectory work with SELinux (thanks, Russell Coker; closes:
+    #556644).
+  * Initialise sc to NULL in ssh_selinux_getctxbyname (thanks, Václav Ovsík;
+    closes: #498684).
+  * Don't duplicate backslashes when displaying server banner (thanks,
+    Michał Górny; closes: #505378, LP: #425346).
+  * Use hardening-includes for hardening logic (thanks, Kees Cook; closes:
+    #561887).
+  * Update OpenSSH FAQ to revision 1.110.
+  * Remove ssh/new_config, only needed for direct upgrades from potato which
+    are no longer particularly feasible anyway (closes: #420682).
+  * Cope with insserv reordering of init script links.
+  * Remove init script stop link in rc1, as killprocs handles it already.
+  * Adjust short descriptions to avoid relying on previous experience with
+    rsh, based on suggestions from Reuben Thomas (closes: #512198).
+  * Remove manual page references to login.conf, which aren't applicable on
+    non-BSD systems (closes: #154434).
+  * Remove/adjust manual page references to BSD-specific /etc/rc (closes:
+    #513417).
+  * Refer to sshd_config(5) rather than sshd(8) in postinst-written
+    /etc/ssh/sshd_config, and add UsePAM commentary from upstream-shipped
+    configuration file (closes: #415008, although unfortunately this will
+    only be conveniently visible on new installations).
+  * Include URL to OpenBSD's ssl(8) in ssh(1), since I don't see a better
+    source for the same information among Debian's manual pages (closes:
+    #530692, LP: #456660).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 04 Jan 2010 13:23:35 +0000
+
+openssh (1:5.1p1-8) unstable; urgency=low
+
+  * Build with just -fPIC on mips/mipsel, not -fPIE as well (thanks, LIU Qi;
+    closes: #538313).
+  * Build-depend on libselinux1-dev on sh4 too (thanks, Nobuhiro Iwamatsu;
+    closes: #547103).
+  * Fix grammar in if-up script (closes: #549128).
+  * Pass $SSHD_OPTS when checking configuration too (thanks, "sobtwmxt";
+    closes: #548662).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 05 Oct 2009 13:30:49 +0100
+
+openssh (1:5.1p1-7) unstable; urgency=low
+
+  * Update config.guess and config.sub from autotools-dev 20090611.1
+    (closes: #538301).
+  * Set umask to 022 in the init script as well as postinsts (closes:
+    #539030).
+  * Add ${misc:Depends} to keep Lintian happy.
+  * Use 'which' rather than 'type' in maintainer scripts.
+  * Upgrade to debhelper v7.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 31 Jul 2009 16:28:10 +0100
+
+openssh (1:5.1p1-6) unstable; urgency=low
+
+  * Open /proc/self/oom_adj with O_RDONLY or O_WRONLY as necessary, rather
+    than O_RDWR.
+  * Disable OOM adjustment for vserver/OpenVZ (thanks, Karl Chen; closes:
+    #511771).
+  * Add ufw integration (thanks, Didier Roche; see
+    https://wiki.ubuntu.com/UbuntuFirewall#Integrating%20UFW%20with%20Packages;
+    LP: #261884).
+  * Add a comment above PermitRootLogin in sshd_config pointing to
+    README.Debian.
+  * Check if delgroup is present in openssh-client.postrm (closes: #530501).
+  * Build with -fPIC on mips/mipsel (thanks, Luk Claes; closes: #531942).
+  * Remove /var/run/sshd from openssh-server package; it will be created at
+    run-time before starting the server.
+  * Use invoke-rc.d in openssh-server's if-up script.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 05 Jun 2009 11:56:03 +0100
+
+openssh (1:5.1p1-5) unstable; urgency=low
+
+  * Backport from upstream CVS (Markus Friedl):
+    - packet_disconnect() on padding error, too. Should reduce the success
+      probability for the CPNI-957037 Plaintext Recovery Attack to 2^-18.
+  * Check that /var/run/sshd.pid exists and that the process ID listed there
+    corresponds to sshd before running '/etc/init.d/ssh reload' from if-up
+    script; SIGHUP is racy if called at boot before sshd has a chance to
+    install its signal handler, but fortunately the pid file is written
+    after that which lets us avoid the race (closes: #502444).
+  * While the above is a valuable sanity-check, it turns out that it doesn't
+    really fix the bug (thanks to Kevin Price for testing), so for the
+    meantime we'll just use '/etc/init.d/ssh restart', even though it is
+    unfortunately heavyweight.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 14 Jan 2009 00:34:08 +0000
+
+openssh (1:5.1p1-4) unstable; urgency=low
+
+  * ssh-copy-id: Strip trailing colons from hostname (closes: #226172,
+    LP: #249706; thanks to Karl Goetz for nudging this along; forwarded
+    upstream as https://bugzilla.mindrot.org/show_bug.cgi?id=1530).
+  * Backport from upstream CVS (Markus Friedl):
+    - Only send eow and no-more-sessions requests to openssh 5 and newer;
+      fixes interop problems with broken ssh v2 implementations (closes:
+      #495917).
+  * Fix double-free when failing to parse a forwarding specification given
+    using ~C (closes: #505330; forwarded upstream as
+    https://bugzilla.mindrot.org/show_bug.cgi?id=1539).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 23 Nov 2008 14:46:10 +0000
+
+openssh (1:5.1p1-3) unstable; urgency=low
+
+  * Remove unnecessary ssh-vulnkey output in non-verbose mode when no
+    compromised or unknown keys were found (closes: #496495).
+  * Configure with --disable-strip; dh_strip will deal with stripping
+    binaries and will honour DEB_BUILD_OPTIONS (thanks, Bernhard R. Link;
+    closes: #498681).
+  * Fix handling of zero-length server banners (thanks, Tomas Mraz; closes:
+    #497026).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 30 Sep 2008 23:09:58 +0100
+
+openssh (1:5.1p1-2) unstable; urgency=low
+
+  * Look for $SHELL on the path when executing ProxyCommands or
+    LocalCommands (closes: #492728).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 29 Jul 2008 15:31:25 +0100
+
+openssh (1:5.1p1-1) unstable; urgency=low
+
+  * New upstream release (closes: #474301). Important changes not previously
+    backported to 4.7p1:
+    - 4.9/4.9p1 (http://www.openssh.com/txt/release-4.9):
+      + Added chroot(2) support for sshd(8), controlled by a new option
+        "ChrootDirectory" (closes: #139047, LP: #24777).
+      + Linked sftp-server(8) into sshd(8). The internal sftp server is used
+        when the command "internal-sftp" is specified in a Subsystem or
+        ForceCommand declaration. When used with ChrootDirectory, the
+        internal sftp server requires no special configuration of files
+        inside the chroot environment.
+      + Added a protocol extension method "posix-rename@openssh.com" for
+        sftp-server(8) to perform POSIX atomic rename() operations; sftp(1)
+        prefers this if available (closes: #308561).
+      + Removed the fixed limit of 100 file handles in sftp-server(8).
+      + ssh(8) will now skip generation of SSH protocol 1 ephemeral server
+        keys when in inetd mode and protocol 2 connections are negotiated.
+        This speeds up protocol 2 connections to inetd-mode servers that
+        also allow Protocol 1.
+      + Accept the PermitRootLogin directive in a sshd_config(5) Match
+        block. Allows for, e.g. permitting root only from the local network.
+      + Reworked sftp(1) argument splitting and escaping to be more
+        internally consistent (i.e. between sftp commands) and more
+        consistent with sh(1). Please note that this will change the
+        interpretation of some quoted strings, especially those with
+        embedded backslash escape sequences.
+      + Support "Banner=none" in sshd_config(5) to disable sending of a
+        pre-login banner (e.g. in a Match block).
+      + ssh(1) ProxyCommands are now executed with $SHELL rather than
+        /bin/sh.
+      + ssh(1)'s ConnectTimeout option is now applied to both the TCP
+        connection and the SSH banner exchange (previously it just covered
+        the TCP connection). This allows callers of ssh(1) to better detect
+        and deal with stuck servers that accept a TCP connection but don't
+        progress the protocol, and also makes ConnectTimeout useful for
+        connections via a ProxyCommand.
+      + scp(1) incorrectly reported "stalled" on slow copies (closes:
+        #140828).
+      + scp(1) date underflow for timestamps before epoch.
+      + ssh(1) used the obsolete SIG DNS RRtype for host keys in DNS,
+        instead of the current standard RRSIG.
+      + Correctly drain ACKs when a sftp(1) upload write fails midway,
+        avoids a fatal() exit from what should be a recoverable condition.
+      + Fixed ssh-keygen(1) selective host key hashing (i.e. "ssh-keygen -HF
+        hostname") to not include any IP address in the data to be hashed.
+      + Make ssh(1) skip listening on the IPv6 wildcard address when a
+        binding address of 0.0.0.0 is used against an old SSH server that
+        does not support the RFC4254 syntax for wildcard bind addresses.
+      + Enable IPV6_V6ONLY socket option on sshd(8) listen socket, as is
+        already done for X11/TCP forwarding sockets (closes: #439661).
+      + Fix FD leak that could hang a ssh(1) connection multiplexing master.
+      + Make ssh(1) -q option documentation consistent with reality.
+      + Fixed sshd(8) PAM support not calling pam_session_close(), or
+        failing to call it with root privileges (closes: #372680).
+      + Fix activation of OpenSSL engine support when requested in configure
+        (LP: #119295).
+      + Cache SELinux status earlier so we know if it's enabled after a
+        chroot (LP: #237557).
+    - 5.1/5.1p1 (http://www.openssh.com/txt/release-5.1):
+      + Introduce experimental SSH Fingerprint ASCII Visualisation to ssh(1)
+        and ssh-keygen(1). Visual fingerprint display is controlled by a new
+        ssh_config(5) option "VisualHostKey". The intent is to render SSH
+        host keys in a visual form that is amenable to easy recall and
+        rejection of changed host keys.
+      + sshd_config(5) now supports CIDR address/masklen matching in "Match
+        address" blocks, with a fallback to classic wildcard matching.
+      + sshd(8) now supports CIDR matching in ~/.ssh/authorized_keys
+        from="..." restrictions, also with a fallback to classic wildcard
+        matching.
+      + Added an extended test mode (-T) to sshd(8) to request that it write
+        its effective configuration to stdout and exit. Extended test mode
+        also supports the specification of connection parameters (username,
+        source address and hostname) to test the application of
+        sshd_config(5) Match rules. 
+      + ssh(1) now prints the number of bytes transferred and the overall
+        connection throughput for SSH protocol 2 sessions when in verbose
+        mode (previously these statistics were displayed for protocol 1
+        connections only).
+      + sftp-server(8) now supports extension methods statvfs@openssh.com
+        and fstatvfs@openssh.com that implement statvfs(2)-like operations.
+      + sftp(1) now has a "df" command to the sftp client that uses the
+        statvfs@openssh.com to produce a df(1)-like display of filesystem
+        space and inode utilisation (requires statvfs@openssh.com support on
+        the server).
+      + Added a MaxSessions option to sshd_config(5) to allow control of the
+        number of multiplexed sessions supported over a single TCP
+        connection. This allows increasing the number of allowed sessions
+        above the previous default of 10, disabling connection multiplexing
+        (MaxSessions=1) or disallowing login/shell/subsystem sessions
+        entirely (MaxSessions=0).
+      + Added a no-more-sessions@openssh.com global request extension that
+        is sent from ssh(1) to sshd(8) when the client knows that it will
+        never request another session (i.e. when session multiplexing is
+        disabled). This allows a server to disallow further session requests
+        and terminate the session in cases where the client has been
+        hijacked.
+      + ssh-keygen(1) now supports the use of the -l option in combination
+        with -F to search for a host in ~/.ssh/known_hosts and display its
+        fingerprint.
+      + ssh-keyscan(1) now defaults to "rsa" (protocol 2) keys, instead of
+        "rsa1" (LP: #129794).
+      + Added an AllowAgentForwarding option to sshd_config(8) to control
+        whether authentication agent forwarding is permitted. Note that this
+        is a loose control, as a client may install their own unofficial
+        forwarder.
+      + ssh(1) and sshd(8): avoid unnecessary malloc/copy/free when
+        receiving network data, resulting in a ~10% speedup.
+      + ssh(1) and sshd(8) will now try additional addresses when connecting
+        to a port forward destination whose DNS name resolves to more than
+        one address. The previous behaviour was to try the only first
+        address and give up if that failed.
+      + ssh(1) and sshd(8) now support signalling that channels are
+        half-closed for writing, through a channel protocol extension
+        notification "eow@openssh.com". This allows propagation of closed
+        file descriptors, so that commands such as "ssh -2 localhost od
+        /bin/ls | true" do not send unnecessary data over the wire.
+      + sshd(8): increased the default size of ssh protocol 1 ephemeral keys
+        from 768 to 1024 bits.
+      + When ssh(1) has been requested to fork after authentication ("ssh
+        -f") with ExitOnForwardFailure enabled, delay the fork until after
+        replies for any -R forwards have been seen. Allows for robust
+        detection of -R forward failure when using -f.
+      + "Match group" blocks in sshd_config(5) now support negation of
+        groups. E.g. "Match group staff,!guests".
+      + sftp(1) and sftp-server(8) now allow chmod-like operations to set
+        set[ug]id/sticky bits.
+      + The MaxAuthTries option is now permitted in sshd_config(5) match
+        blocks.
+      + Multiplexed ssh(1) sessions now support a subset of the ~ escapes
+        that are available to a primary connection.
+      + ssh(1) connection multiplexing will now fall back to creating a new
+        connection in most error cases (closes: #352830).
+      + Make ssh(1) deal more gracefully with channel requests that fail.
+        Previously it would optimistically assume that requests would always
+        succeed, which could cause hangs if they did not (e.g. when the
+        server runs out of file descriptors).
+      + ssh(1) now reports multiplexing errors via the multiplex slave's
+        stderr where possible (subject to LogLevel in the mux master).
+      + Fixed an UMAC alignment problem that manifested on Itanium
+        platforms.
+  * Remove our local version of moduli(5) now that there's one upstream.
+  * Say "GTK+" rather than "GTK" in ssh-askpass-gnome's description.
+  * Add lintian overrides for empty /usr/share/doc/openssh-client
+    directories in openssh-server and ssh (necessary due to being symlink
+    targets).
+  * Merge from Ubuntu:
+    - Add 'status' action to openssh-server init script, requiring lsb-base
+      (>= 3.2-13) (thanks, Dustin Kirkland).
+  * debconf template translations:
+    - Update Korean (thanks, Sunjae Park; closes: #484821).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 25 Jul 2008 10:45:08 +0100
+
+openssh (1:4.7p1-13) unstable; urgency=low
+
+  * Add some helpful advice to the end of ssh-vulnkey's output if there are
+    unknown or compromised keys (thanks, Dan Jacobson; closes: #483756).
+  * Check compromised key blacklist in ssh or ssh-add, as well as in the
+    server (LP: #232391). To override the blacklist check in ssh
+    temporarily, use 'ssh -o UseBlacklistedKeys=yes'; there is no override
+    for the blacklist check in ssh-add.
+  * Add cross-references to ssh-vulnkey(1) to ssh(1), ssh-add(1),
+    ssh-keygen(1), and sshd(8) (closes: #484451).
+  * Change openssh-client-udeb's Installer-Menu-Item from 99900 to 99999
+    (thanks, Frans Pop).
+  * Drop openssh-client-udeb isinstallable hack, as main-menu (>= 1.26) now
+    takes care of that (thanks, Frans Pop; closes: #484404).
+  * Update DEB_BUILD_OPTIONS parsing code from policy 3.8.0.
+  * Add documentation on removing openssh-blacklist locally (see #484269).
+  * Clarify documentation of SSHD_OOM_ADJUST, and make setting it to the
+    empty string actually skip adjustment as intended (closes: #487325).
+  * Remove empty /usr/share/applications directory in ssh-askpass-gnome.
+  * debconf template translations:
+    - Update Romanian (thanks, Cătălin Feștilă; closes: #485415).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 21 Jul 2008 12:18:28 +0100
+
+openssh (1:4.7p1-12) unstable; urgency=low
+
+  * Fill in CVE identifier for ssh-vulnkey bug fixed in 1:4.7p1-10.
+  * Refactor rejection of blacklisted user keys into a single
+    reject_blacklisted_key function in auth.c (thanks, Dmitry V. Levin).
+  * Fix memory leak of blacklisted host keys (thanks, Dmitry V. Levin).
+  * debconf template translations:
+    - Update Dutch (thanks, Bart Cornelis; closes: #483004).
+    - Update Brazilian Portuguese (thanks, Eder L. Marques; closes:
+      #483142).
+    - Update Slovak (thanks, Ivan Masár; closes: #483517).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 29 May 2008 21:41:29 +0100
+
+openssh (1:4.7p1-11) unstable; urgency=low
+
+  * Make init script depend on $syslog, and fix some other dependency
+    glitches (thanks, Petter Reinholdtsen; closes: #481018).
+  * Remove 0 and 6 from Default-Stop in init script (thanks, Kel Modderman;
+    closes: #481151).
+  * Restore OOM killer adjustment for child processes (thanks, Vaclav Ovsik;
+    closes: #480020).
+  * Allow building with heimdal-dev (LP: #125805).
+
+  * Check RSA1 keys without the need for a separate blacklist. Thanks to
+    Simon Tatham for the idea.
+  * Generate two keys with the PID forced to the same value and test that
+    they differ, to defend against recurrences of the recent Debian OpenSSL
+    vulnerability.
+  * Recommend openssh-blacklist from openssh-client (closes: #481187).
+  * Recommend openssh-blacklist-extra from openssh-client and
+    openssh-server.
+  * Make ssh-vulnkey report the file name and line number for each key
+    (thanks, Heiko Schlittermann and Christopher Perry; closes: #481398).
+  * Check for blacklists in /usr/share/ssh/ as well as /etc/ssh/ (see
+    #481283).
+  * Log IP addresses of hosts attempting to use blacklisted keys (closes:
+    #481721).
+  * Incorporate various ssh-vulnkey suggestions from Hugh Daniel:
+    - Add -v (verbose) option, and don't print output for keys that have a
+      blacklist file but that are not listed unless in verbose mode.
+    - Move exit status documentation to a separate section.
+    - Document key status descriptions.
+    - Add key type to output.
+    - Fix error output if ssh-vulnkey fails to read key files, with the
+      exception of host keys unless -a was given.
+    - In verbose mode, output the name of each file examined.
+  * Handle leading IP addresses in ssh-vulnkey input (LP: #230497).
+  * Fix various ssh-vulnkey problems pointed out by Solar Designer:
+    - Fix some buffer handling inconsistencies.
+    - Use xasprintf to build user key file names, avoiding truncation
+      problems.
+    - Drop to the user's UID when reading user keys with -a.
+    - Use EUID rather than UID when run with no file names and without -a.
+    - Reword "Unknown (no blacklist information)" to "Unknown (blacklist
+      file not installed)".
+
+  * Fix typo in ssh/vulnerable_host_keys message (thanks, Esko Arajärvi).
+  * debconf template translations:
+    - Update Finnish (thanks, Esko Arajärvi; closes: #481530).
+    - Update French (thanks, Christian Perrier; closes: #481576).
+    - Update Norwegian Bokmål (thanks, Bjørn Steensrud; closes: #481591).
+    - Update Galician (thanks, Jacobo Tarrio; closes: #481596).
+    - Update Japanese (thanks, Kenshi Muto; closes: #481621).
+    - Update Czech (thanks, Miroslav Kure; closes: #481624).
+    - Update German (thanks, Helge Kreutzmann; closes: #481676).
+    - Update Portuguese (thanks, Ricardo Silva; closes: #481781).
+    - Update Basque (thanks, Piarres Beobide; closes: #481836).
+    - Update Bulgarian (thanks, Damyan Ivanov; closes: #481870).
+    - Update Vietnamese (thanks, Clytie Siddall; closes: #481876).
+    - Update Spanish (thanks, Javier Fernandez-Sanguino Peña; closes:
+      #482341).
+    - Update Turkish (thanks, Mert Dirik; closes: #482548).
+    - Update Russian (thanks, Yuri Kozlov; closes: #482887).
+    - Update Swedish (thanks, Martin Bagge; closes: #482464).
+    - Update Italian (thanks, Luca Monducci; closes: #482808).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 26 May 2008 12:21:39 +0100
+
+openssh (1:4.7p1-10) unstable; urgency=low
+
+  * Add a FILES section to ssh-vulnkey(1) (thanks, Hugh Daniel).
+  * CVE-2008-2285: ssh-vulnkey handles options in authorized_keys
+    (LP: #230029), and treats # as introducing a comment even if it is
+    preceded by whitespace.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 14 May 2008 12:35:05 +0100
+
+openssh (1:4.7p1-9) unstable; urgency=critical
+
+  * Fill in CVE identifier for security vulnerability fixed in 1:4.7p1-8.
+  * Mitigate OpenSSL security vulnerability (CVE-2008-0166):
+    - Add key blacklisting support. Keys listed in
+      /etc/ssh/blacklist.TYPE-LENGTH will be rejected for authentication by
+      sshd, unless "PermitBlacklistedKeys yes" is set in
+      /etc/ssh/sshd_config.
+    - Add a new program, ssh-vulnkey, which can be used to check keys
+      against these blacklists.
+    - Depend on openssh-blacklist.
+    - Force dependencies on libssl0.9.8 / libcrypto0.9.8-udeb to at least
+      0.9.8g-9.
+    - Automatically regenerate known-compromised host keys, with a
+      critical-priority debconf note. (I regret that there was no time to
+      gather translations.)
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 13 May 2008 12:33:38 +0100
+
+openssh (1:4.7p1-8) unstable; urgency=high
+
+  * Fill in CVE identifier for security vulnerability fixed in 1:4.7p1-5.
+  * Rename KeepAlive to TCPKeepAlive in sshd_config, cleaning up from old
+    configurations (LP: #211400).
+  * Tweak scp's reporting of filenames in verbose mode to be a bit less
+    confusing with spaces (thanks, Nicolas Valcárcel; LP: #89945).
+  * Backport from 4.9p1:
+    - CVE-2008-1657: Ignore ~/.ssh/rc if a sshd_config ForceCommand is
+      specified.
+    - Add no-user-rc authorized_keys option to disable execution of
+      ~/.ssh/rc.
+  * Backport from Simon Wilkinson's GSSAPI key exchange patch for 5.0p1:
+    - Add code to actually implement GSSAPIStrictAcceptorCheck, which had
+      somehow been omitted from a previous version of this patch (closes:
+      #474246).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 06 Apr 2008 12:34:19 +0100
+
+openssh (1:4.7p1-7) unstable; urgency=low
+
+  * Ignore errors writing to oom_adj (closes: #473573).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 31 Mar 2008 16:24:44 +0100
+
+openssh (1:4.7p1-6) unstable; urgency=low
+
+  * Disable the Linux kernel's OOM-killer for the sshd parent; tweak
+    SSHD_OOM_ADJUST in /etc/default/ssh to change this (closes: #341767).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 30 Mar 2008 21:14:12 +0100
+
+openssh (1:4.7p1-5) unstable; urgency=low
+
+  * Recommends: xauth rather than Suggests: xbase-clients.
+  * Document in ssh(1) that '-S none' disables connection sharing
+    (closes: #471437).
+  * Patch from Red Hat / Fedora:
+    - CVE-2008-1483: Don't use X11 forwarding port which can't be bound on
+      all address families, preventing hijacking of X11 forwarding by
+      unprivileged users when both IPv4 and IPv6 are configured (closes:
+      #463011).
+  * Use printf rather than echo -en (a bashism) in openssh-server.config and
+    openssh-server.preinst.
+  * debconf template translations:
+    - Update Finnish (thanks, Esko Arajärvi; closes: #468563).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 22 Mar 2008 12:37:00 +0000
+
+openssh (1:4.7p1-4) unstable; urgency=low
+
+  [ Caleb Case ]
+  * Fix configure detection of getseuserbyname and
+    get_default_context_with_level (closes: #465614, LP: #188136).
+
+  [ Colin Watson ]
+  * Include the autogenerated debian/copyright in the source package.
+  * Move /etc/pam.d/ssh to /etc/pam.d/sshd, allowing us to stop defining
+    SSHD_PAM_SERVICE (closes: #255870).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 13 Feb 2008 18:18:52 +0000
+
+openssh (1:4.7p1-3) unstable; urgency=low
+
+  * Improve grammar of ssh-askpass-gnome description.
+  * Backport from upstream:
+    - Use the correct packet maximum sizes for remote port and agent
+      forwarding. Prevents the server from killing the connection if too
+      much data is queued and an excessively large packet gets sent
+      (https://bugzilla.mindrot.org/show_bug.cgi?id=1360).
+  * Allow passing temporary daemon parameters on the init script's command
+    line, e.g. '/etc/init.d/ssh start "-o PermitRootLogin=yes"' (thanks,
+    Marc Haber; closes: #458547).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 01 Feb 2008 21:59:59 +0000
+
+openssh (1:4.7p1-2) unstable; urgency=low
+
+  * Adjust many relative links in faq.html to point to
+    http://www.openssh.org/ (thanks, Dan Jacobson; mentioned in #459807).
+  * Pass --with-mantype=doc to configure rather than build-depending on
+    groff (closes: #460121).
+  * Add armel to architecture list for libselinux1-dev build-dependency
+    (closes: #460136).
+  * Drop source-compatibility with Debian 3.0:
+    - Remove support for building with GNOME 1. This allows simplification
+      of our GNOME build-dependencies (see #460136).
+    - Remove hacks to support the old PAM configuration scheme.
+    - Remove compatibility for building without po-debconf.
+  * Build-depend on libgtk2.0-dev rather than libgnomeui-dev. As far as I
+    can see, the GTK2 version of ssh-askpass-gnome has never required
+    libgnomeui-dev.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 11 Jan 2008 00:14:10 +0000
+
+openssh (1:4.7p1-1) unstable; urgency=low
+
+  * New upstream release (closes: #453367).
+    - CVE-2007-4752: Prevent ssh(1) from using a trusted X11 cookie if
+      creation of an untrusted cookie fails; found and fixed by Jan Pechanec
+      (closes: #444738).
+    - sshd(8) in new installations defaults to SSH Protocol 2 only. Existing
+      installations are unchanged.
+    - The SSH channel window size has been increased, and both ssh(1)
+      sshd(8) now send window updates more aggressively. These improves
+      performance on high-BDP (Bandwidth Delay Product) networks.
+    - ssh(1) and sshd(8) now preserve MAC contexts between packets, which
+      saves 2 hash calls per packet and results in 12-16% speedup for
+      arcfour256/hmac-md5.
+    - A new MAC algorithm has been added, UMAC-64 (RFC4418) as
+      "umac-64@openssh.com". UMAC-64 has been measured to be approximately
+      20% faster than HMAC-MD5.
+    - Failure to establish a ssh(1) TunnelForward is now treated as a fatal
+      error when the ExitOnForwardFailure option is set.
+    - ssh(1) returns a sensible exit status if the control master goes away
+      without passing the full exit status.
+    - When using a ProxyCommand in ssh(1), set the outgoing hostname with
+      gethostname(2), allowing hostbased authentication to work.
+    - Make scp(1) skip FIFOs rather than hanging (closes: #246774).
+    - Encode non-printing characters in scp(1) filenames. These could cause
+      copies to be aborted with a "protocol error".
+    - Handle SIGINT in sshd(8) privilege separation child process to ensure
+      that wtmp and lastlog records are correctly updated.
+    - Report GSSAPI mechanism in errors, for libraries that support multiple
+      mechanisms.
+    - Improve documentation for ssh-add(1)'s -d option.
+    - Rearrange and tidy GSSAPI code, removing server-only code being linked
+      into the client.
+    - Delay execution of ssh(1)'s LocalCommand until after all forwardings
+      have been established.
+    - In scp(1), do not truncate non-regular files.
+    - Improve exit message from ControlMaster clients.
+    - Prevent sftp-server(8) from reading until it runs out of buffer space,
+      whereupon it would exit with a fatal error (closes: #365541).
+    - pam_end() was not being called if authentication failed
+      (closes: #405041).
+    - Manual page datestamps updated (closes: #433181).
+  * Install the OpenSSH FAQ in /usr/share/doc/openssh-client.
+    - Includes documentation on copying files with colons using scp
+      (closes: #303453).
+  * Create /var/run/sshd on start even if /etc/ssh/sshd_not_to_be_run exists
+    (closes: #453285).
+  * Fix "overriden" typo in ssh(1) (thanks, A. Costa; closes: #390699).
+  * Refactor debian/rules configure and make invocations to make development
+    easier.
+  * Remove the hideously old /etc/ssh/primes on upgrade (closes: #123013).
+  * Update moduli(5) to revision 1.11 from OpenBSD CVS.
+  * Document the non-default options we set as standard in ssh_config(5) and
+    sshd_config(5) (closes: #327886, #345628).
+  * Recode LICENCE to UTF-8 when concatenating it to debian/copyright.
+  * Override desktop-file-but-no-dh_desktop-call lintian warning; the
+    .desktop file is intentionally not installed (see 1:3.8.1p1-10).
+  * Update copyright dates for Kerberos patch in debian/copyright.head.
+  * Policy version 3.7.3: no changes required.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 24 Dec 2007 16:43:02 +0000
+
+openssh (1:4.6p1-7) unstable; urgency=low
+
+  * Don't build PIE executables on m68k (closes: #451192).
+  * Use autotools-dev's recommended configure --build and --host options.
+  * Adjust README.Debian to suggest mailing debian-ssh@lists.debian.org
+    rather than Matthew.
+  * Check whether deluser exists in postrm (closes: #454085).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 03 Dec 2007 11:11:02 +0000
+
+openssh (1:4.6p1-6) unstable; urgency=low
+
+  * Remove blank line between head comment and first template in
+    debian/openssh-server.templates.master; apparently it confuses some
+    versions of debconf.
+  * Install authorized_keys(5) as a symlink to sshd(8) (thanks, Tomas
+    Pospisek; closes: #441817).
+  * Discard error output from dpkg-query in preinsts, in case the ssh
+    metapackage is not installed.
+  * Fix sshd/inittab advice in README.Debian to account for rc.d movement
+    (closes: #450632).
+  * Suppress error from debian/rules if lsb-release is not installed.
+  * Don't ignore errors from 'make -C contrib clean'.
+  * Adjust categories in ssh-askpass-gnome.desktop to comply with the
+    Desktop Menu Specification.
+  * debconf template translations:
+    - Add Slovak (thanks, Ivan Masár; closes: #441690).
+    - Update Brazilian Portuguese (thanks, Eder L. Marques;
+      closes: #447145).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 12 Nov 2007 11:47:28 +0000
+
+openssh (1:4.6p1-5) unstable; urgency=low
+
+  * Identify ssh as a metapackage rather than a transitional package. It's
+    still useful as a quick way to install both the client and the server.
+  * ssh-copy-id now checks the exit status of ssh-add -L (thanks, Adeodato
+    Simó; closes: #221675).
+  * ssh-copy-id no longer prints the output of expr (thanks, Peter
+    Eisentraut; closes: #291534).
+  * ssh-copy-id defaults to ~/.ssh/id_rsa.pub rather than
+    ~/.ssh/identity.pub, in line with ssh-keygen (thanks, Greg Norris;
+    closes: #234627).
+  * Build-depend on libselinux1-dev on lpia.
+  * openssh-client Suggests: keychain.
+  * debconf template translations:
+    - Update Catalan (thanks, Jordà Polo; closes: #431970).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 30 Jul 2007 09:34:38 +0100
+
+openssh (1:4.6p1-4) unstable; urgency=low
+
+  * Don't build PIE executables on hppa, as they crash.
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 05 Jul 2007 11:06:54 +0100
+
+openssh (1:4.6p1-3) unstable; urgency=low
+
+  * Only build PIE executables on Linux and NetBSD (closes: #430455).
+  * Fix broken switch fallthrough when SELinux is running in permissive mode
+    (closes: #430838).
+  * Document that HashKnownHosts may break tab-completion (closes: #430154).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 29 Jun 2007 07:15:38 +0100
+
+openssh (1:4.6p1-2) unstable; urgency=low
+
+  * Fix ordering of SYSLOG_LEVEL_QUIET and SYSLOG_LEVEL_FATAL.
+  * Clarify that 'ssh -q -q' still prints errors caused by bad arguments
+    (i.e. before the logging system is initialised).
+  * Suppress "Connection to <host> closed" and "Connection to master closed"
+    messages at loglevel SILENT (thanks, Jaap Eldering; closes: #409788).
+  * Suppress "Pseudo-terminal will not be allocated because stdin is not a
+    terminal" message at loglevels QUIET and SILENT (closes: #366814).
+  * Document the SILENT loglevel in sftp-server(8), ssh_config(5), and
+    sshd_config(5).
+  * Add try-restart action to init script.
+  * Add /etc/network/if-up.d/openssh-server to restart sshd when new
+    interfaces appear (LP: #103436).
+  * Backport from upstream:
+    - Move C/R -> kbdint special case to after the defaults have been
+      loaded, which makes ChallengeResponse default to yes again. This was
+      broken by the Match changes and not fixed properly subsequently
+      (closes: #428968).
+    - Silence spurious error messages from hang-on-exit fix
+      (http://bugzilla.mindrot.org/show_bug.cgi?id=1306, closes: #429531).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 20 Jun 2007 11:52:44 +0100
+
+openssh (1:4.6p1-1) unstable; urgency=low
+
+  * New upstream release (closes: #395507, #397961, #420035). Important
+    changes not previously backported to 4.3p2:
+    - 4.4/4.4p1 (http://www.openssh.org/txt/release-4.4):
+      + On portable OpenSSH, fix a GSSAPI authentication abort that could be
+        used to determine the validity of usernames on some platforms.
+      + Implemented conditional configuration in sshd_config(5) using the
+        "Match" directive. This allows some configuration options to be
+        selectively overridden if specific criteria (based on user, group,
+        hostname and/or address) are met. So far a useful subset of
+        post-authentication options are supported and more are expected to
+        be added in future releases.
+      + Add support for Diffie-Hellman group exchange key agreement with a
+        final hash of SHA256.
+      + Added a "ForceCommand" directive to sshd_config(5). Similar to the
+        command="..." option accepted in ~/.ssh/authorized_keys, this forces
+        the execution of the specified command regardless of what the user
+        requested. This is very useful in conjunction with the new "Match"
+        option.
+      + Add a "PermitOpen" directive to sshd_config(5). This mirrors the
+        permitopen="..." authorized_keys option, allowing fine-grained
+        control over the port-forwardings that a user is allowed to
+        establish.
+      + Add optional logging of transactions to sftp-server(8).
+      + ssh(1) will now record port numbers for hosts stored in
+        ~/.ssh/known_hosts when a non-standard port has been requested
+        (closes: #50612).
+      + Add an "ExitOnForwardFailure" option to cause ssh(1) to exit (with a
+        non-zero exit code) when requested port forwardings could not be
+        established.
+      + Extend sshd_config(5) "SubSystem" declarations to allow the
+        specification of command-line arguments.
+      + Replacement of all integer overflow susceptible invocations of
+        malloc(3) and realloc(3) with overflow-checking equivalents.
+      + Many manpage fixes and improvements.
+      + Add optional support for OpenSSL hardware accelerators (engines),
+        enabled using the --with-ssl-engine configure option.
+      + Tokens in configuration files may be double-quoted in order to
+        contain spaces (closes: #319639).
+      + Move a debug() call out of a SIGCHLD handler, fixing a hang when the
+        session exits very quickly (closes: #307890).
+      + Fix some incorrect buffer allocation calculations (closes: #410599).
+      + ssh-add doesn't ask for a passphrase if key file permissions are too
+        liberal (closes: #103677).
+      + Likewise, ssh doesn't ask either (closes: #99675).
+    - 4.6/4.6p1 (http://www.openssh.org/txt/release-4.6):
+      + sshd now allows the enabling and disabling of authentication methods
+        on a per user, group, host and network basis via the Match directive
+        in sshd_config.
+      + Fixed an inconsistent check for a terminal when displaying scp
+        progress meter (closes: #257524).
+      + Fix "hang on exit" when background processes are running at the time
+        of exit on a ttyful/login session (closes: #88337).
+  * Update to current GSSAPI patch from
+    http://www.sxw.org.uk/computing/patches/openssh-4.6p1-gsskex-20070312.patch;
+    install ChangeLog.gssapi.
+  * Build the .deb --with-ssl-engine (closes: #408027, LP: #119295).
+  * Use LSB functions in init scripts, and add an LSB-style header (partly
+    from Ubuntu and partly thanks to Christian Perrier; closes: #389038).
+  * Move init script start links to S16, move rc1 stop link to K84, and
+    remove rc0 and rc6 stop links altogether (the last part from Ubuntu;
+    closes: #122188).
+  * Emit a slightly more informative message from the init script if
+    /dev/null has somehow become not a character device (closes: #369964).
+  * Belatedly build-depend on zlib1g-dev (>= 1:1.2.3-1) (closes: #333447).
+  * Merge from Ubuntu:
+    - Build position-independent executables (only for debs, not for udebs)
+      to take advantage of address space layout randomisation.
+    - If building on Ubuntu, add /sbin, /usr/sbin, and /usr/local/sbin to
+      the default path.
+  * Use ${binary:Version} rather than ${Source-Version} in openssh-server ->
+    openssh-client dependency.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 13 Jun 2007 00:28:26 +0100
+
+openssh (1:4.3p2-11) unstable; urgency=low
+
+  * It's been four and a half years now since I took over as "temporary"
+    maintainer, so the Maintainer field is getting a bit inaccurate. Set
+    Maintainer to debian-ssh@lists.debian.org and leave Matthew and myself
+    as Uploaders.
+  * Use dpkg-query to fetch conffile md5sums rather than parsing
+    /var/lib/dpkg/status directly.
+  * openssh-client Suggests: libpam-ssh (closes: #427840).
+  * Use 'start-stop-daemon --oknodo' so that openssh-server's init script
+    exits successfully if sshd is already running (closes: #426858).
+
+  * Apply results of debconf templates and package descriptions review by
+    debian-l10n-english (closes: #420107, #420742).
+  * debconf template translations:
+    - Update Dutch (thanks, Machteld de Kok; closes: #419260).
+    - Update Norwegian Bokmål (thanks, Bjørn Steensrud; closes: #420630).
+    - Update Galician (thanks, Jacobo Tarrio; closes: #420635).
+    - Update Spanish (thanks, Javier Fernández-Sanguino Peña;
+      closes: #420651).
+    - Update Swedish (thanks, Daniel Nylander; closes: #420663).
+    - Add Bulgarian (thanks, Damyan Ivanov; closes: #420703).
+    - Add Tamil (thanks, Tirumurti Vasudevan; closes: #420739).
+    - Update German (thanks, Helge Kreutzmann; closes: #420743).
+    - Update Japanese (thanks, Kenshi Muto; closes: #420946).
+    - Add Basque (thanks, Piarres Beobide; closes: #421238).
+    - Update Italian (thanks, Luca Monducci; closes: #421348).
+    - Update Czech (thanks, Miroslav Kure; closes: #421484).
+    - Update Romanian (thanks, Igor Stirbu; closes: #421760).
+    - Update Russian (thanks, Yuriy Talakan' and Sergey Alyoshin;
+      closes: #420862).
+    - Update Dutch (thanks, Bart Cornelis; closes: #422767).
+    - Update Portuguese (thanks, Ricardo Silva; closes: #423112).
+    - Update French (thanks, Christian Perrier).
+    - Add Korean (thanks, Sunjae Park; closes: #424008).
+    - Update Vietnamese (thanks, Clytie Siddall; closes: #426991).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 10 Jun 2007 08:59:42 +0100
+
+openssh (1:4.3p2-10) unstable; urgency=low
+
+  * Multiply openssh-client-udeb's Installer-Menu-Item by 100.
+  * Increase MAX_SESSIONS to 64.
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 10 Apr 2007 19:17:20 +0100
+
+openssh (1:4.3p2-9) unstable; urgency=high
+
+  [ Russ Allbery ]
+  * Fix GSSAPIKeyExchange configuration file handling logic in ssh-krb5
+    (closes: #404863).
+  * Fix uncommenting of GSSAPI options by ssh-krb5 (closes: #407766).
+
+  [ Colin Watson ]
+  * debconf template translations:
+    - Add Norwegian Bokmål (thanks, Bjørn Steensrud; closes: #412330).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  5 Mar 2007 16:13:50 +0000
+
+openssh (1:4.3p2-8) unstable; urgency=medium
+
+  [ Vincent Untz ]
+  * Give the ssh-askpass-gnome window a default icon; remove unnecessary
+    icon extension from .desktop file (closes:
+    https://launchpad.net/bugs/27152).
+
+  [ Colin Watson ]
+  * Drop versioning on ssh/ssh-krb5 Replaces, as otherwise it isn't
+    sufficient to replace conffiles (closes: #402804).
+  * Make GSSAPICleanupCreds a compatibility alias for
+    GSSAPICleanupCredentials. Mark GSSUseSessionCCache and
+    GSSAPIUseSessionCredCache as known-but-unsupported options, and migrate
+    away from them on upgrade.
+  * It turns out that the people who told me that removing a conffile in the
+    preinst was sufficient to have dpkg replace it without prompting when
+    moving a conffile between packages were very much mistaken. As far as I
+    can tell, the only way to do this reliably is to write out the desired
+    new text of the conffile in the preinst. This is gross, and requires
+    shipping the text of all conffiles in the preinst too, but there's
+    nothing for it. Fortunately this nonsense is only required for smooth
+    upgrades from sarge.
+  * debconf template translations:
+    - Add Romanian (thanks, Stan Ioan-Eugen; closes: #403528).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 23 Dec 2006 18:38:33 +0000
+
+openssh (1:4.3p2-7) unstable; urgency=medium
+
+  [ Colin Watson ]
+  * Ignore errors from usermod when changing sshd's shell, since it will
+    fail if the sshd user is not local (closes: #398436).
+  * Remove version control tags from /etc/ssh/moduli and /etc/ssh/ssh_config
+    to avoid unnecessary conffile resolution steps for administrators
+    (thanks, Jari Aalto; closes: #335259).
+  * Fix quoting error in configure.ac and regenerate configure (thanks, Ben
+    Pfaff; closes: #391248).
+  * When installing openssh-client or openssh-server from scratch, remove
+    any unchanged conffiles from the pre-split ssh package to work around a
+    bug in sarge's dpkg (thanks, Justin Pryzby and others; closes: #335276).
+
+  [ Russ Allbery ]
+  * Create transitional ssh-krb5 package which enables GSSAPI configuration
+    in sshd_config (closes: #390986).
+  * Default client to attempting GSSAPI authentication.
+  * Remove obsolete GSSAPINoMICAuthentication from sshd_config if it's
+    found.
+  * Add ssh -K option, the converse of -k, to enable GSSAPI credential
+    delegation (closes: #401483).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed,  6 Dec 2006 23:00:49 +0000
+
+openssh (1:4.3p2-6) unstable; urgency=low
+
+  * Acknowledge NMU (thanks, Manoj; closes: #394795).
+  * Backport from 4.5p1:
+    - Fix a bug in the sshd privilege separation monitor that weakened its
+      verification of successful authentication. This bug is not known to be
+      exploitable in the absence of additional vulnerabilities.
+  * openssh-server Suggests: molly-guard (closes: #395473).
+  * debconf template translations:
+    - Update German (thanks, Helge Kreutzmann; closes: #395947).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 15 Nov 2006 00:07:32 +0000
+
+openssh (1:4.3p2-5.1) unstable; urgency=low
+
+  * NMU to update SELinux patch, bringing it in line with current selinux
+    releases.  The patch for this NMU is simply the Bug#394795 patch, 
+    and no other changes.                       (closes: #394795)
+
+ -- Manoj Srivastava <srivasta@debian.org>  Mon,  23 Oct 2006 14:11:24 -0500
+
+openssh (1:4.3p2-5) unstable; urgency=low
+
+  * Remove ssh/insecure_telnetd check altogether (closes: #391081).
+  * debconf template translations:
+    - Update Danish (thanks, Claus Hindsgaul; closes: #390612).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu,  5 Oct 2006 09:04:19 +0100
+
+openssh (1:4.3p2-4) unstable; urgency=high
+
+  * Backport from 4.4p1 (since I don't have an updated version of the GSSAPI
+    patch yet):
+    - CVE-2006-4924: Fix a pre-authentication denial of service found by
+      Tavis Ormandy, that would cause sshd(8) to spin until the login grace
+      time expired (closes: #389995).
+    - CVE-2006-5051: Fix an unsafe signal hander reported by Mark Dowd. The
+      signal handler was vulnerable to a race condition that could be
+      exploited to perform a pre-authentication denial of service. On
+      portable OpenSSH, this vulnerability could theoretically lead to
+      pre-authentication remote code execution if GSSAPI authentication is
+      enabled, but the likelihood of successful exploitation appears remote.
+
+  * Read /etc/default/locale as well as /etc/environment (thanks, Raphaël
+    Hertzog; closes: #369395).
+  * Remove no-longer-used ssh/insecure_rshd debconf template.
+  * Make ssh/insecure_telnetd Type: error (closes: #388946).
+
+  * debconf template translations:
+    - Update Portuguese (thanks, Rui Branco; closes: #381942).
+    - Update Spanish (thanks, Javier Fernández-Sanguino Peña;
+      closes: #382966).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 29 Sep 2006 16:28:24 +0100
+
+openssh (1:4.3p2-3) unstable; urgency=low
+
+  * Document KeepAlive->TCPKeepAlive renaming in sshd_config(5) (closes:
+    https://launchpad.net/bugs/50702).
+  * Change sshd user's shell to /usr/sbin/nologin (closes: #366541).
+    Introduces dependency on passwd for usermod.
+  * debconf template translations:
+    - Update French (thanks, Denis Barbier; closes: #368503).
+    - Update Dutch (thanks, Bart Cornelis; closes: #375100).
+    - Update Japanese (thanks, Kenshi Muto; closes: #379950).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 27 Jul 2006 00:12:36 +0100
+
+openssh (1:4.3p2-2) unstable; urgency=low
+
+  * Include commented-out pam_access example in /etc/pam.d/ssh.
+  * On '/etc/init.d/ssh restart', create /var/run/sshd before checking the
+    server configuration, as otherwise 'sshd -t' will complain about the
+    lack of /var/run/sshd (closes: https://launchpad.net/bugs/45234).
+  * debconf template translations:
+    - Update Russian (thanks, Yuriy Talakan'; closes: #367143).
+    - Update Czech (thanks, Miroslav Kure; closes: #367161).
+    - Update Italian (thanks, Luca Monducci; closes: #367186).
+    - Update Galician (thanks, Jacobo Tarrio; closes: #367318).
+    - Update Swedish (thanks, Daniel Nylander; closes: #367971).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 19 May 2006 09:14:27 +0100
+
+openssh (1:4.3p2-1) unstable; urgency=low
+
+  * New upstream release (closes: #361032).
+    - CVE-2006-0225: scp (as does rcp, on which it is based) invoked a
+      subshell to perform local to local, and remote to remote copy
+      operations. This subshell exposed filenames to shell expansion twice;
+      allowing a local attacker to create filenames containing shell
+      metacharacters that, if matched by a wildcard, could lead to execution
+      of attacker-specified commands with the privilege of the user running
+      scp (closes: #349645).
+    - Add support for tunneling arbitrary network packets over a connection
+      between an OpenSSH client and server via tun(4) virtual network
+      interfaces. This allows the use of OpenSSH (4.3+) to create a true VPN
+      between the client and server providing real network connectivity at
+      layer 2 or 3. This feature is experimental.
+    - Reduce default key length for new DSA keys generated by ssh-keygen
+      back to 1024 bits. DSA is not specified for longer lengths and does
+      not fully benefit from simply making keys longer. As per FIPS 186-2
+      Change Notice 1, ssh-keygen will refuse to generate a new DSA key
+      smaller or larger than 1024 bits.
+    - Fixed X forwarding failing to start when the X11 client is executed in
+      background at the time of session exit.
+    - Change ssh-keygen to generate a protocol 2 RSA key when invoked
+      without arguments (closes: #114894).
+    - Fix timing variance for valid vs. invalid accounts when attempting
+      Kerberos authentication.
+    - Ensure that ssh always returns code 255 on internal error
+      (closes: #259865).
+    - Cleanup wtmp files on SIGTERM when not using privsep.
+    - Set SO_REUSEADDR on X11 listeners to avoid problems caused by
+      lingering sockets from previous session (X11 applications can
+      sometimes not connect to 127.0.0.1:60xx) (closes:
+      https://launchpad.net/bugs/25528).
+    - Ensure that fds 0, 1 and 2 are always attached in all programs, by
+      duping /dev/null to them if necessary.
+    - Xauth list invocation had bogus "." argument.
+    - Remove internal assumptions on key exchange hash algorithm and output
+      length, preparing OpenSSH for KEX methods with alternate hashes.
+    - Ignore junk sent by a server before it sends the "SSH-" banner.
+    - Many manual page improvements.
+    - Lots of cleanups, including fixes to memory leaks on error paths and
+      possible crashes.
+  * Update to current GSSAPI patch from
+    http://www.sxw.org.uk/computing/patches/openssh-4.3p2-gsskex-20060223.patch
+    (closes: #352042).
+  * debian/rules: Resynchronise CFLAGS with that generated by configure.
+  * Restore pam_nologin to /etc/pam.d/ssh; sshd no longer checks this itself
+    when PAM is enabled, but relies on PAM to do it.
+  * Rename KeepAlive to TCPKeepAlive in default sshd_config
+    (closes: #349896).
+  * Rephrase ssh/new_config and ssh/encrypted_host_key_but_no_keygen debconf
+    templates to make boolean short descriptions end with a question mark
+    and to avoid use of the first person.
+  * Ship README.tun.
+  * Policy version 3.7.2: no changes required.
+  * debconf template translations:
+    - Update Italian (thanks, Luca Monducci; closes: #360348).
+    - Add Galician (thanks, Jacobo Tarrio; closes: #361220).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 12 May 2006 12:48:24 +0100
+
+openssh (1:4.2p1-8) unstable; urgency=low
+
+  [ Frans Pop ]
+  * Use udeb support introduced in debhelper 4.2.0 (available in sarge)
+    rather than constructing udebs by steam.
+  * Require debhelper 5.0.22, which generates correct shared library
+    dependencies for udebs (closes: #360068). This build-dependency can be
+    ignored if building on sarge.
+
+  [ Colin Watson ]
+  * Switch to debhelper compatibility level 4, since we now require
+    debhelper 4 even on sarge anyway for udeb support.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 31 Mar 2006 09:44:55 +0100
+
+openssh (1:4.2p1-7) unstable; urgency=low
+
+  * I accidentally applied the default $PATH change in 1:4.2p1-6 to the udeb
+    rather than the deb. Fixed.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed,  1 Mar 2006 16:19:00 +0000
+
+openssh (1:4.2p1-6) unstable; urgency=low
+
+  * Sync default values of $PATH from shadow 1:4.0.12-6, adding /usr/bin/X11
+    to the normal and superuser paths and /usr/games to the normal path.
+  * When the client receives a signal, don't fatal() with "Killed by signal
+    %d." (which produces unhelpful noise on stderr and causes confusion for
+    users of some applications that wrap ssh); instead, generate a debug
+    message and exit with the traditional status (closes: #313371).
+  * debconf template translations:
+    - Add Swedish (thanks, Daniel Nylander; closes: #333133).
+    - Update Spanish (thanks, Javier Fernández-Sanguino Peña;
+      closes: #341371).
+    - Correct erroneously-changed Last-Translator headers in Greek and
+      Spanish translations.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 20 Feb 2006 16:50:55 +0000
+
+openssh (1:4.2p1-5) unstable; urgency=low
+
+  * Add a CVE name to the 1:4.0p1-1 changelog entry.
+  * Build-depend on libselinux1-dev on armeb.
+  * Only send GSSAPI proposal if GSSAPIAuthentication is enabled.
+  * Build-depend on libssl-dev (>= 0.9.8-1) to cope with surprise OpenSSL
+    transition, since otherwise who knows what the buildds will do. If
+    you're building openssh yourself, you can safely ignore this and use an
+    older libssl-dev.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri,  7 Oct 2005 12:23:42 +0100
+
+openssh (1:4.2p1-4) unstable; urgency=low
+
+  * Initialise token to GSS_C_EMPTY_BUFFER in ssh_gssapi_check_mechanism
+    (closes: #328606).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 16 Sep 2005 12:50:16 +0100
+
+openssh (1:4.2p1-3) unstable; urgency=low
+
+  * Add prototype for ssh_gssapi_server_mechanisms (closes: #328372).
+  * Interoperate with ssh-krb5 << 3.8.1p1-1 servers, which used a slightly
+    different version of the gssapi authentication method (thanks, Aaron M.
+    Ucko; closes: #328388).
+  * Explicitly tell po2debconf to use the 'popular' output encoding, so that
+    the woody-compatibility hack works even with po-debconf 0.9.0.
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 15 Sep 2005 09:28:21 +0100
+
+openssh (1:4.2p1-2) unstable; urgency=low
+
+  * Annotate 1:4.2p1-1 changelog with CVE references.
+  * Add remaining pieces of Kerberos support (closes: #152657, #275472):
+    - Add GSSAPI key exchange support from
+      http://www.sxw.org.uk/computing/patches/openssh.html (thanks, Stephen
+      Frost).
+    - Build-depend on libkrb5-dev and configure --with-kerberos5=/usr.
+    - openssh-client and openssh-server replace ssh-krb5.
+    - Update commented-out Kerberos/GSSAPI options in default sshd_config.
+    - Fix HAVE_GSSAPI_KRB5_H/HAVE_GSSAPI_GSSAPI_KRB5_H typos in
+      gss-serv-krb5.c.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 14 Sep 2005 18:28:49 +0100
+
+openssh (1:4.2p1-1) unstable; urgency=low
+
+  * New upstream release.
+    - SECURITY (CAN-2005-2797): Fix a bug introduced in OpenSSH 4.0 that
+      caused GatewayPorts to be incorrectly activated for dynamic ("-D")
+      port forwardings when no listen address was explicitly specified
+      (closes: #326065).
+    - SECURITY (CAN-2005-2798): Fix improper delegation of GSSAPI
+      credentials. This code is only built in openssh-krb5, not openssh, but
+      I mention the CVE reference here anyway for completeness.
+    - Add a new compression method ("Compression delayed") that delays zlib
+      compression until after authentication, eliminating the risk of zlib
+      vulnerabilities being exploited by unauthenticated users. Note that
+      users of OpenSSH versions earlier than 3.5 will need to disable
+      compression on the client or set "Compression yes" (losing this
+      security benefit) on the server.
+    - Increase the default size of new RSA/DSA keys generated by ssh-keygen
+      from 1024 to 2048 bits (closes: #181162).
+    - Many bugfixes and improvements to connection multiplexing.
+    - Don't pretend to accept $HOME (closes: #208648).
+  * debian/rules: Resynchronise CFLAGS with that generated by configure.
+  * openssh-client and openssh-server conflict with pre-split ssh to avoid
+    problems when ssh is left un-upgraded (closes: #324695).
+  * Set X11Forwarding to yes in the default sshd_config (new installs only).
+    At least when X11UseLocalhost is turned on, which is the default, the
+    security risks of using X11 forwarding are risks to the client, not to
+    the server (closes: #320104).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 14 Sep 2005 15:16:14 +0100
+
+openssh (1:4.1p1-7) unstable; urgency=low
+
+  * Do the IDEA host key check on a temporary file to avoid altering
+    /etc/ssh/ssh_host_key itself (closes: #312312).
+  * Work around the ssh-askpass alternative somehow ending up in manual mode
+    pointing to the obsolete /usr/lib/ssh/gnome-ssh-askpass.
+  * Add GNU/kFreeBSD support (thanks, Aurelien Jarno; closes: #318113).
+  * Fix XSIish uses of 'test' in openssh-server.preinst.
+  * Policy version 3.6.2: no changes required.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri,  2 Sep 2005 16:18:11 +0100
+
+openssh (1:4.1p1-6) unstable; urgency=low
+
+  * Fix one-character typo that meant the binaries in openssh-client and
+    openssh-server got recompiled with the wrong options during
+    'debian/rules install' (closes: #317088, #317238, #317241).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu,  7 Jul 2005 10:56:16 +0100
+
+openssh (1:4.1p1-5) unstable; urgency=low
+
+  * Build-depend on libselinux1-dev on ppc64 too (closes: #314625).
+  * Drop priority of ssh to extra to match the override file.
+  * Make /usr/share/doc/openssh-server and /usr/share/doc/ssh symlinks to
+    /usr/share/doc/openssh-client (closes: #314745).
+  * Ship README.dns (closes: #284874).
+  * Disable btmp logging, since Debian's /var/log/btmp has inappropriate
+    permissions (closes: #314956).
+  * Allow ~/.ssh/config to be group-writable, provided that the group in
+    question contains only the file's owner (closes: #314347).
+  * debconf template translations:
+    - Update Brazilian Portuguese (thanks, André Luís Lopes;
+      closes: #315477).
+    - Add Vietnamese (thanks, Clytie Siddall; closes: #316636).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun,  3 Jul 2005 17:08:08 +0100
+
+openssh (1:4.1p1-4) unstable; urgency=low
+
+  * openssh-client and openssh-server conflict with ssh-krb5, as ssh-krb5
+    only conflicts with ssh (closes: #312475).
+  * SELinux support (thanks, Manoj Srivastava; closes: #308555):
+    - Added SELinux capability, and turned it on be default. Added
+      restorecon calls in preinst and postinst (should not matter if the
+      machine is not SELinux aware). By and large, the changes made should
+      have no effect unless the rules file calls --with-selinux; and even
+      then there should be no performance hit for machines not actively
+      running SELinux.
+    - Modified the preinst and postinst to call restorecon to set the
+      security context for the generated public key files.
+    - Added a comment to /etc/pam.d/ssh to indicate that an SELinux system
+      may want to also include pam_selinux.so.
+  * Re-enable ssh-askpass-gnome on the Hurd, now that its build-dependencies
+    are available.
+  * Restore /usr/lib/sftp-server temporarily, as a symlink to
+    /usr/lib/openssh/sftp-server (closes: #312891).
+  * Switch to debhelper compatibility level 3, since 2 is deprecated.
+  * debconf template translations:
+    - Update German (thanks, Jens Seidel; closes: #313949).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 17 Jun 2005 14:20:20 +0100
+
+openssh (1:4.1p1-3) unstable; urgency=low
+
+  * Upload to unstable.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  6 Jun 2005 22:28:33 +0100
+
+openssh (1:4.1p1-2) experimental; urgency=low
+
+  * Drop debconf support for allowing SSH protocol 1, which is discouraged
+    and has not been the default since openssh 1:3.0.1p1-1. Users who need
+    this should edit sshd_config instead (closes: #147212).
+  * Since ssh-keysign isn't used by default (you need to set
+    EnableSSHKeysign to "yes" in /etc/ssh/ssh_config), having a debconf
+    question to ask whether it should be setuid is overkill, and the
+    question text had got out of date anyway. Remove this question, ship
+    ssh-keysign setuid in openssh-client.deb, and set a statoverride if the
+    debconf question was previously set to false.
+  * Add lintian overrides for the above (setuid-binary,
+    no-debconf-templates).
+  * Fix picky lintian errors about slogin symlinks.
+  * Fix DEB_HOST_ARCH_OS/DEB_HOST_GNU_SYSTEM compatibility handling.
+  * Apply Linux 2.2 workaround (see #239999) only on Linux.
+
+ -- Colin Watson <cjwatson@debian.org>  Thu,  2 Jun 2005 00:55:58 +0100
+
+openssh (1:4.1p1-1) experimental; urgency=low
+
+  * New upstream release.
+    - Normalise socket addresses returned by get_remote_hostname(), fixing
+      4-in-6 mapping issues with AllowUsers et al (closes: #192234).
+  * Take upstream's hint and disable the unsupported USE_POSIX_THREADS
+    (closes: #295757, #308868, and possibly others; may open other bugs).
+    Use PAM password authentication to avoid #278394. In future I may
+    provide two sets of binaries built with and without this option, since
+    it seems I can't win.
+  * Disable ChallengeResponseAuthentication in new installations, returning
+    to PasswordAuthentication by default, since it now supports PAM and
+    apparently works better with a non-threaded sshd (closes: #247521).
+  * openssh-server Suggests: rssh (closes: #233012).
+  * Change libexecdir to /usr/lib/openssh, and fix up various alternatives
+    and configuration files to match (closes: #87900, #151321).
+  * Fix up very old sshd_config files that refer to /usr/libexec/sftp-server
+    (closes: #141979).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 31 May 2005 01:33:33 +0100
+
+openssh (1:4.0p1-1) experimental; urgency=low
+
+  * New upstream release.
+    - Port-forwarding specifications now take optional bind addresses, and
+      the server allows client-specified bind addresses for remote port
+      forwardings when configured with "GatewayPorts clientspecified"
+      (closes: #87253, #192206).
+    - ssh and ssh-keyscan now support hashing of known_hosts files for
+      improved privacy (CAN-2005-2666). ssh-keygen has new options for
+      managing known_hosts files, which understand hashing.
+    - sftp supports command history and editing support using libedit
+      (closes: #287013).
+    - Have scp and sftp wait for the spawned ssh to exit before they exit
+      themselves, allowing ssh to restore terminal modes (closes: #257130).
+    - Improved the handling of bad data in authorized_keys files,
+      eliminating fatal errors on corrupt or very large keys; e.g. linefeeds
+      in keys only produce errors in auth.log now (closes: #220726).
+    - Add "command mode" to ssh connection multiplexing (closes: #303452).
+    - Mention $HOME/.hushlogin in sshd(8) FILES section (closes: #163933).
+  * Make gnome-ssh-askpass stay above other windows (thanks, Liyang HU;
+    closes: #296487).
+  * Remove obsolete and unnecessary ssh/forward_warning debconf note.
+  * Hurd build fixes (although sshd still doesn't work):
+    - Restore X forwarding fix from #102991, lost somewhere along the way.
+    - Link with -lcrypt.
+    - Link with -lpthread rather than -pthread.
+    - Don't build ssh-askpass-gnome on the Hurd, until GNOME is available to
+      satisfy build-dependencies.
+  * Drop workaround for #242462 on amd64; it's been fixed properly upstream.
+  * Enable HashKnownHosts by default. This only affects new entries; use
+    'ssh-keygen -H' to convert an entire known_hosts file to hashed format.
+  * Note in ssh_config(5) that the SetupTimeOut option is Debian-specific
+    (closes: #307069).
+  * debconf template translations:
+    - Update Czech (thanks, Miroslav Kure; closes: #298744).
+    - Update Finnish (thanks, Matti Pöllä; closes: #303787).
+    - Synchronise Spanish with sarge branch (thanks, Javier
+      Fernández-Sanguino Peña; closes: #298536).
+    - Add Ukrainian (thanks, Eugeniy Meshcheryakov; closes: #301852).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 26 May 2005 11:23:18 +0100
+
+openssh (1:3.9p1-3) experimental; urgency=low
+
+  * Explain how to run sshd from inittab in README.Debian (closes: #147360).
+  * Add debian/watch file.
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 18 Feb 2005 00:20:16 +0000
+
+openssh (1:3.9p1-2) experimental; urgency=low
+
+  * Remove pam_nologin from /etc/pam.d/ssh, as sshd's built-in support
+    appears to be sufficient and more useful (closes: #162996).
+  * Depend on debconf | debconf-2.0.
+  * Drop LoginGraceTime back to the upstream default of two minutes on new
+    installs (closes: #289573).
+  * debconf template translations from Ubuntu bug #1232:
+    - Update Greek (thanks, Logiotatidis George).
+    - Update Spanish (thanks, Santiago Erquicia).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 15 Jan 2005 12:37:54 +0000
+
+openssh (1:3.9p1-1) experimental; urgency=low
+
+  * New upstream release.
+    - PAM password authentication implemented again (closes: #238699,
+      #242119).
+    - Implemented the ability to pass selected environment variables between
+      the client and the server.
+    - Fix ssh-keyscan breakage when remote server doesn't speak SSH protocol
+      (closes: #228828).
+    - Fix res_query detection (closes: #242462).
+    - 'ssh -c' documentation improved (closes: #265627).
+  * Pass LANG and LC_* environment variables from the client by default, and
+    accept them to the server by default in new installs, although not on
+    upgrade (closes: #264024).
+  * Build ssh in binary-indep, not binary-arch (thanks, LaMont Jones).
+  * Expand on openssh-client package description (closes: #273831).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue,  4 Jan 2005 14:18:31 +0000
+
+openssh (1:3.8.1p1-14) experimental; urgency=low
+
+  * We use DH_COMPAT=2, so build-depend on debhelper (>= 2).
+  * Fix timing information leak allowing discovery of invalid usernames in
+    PAM keyboard-interactive authentication (backported from a patch by
+    Darren Tucker; closes: #281595).
+  * Make sure that there's a delay in PAM keyboard-interactive
+    authentication when PermitRootLogin is not set to yes and the correct
+    root password is entered (closes: #248747).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 28 Nov 2004 18:09:37 +0000
+
+openssh (1:3.8.1p1-13) experimental; urgency=low
+
+  * Enable threading for PAM, on Sam Hartman's advice (closes: #278394).
+  * debconf template translations:
+    - Update Dutch (thanks, cobaco; closes: #278715).
+  * Correct README.Debian's ForwardX11Trusted description (closes: #280190).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 12 Nov 2004 12:03:13 +0000
+
+openssh (1:3.8.1p1-12) experimental; urgency=low
+
+  * Preserve /etc/ssh/sshd_config ownership/permissions (closes: #276754).
+  * Shorten the version string from the form "OpenSSH_3.8.1p1 Debian
+    1:3.8.1p1-8.sarge.1" to "OpenSSH_3.8.1p1 Debian-8.sarge.1", as some SSH
+    implementations apparently have problems with the long version string.
+    This is of course a bug in those implementations, but since the extent
+    of the problem is unknown it's best to play safe (closes: #275731).
+  * debconf template translations:
+    - Add Finnish (thanks, Matti Pöllä; closes: #265339).
+    - Update Danish (thanks, Morten Brix Pedersen; closes: #275895).
+    - Update French (thanks, Denis Barbier; closes: #276703).
+    - Update Japanese (thanks, Kenshi Muto; closes: #277438).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 24 Oct 2004 19:21:17 +0100
+
+openssh (1:3.8.1p1-11) experimental; urgency=high
+
+  * Move sshd_config(5) to openssh-server, where it belongs.
+  * If PasswordAuthentication is disabled, then offer to disable
+    ChallengeResponseAuthentication too. The current PAM code will attempt
+    password-style authentication if ChallengeResponseAuthentication is
+    enabled (closes: #250369).
+  * This will ask a question of anyone who installed fresh with 1:3.8p1-2 or
+    later and then upgraded. Sorry about that ... for this reason, the
+    default answer is to leave ChallengeResponseAuthentication enabled.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed,  6 Oct 2004 14:28:20 +0100
+
+openssh (1:3.8.1p1-10) experimental; urgency=low
+
+  * Don't install the ssh-askpass-gnome .desktop file by default; I've had
+    too many GNOME people tell me it's the wrong thing to be doing. I've
+    left it in /usr/share/doc/ssh-askpass-gnome/examples/ for now.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 25 Aug 2004 18:18:14 +0100
+
+openssh (1:3.8.1p1-9) experimental; urgency=low
+
+  * Split the ssh binary package into openssh-client and openssh-server
+    (closes: #39741). openssh-server depends on openssh-client for some
+    common functionality; it didn't seem worth creating yet another package
+    for this. openssh-client is priority standard, openssh-server optional.
+  * New transitional ssh package, priority optional, depending on
+    openssh-client and openssh-server. May be removed once nothing depends
+    on it.
+  * When upgrading from ssh to openssh-{client,server}, it's very difficult
+    for the maintainer scripts to find out what version we're upgrading from
+    without dodgy dpkg hackery. I've therefore taken the opportunity to move
+    a couple of debconf notes into NEWS files, namely ssh/ssh2_keys_merged
+    and ssh/user_environment_tell.
+  * Add a heuristic to try to make sure the sshd_config upgrade to >= 3.7
+    happens even though we don't know what version we're upgrading from.
+  * Remove /etc/ssh/sshd_not_to_be_run on purge of openssh-server. For now
+    (until sarge+2) it's still honoured to avoid breaking existing
+    configurations, but the right approach is now to remove the
+    openssh-server package if you don't want to run the server. Add a NEWS
+    item to that effect.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  2 Aug 2004 20:48:54 +0100
+
+openssh (1:3.8.1p1-8.sarge.4) unstable; urgency=high
+
+  * Fix timing information leak allowing discovery of invalid usernames in
+    PAM keyboard-interactive authentication (backported from a patch by
+    Darren Tucker; closes: #281595).
+  * Make sure that there's a delay in PAM keyboard-interactive
+    authentication when PermitRootLogin is not set to yes and the correct
+    root password is entered (closes: #248747).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 28 Nov 2004 12:37:16 +0000
+
+openssh (1:3.8.1p1-8.sarge.3) unstable; urgency=low
+
+  * Enable threading for PAM, on Sam Hartman's advice (closes: #278394).
+  * debconf template translations:
+    - Update Dutch (thanks, cobaco; closes: #278715).
+  * Correct README.Debian's ForwardX11Trusted description (closes: #280190).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 12 Nov 2004 10:31:12 +0000
+
+openssh (1:3.8.1p1-8.sarge.2) unstable; urgency=low
+
+  * Preserve /etc/ssh/sshd_config ownership/permissions (closes: #276754).
+  * Shorten the version string from the form "OpenSSH_3.8.1p1 Debian
+    1:3.8.1p1-8.sarge.1" to "OpenSSH_3.8.1p1 Debian-8.sarge.1", as some SSH
+    implementations apparently have problems with the long version string.
+    This is of course a bug in those implementations, but since the extent
+    of the problem is unknown it's best to play safe (closes: #275731).
+  * debconf template translations:
+    - Add Finnish (thanks, Matti Pöllä; closes: #265339).
+    - Update Danish (thanks, Morten Brix Pedersen; closes: #275895).
+    - Update French (thanks, Denis Barbier; closes: #276703).
+    - Update Japanese (thanks, Kenshi Muto; closes: #277438).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 24 Oct 2004 17:57:14 +0100
+
+openssh (1:3.8.1p1-8.sarge.1) unstable; urgency=high
+
+  * If PasswordAuthentication is disabled, then offer to disable
+    ChallengeResponseAuthentication too. The current PAM code will attempt
+    password-style authentication if ChallengeResponseAuthentication is
+    enabled (closes: #250369).
+  * This will ask a question of anyone who installed fresh with 1:3.8p1-2 or
+    later and then upgraded. Sorry about that ... for this reason, the
+    default answer is to leave ChallengeResponseAuthentication enabled.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed,  6 Oct 2004 14:21:55 +0100
+
+openssh (1:3.8.1p1-8) unstable; urgency=high
+
+  * Matthew Vernon:
+    - Add a GPL exception to the licensing terms of the Debian patch
+      (closes: #211644).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 29 Jul 2004 13:28:47 +0100
+
+openssh (1:3.8.1p1-7) unstable; urgency=low
+
+  * Re-enable shadow password support in openssh-server-udeb, at Bastian
+    Blank's request (closes: #260800).
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 22 Jul 2004 10:56:06 +0100
+
+openssh (1:3.8.1p1-6) unstable; urgency=low
+
+  * Implement hack in
+    http://lists.debian.org/debian-boot/2004/07/msg01207.html to get
+    openssh-client-udeb to show up as a retrievable debian-installer
+    component.
+  * Generate host keys in postinst only if the relevant HostKey directives
+    are found in sshd_config (closes: #87946).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 21 Jul 2004 15:14:46 +0100
+
+openssh (1:3.8.1p1-5) unstable; urgency=medium
+
+  * Update German debconf template translation (thanks, Helge Kreutzmann;
+    closes: #252226).
+  * Remove Suggests: dnsutils, as it was only needed for
+    make-ssh-known-hosts (#93265), which has been replaced by ssh-keyscan.
+  * Disable shadow password support in openssh-server-udeb.
+  * Fix non-portable shell constructs in maintainer scripts, Makefile, and
+    ssh-copy-id (thanks, David Weinehall; closes: #258517).
+  * Apply patch from Darren Tucker to make the PAM authentication SIGCHLD
+    handler kill the PAM thread if its waitpid() call returns 0, as well as
+    the previous check for -1 (closes: #252676).
+  * Add scp and sftp to openssh-client-udeb. It might not be very 'u' any
+    more; oh well.
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 10 Jul 2004 13:57:27 +0100
+
+openssh (1:3.8.1p1-4) unstable; urgency=medium
+
+  * Kill off PAM thread if privsep slave dies (closes: #248125).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 28 May 2004 17:58:45 -0300
+
+openssh (1:3.8.1p1-3) unstable; urgency=low
+
+  * Add ssh-keygen to openssh-server-udeb.
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 20 May 2004 16:31:52 +0100
+
+openssh (1:3.8.1p1-2) unstable; urgency=low
+
+  * Add Catalan debconf template translation (thanks, Aleix Badia i Bosch;
+    closes: #248748).
+  * openssh-client-udeb and openssh-server-udeb depend on libnss-files-udeb
+    (not yet uploaded).
+  * Restore ssh-askpass-gnome binary, lost by mistake.
+  * Don't link against libnsl in udeb builds.
+
+ -- Colin Watson <cjwatson@debian.org>  Thu, 20 May 2004 11:15:58 +0100
+
+openssh (1:3.8.1p1-1) unstable; urgency=low
+
+  * New upstream release.
+    - Use a longer buffer for tty names in utmp (closes: #247538).
+  * Make sure there's a newline at the end of sshd_config before adding
+    'UsePAM yes' (closes: #244829).
+  * Generate a new .orig.tar.gz without RFC.nroff, and remove
+    /usr/share/doc/ssh/RFC.gz (closes: #211640). It isn't DFSG-free and only
+    documents the obsolete SSH1 protocol, not to mention that it was never a
+    real RFC but only an Internet-Draft. It's available from
+    http://www.free.lp.se/bamse/draft-ylonen-ssh-protocol-00.txt if you want
+    it for some reason.
+  * Add openssh-client-udeb and openssh-server-udeb binary packages for use
+    in debian-installer. They still need libnss_files to be supplied in udeb
+    form by glibc.
+  * Work around lack of res_query weak alias in libresolv on amd64 (see
+    #242462, awaiting real fix upstream).
+  * Fix grammar in sshd(8) (closes: #238753).
+  * Add .desktop file and icon for ssh-askpass-gnome (closes: #232333).
+  * Update Polish debconf template translation (thanks, Emil Nowak;
+    closes: #242808).
+  * Add Turkish debconf template translation (thanks, Recai Oktaş;
+    closes: #246068).
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 11 May 2004 23:38:10 +0100
+
+openssh (1:3.8p1-3) unstable; urgency=low
+
+  * Remove deprecated ReverseMappingCheck option from newly generated
+    sshd_config files (closes: #239987).
+  * Build everything apart from contrib in a subdirectory, to allow for
+    multiple builds.
+  * Some older kernels are missing setresuid() and setresgid(), so don't try
+    to use them. setreuid() and setregid() will do well enough for our
+    purposes (closes: #239999).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  5 Apr 2004 21:23:43 +0100
+
+openssh (1:3.8p1-2) unstable; urgency=medium
+
+  * Disable PasswordAuthentication for new installations (closes: #236810).
+  * Turn off the new ForwardX11Trusted by default, returning to the
+    semantics of 3.7 and earlier, since it seems immature and causes far too
+    many problems with existing setups. See README.Debian for details
+    (closes: #237021).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 10 Mar 2004 10:33:07 +0000
+
+openssh (1:3.8p1-1) unstable; urgency=low
+
+  * New upstream release (closes: #232281):
+    - New PAM implementation based on that in FreeBSD. This runs PAM session
+      modules before dropping privileges (closes: #132681, #150968).
+    - Since PAM session modules are run as root, we can turn pam_limits back
+      on by default, and it no longer spits out "Operation not permitted" to
+      syslog (closes: #171673).
+    - Password expiry works again (closes: #153235).
+    - 'ssh -q' suppresses login banner (closes: #134589).
+    - sshd doesn't lie to PAM about invalid usernames (closes: #157078).
+    - ssh-add prints key comment on each prompt (closes: #181869).
+    - Punctuation formatting fixed in man pages (closes: #191131).
+    - EnableSSHKeysign documented in ssh_config(5) (closes: #224457).
+  * Add 'UsePAM yes' to /etc/ssh/sshd_config on upgrade from versions older
+    than this, to maintain the standard Debian sshd configuration.
+  * Comment out PAMAuthenticationViaKbdInt and RhostsAuthentication in
+    sshd_config on upgrade. Neither option is supported any more.
+  * Privilege separation and PAM are now properly supported together, so
+    remove both debconf questions related to them and simply set it
+    unconditionally in newly generated sshd_config files (closes: #228838).
+  * ServerAliveInterval implemented upstream, so ProtocolKeepAlives is now a
+    compatibility alias. The semantics differ slightly, though; see
+    ssh_config(5) for details.
+  * Implement SSH1 support for ServerAliveInterval using SSH_MSG_IGNORE. As
+    documented in ssh_config(5), it's not as good as the SSH2 version.
+  * Remove -fno-builtin-log, -DHAVE_MMAP_ANON_SHARED, and
+    -D__FILE_OFFSET_BITS=64 compiler options, which are no longer necessary.
+  * Update config.guess and config.sub from autotools-dev 20040105.1.
+  * Darren Tucker:
+    - Reset signal status when starting pam auth thread, prevent hanging
+      during PAM keyboard-interactive authentications.
+    - Fix a non-security-critical segfault in PAM authentication.
+  * Add debconf template translations:
+    - Greek (thanks, Konstantinos Margaritis; closes: #232843).
+    - Italian (thanks, Renato Gini; closes: #234777).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat,  6 Mar 2004 18:43:44 +0000
+
+openssh (1:3.6.1p2-12) unstable; urgency=low
+
+  * Update Spanish debconf template translation (thanks, Javier
+    Fernández-Sanguino Peña; closes: #228242).
+  * Add debconf template translations:
+    - Czech (thanks, Miroslav Kure; closes: #230110).
+    - Simplified Chinese (thanks, Hiei Xu; closes: #230726).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 11 Feb 2004 09:37:57 +0000
+
+openssh (1:3.6.1p2-11) unstable; urgency=low
+
+  * Comment out pam_limits in default configuration, for now at least
+    (closes: #198254).
+  * Use invoke-rc.d (if it exists) to run the init script.
+  * Backport format string bug fix in sshconnect.c (closes: #225238).
+  * ssh-copy-id exits if ssh fails (closes: #215252).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun,  4 Jan 2004 18:59:21 +0000
+
+openssh (1:3.6.1p2-10) unstable; urgency=low
+
+  * Use --retry in init script when restarting rather than sleeping, to make
+    sure the old process is dead (thanks, Herbert Xu; closes: #212117).
+    Depend on dpkg (>= 1.9.0) for start-stop-daemon's --retry option.
+  * Update debconf template translations:
+    - Brazilian Portuguese (thanks, Andre Luis Lopes; closes: #219844).
+    - Danish (thanks, Morten Brix Pedersen; closes: #217964).
+    - Japanese (thanks, Kenshi Muto; closes: #212497).
+    - Russian (thanks, Ilgiz Kalmetev).
+    - Spanish (thanks, Carlos Valdivia Yagüe; closes: #211832).
+  * Add Dutch debconf template translation (thanks, cobaco;
+    closes: #215372).
+  * Update config.guess and config.sub from autotools-dev 20031007.1
+    (closes: #217696).
+  * Implement New World Order for PAM configuration, including
+    /etc/pam.d/common-* from /etc/pam.d/ssh (closes: #212959).
+    - To backport this release to woody, you need to set DEB_BUILD_SSH_WOODY
+      in your environment. See README.Debian.
+  * Add more commentary to /etc/pam.d/ssh.
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 16 Nov 2003 01:14:16 +0000
+
+openssh (1:3.6.1p2-9) unstable; urgency=high
+
+  * Merge even more buffer allocation fixes from upstream (CAN-2003-0682;
+    closes: #211434).
+
+ -- Colin Watson <cjwatson@debian.org>  Fri, 19 Sep 2003 10:25:25 +0100
+
+openssh (1:3.6.1p2-8) unstable; urgency=high
+
+  * Merge more buffer allocation fixes from new upstream version 3.7.1p1
+    (closes: #211324).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 17 Sep 2003 03:07:19 +0100
+
+openssh (1:3.6.1p2-7) unstable; urgency=high
+
+  * Update debconf template translations:
+    - French (thanks, Christian Perrier; closes: #208801).
+    - Japanese (thanks, Kenshi Muto; closes: #210380).
+  * Some small improvements to the English templates courtesy of Christian
+    Perrier. I've manually unfuzzied a few translations where it was
+    obvious, on Christian's advice, but the others will have to be updated.
+  * Document how to generate an RSA1 host key (closes: #141703).
+  * Incorporate NMU fix for early buffer expansion vulnerability,
+    CAN-2003-0693 (closes: #211205). Thanks to Michael Stone.
+
+ -- Colin Watson <cjwatson@debian.org>  Tue, 16 Sep 2003 14:32:28 +0100
+
+openssh (1:3.6.1p2-6.0) unstable; urgency=high
+
+  * SECURITY: fix for CAN-2003-0693, buffer allocation error
+
+ -- Michael Stone <mstone@debian.org>  Tue, 16 Sep 2003 08:27:07 -0400
+
+openssh (1:3.6.1p2-6) unstable; urgency=medium
+
+  * Use a more CVS-friendly means of setting SSH_VERSION.
+  * Update Brazilian Portuguese debconf template translation (thanks, Andre
+    Luis Lopes; closes: #208036).
+  * Don't run 'sshd -t' in init script if the server isn't to be run
+    (closes: #197576).
+  * Fix login delay, spurious auth.log entry, and PermitRootLogin
+    information leakage due to PAM issues with upstream's recent security
+    update (thanks, Darren Tucker; closes: #99168, #192207, #193546).
+  * Policy version 3.6.1: recode this changelog to UTF-8.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed,  3 Sep 2003 19:14:02 +0100
+
+openssh (1:3.6.1p2-5) unstable; urgency=low
+
+  * Disable cmsg_type check for file descriptor passing when running on
+    Linux 2.0 (closes: #150976). Remove comments about non-functional
+    privilege separation on 2.0 from ssh/privsep_ask and ssh/privsep_tell
+    debconf questions and from README.Debian, since it should all now work.
+  * Fix "defails" typo in generated sshd_config (closes: #206484).
+  * Backport upstream patch to strip trailing whitespace (including
+    newlines) from configuration directives (closes: #192079).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed, 27 Aug 2003 02:19:57 +0100
+
+openssh (1:3.6.1p2-4) unstable; urgency=low
+
+  * getent can get just one key; no need to use grep (thanks, James Troup).
+  * Move /usr/local/bin to the front of the default path, following
+    /etc/login.defs (closes: #201150).
+  * Remove specifics of problematic countries from package description
+    (closes: #197040).
+  * Update Spanish debconf template translation (thanks, Carlos Valdivia
+    Yagüe; closes: #198456).
+  * Backport upstream patch to pass monitor signals through to child
+    (closes: #164797).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 27 Jul 2003 17:31:15 +0100
+
+openssh (1:3.6.1p2-3) unstable; urgency=low
+
+  * Update French debconf template translation (thanks, Christian Perrier;
+    closes: #194323).
+  * Version the adduser dependency for --no-create-home (closes: #195756).
+  * Add a version of moduli(5), namely revision 1.7 of
+    http://www.openbsd.org/cgi-bin/cvsweb/src/share/man/man5/moduli.5 with
+    '/etc/moduli' changed to '/etc/ssh/moduli' throughout (closes: #196061).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  9 Jun 2003 02:51:35 +0100
+
+openssh (1:3.6.1p2-2) unstable; urgency=low
+
+  * Force /etc/default/ssh to be non-executable, since dpkg apparently
+    doesn't deal with permissions changes on conffiles (closes: #192966).
+  * Use debconf 0.5's seen flag rather than the deprecated isdefault.
+  * Add GPL location to copyright file.
+  * Remove debian/postinst.old.
+  * Switch to po-debconf, with some careful manual use of po2debconf to
+    ensure that the source package continues to build smoothly on woody
+    (closes: #183986).
+  * Update debconf template translations:
+    - Brazilian Portugese (thanks, Andre Luis Lopes; see #183986).
+    - Japanese (thanks, Tomohiro KUBOTA; closes: #192429).
+  * Compile with -fno-builtin-log for now, otherwise gcc-3.3 complains
+    "log.h:59: warning: conflicting types for built-in function `log'". The
+    OpenSSH log() function has been renamed in upstream CVS.
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 19 May 2003 01:52:38 +0100
+
+openssh (1:3.6.1p2-1) unstable; urgency=medium
+
+  * New upstream release, including fix for PAM user-discovery security hole
+    (closes: #191681).
+  * Fix ChallengeResponseAuthentication default in generated sshd_config
+    (closes: #106037).
+  * Put newlines after full stops in man page documentation for
+    ProtocolKeepAlives and SetupTimeOut.
+  * Policy version 3.5.9: support DEB_BUILD_OPTIONS=noopt, build
+    gnome-ssh-askpass with -g and -Wall flags.
+  * Really ask ssh/new_config debconf question before trying to fetch its
+    value (closes: #188721).
+  * On purge, remove only the files we know about in /etc/ssh rather than
+    the whole thing, and remove the directory if that leaves it empty
+    (closes: #176679).
+  * ssh has depended on debconf for some time now with no complaints, so:
+    - Simplify the postinst by relying on debconf being present. (The absent
+      case was buggy anyway.)
+    - Get rid of "if you have not installed debconf" text in README.Debian,
+      and generally update the "/usr/bin/ssh not SUID" entry.
+  * More README.Debian work:
+    - Reorganize into "UPGRADE ISSUES" and "OTHER ISSUES", in an effort to
+      make it easier for people to find the former. The upgrade issues
+      should probably be sorted by version somehow.
+    - Document X11UseLocalhost under "X11 Forwarding" (closes: #150913).
+  * Fix setting of IP flags for interactive sessions (upstream bug #541).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  5 May 2003 17:47:40 +0100
+
+openssh (1:3.6.1p1-1) unstable; urgency=low
+
+  * New upstream release (thanks, Laurence J. Lane).
+  * debian/control: ssh-askpass-gnome is now Section: gnome, following the
+    override file.
+
+ -- Colin Watson <cjwatson@debian.org>  Wed,  2 Apr 2003 00:51:02 +0100
+
+openssh (1:3.6p1-1) unstable; urgency=low
+
+  * New upstream release.
+    - Workaround applied upstream for a bug in the interaction of glibc's
+      getaddrinfo() with the Linux 2.2 kernel (closes: #155814).
+    - As such, it should now be safe to remove --with-ipv4-default, so
+      starting sshd with -6 is no longer necessary (closes: #79861 and lots
+      of other merged bugs).
+    - ssh-copy-id prints usage when run without arguments (closes: #71376).
+    - scp exits 1 if ssh fails (closes: #138400).
+    - sshd writes to utmp's ut_addr_v6 field in IPv6 mode (closes: #167867).
+    - 'ssh-add -c' causes ssh-agent to ask the user each time a key is used
+      (closes: #109795).
+  * Install /etc/default/ssh non-executable (closes: #185537).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon, 31 Mar 2003 23:00:59 +0100
+
+openssh (1:3.5p1-5) unstable; urgency=low
+
+  * Add /etc/default/ssh (closes: #161049).
+  * Run the init script under 'set -e' (closes: #175010).
+  * Change the default superuser path to include /sbin, /usr/sbin, and
+    /usr/local/sbin (closes: #128235, #151267). Using login.defs would be
+    nice, but that belongs to another package. Without a defined API to
+    retrieve its settings, parsing it is off-limits.
+  * Build ssh-askpass-gnome with GNOME 2. The source package should still
+    support building on stable with GNOME 1, using the alternate
+    libgnome-dev build-dependency (thanks, Colin Walters; closes: #167582).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun,  9 Mar 2003 20:12:10 +0000
+
+openssh (1:3.5p1-4) unstable; urgency=low
+
+  * Point rlogin and rcp alternatives at slogin and scp respectively rather
+    than ssh (closes: #121103, #151666). Fix alternative removal to match;
+    previously it was completely wrong anyway.
+  * Find out whether /etc/ssh/sshd_not_to_be_run exists and set the debconf
+    question's default using that information, rather than using debconf as
+    a registry. Other solutions may be better in the long run, but this is
+    at least correct (thanks, Matthew Woodcraft; closes: #84725).
+  * Stop using pam_lastlog, as it doesn't currently work well as a session
+    module when privilege separation is enabled; it can usually read
+    /var/log/lastlog but can't write to it. Instead, just use sshd's
+    built-in support, already enabled by default (closes: #151297, #169938).
+  * Use 'ssh-keygen -q' rather than redirecting output to /dev/null.
+  * Add a "this may take some time" warning when creating host keys on
+    installation (part of #110094).
+  * When restarting via the init script, check for sshd_not_to_be_run after
+    stopping sshd (idea from Tomas Pospisek; closes: #149850).
+  * Append /usr/sbin:/sbin to the init script's $PATH, just in case of
+    strangeness (closes: #115138).
+  * Fix a dpkg-statoverride call to redirect stdout to /dev/null, not
+    stderr.
+  * Correct copyright file typo: "orignal" -> "original" (closes: #176490).
+  * Rebuild with libssl0.9.7 (closes: #176983).
+  * We're up to policy version 3.5.6. DEB_BUILD_OPTIONS stuff still needs to
+    be looked at.
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 18 Jan 2003 01:37:23 +0000
+
+openssh (1:3.5p1-3) unstable; urgency=low
+
+  * Happy new year!
+  * Use getent rather than id to find out whether the sshd user exists
+    (closes: #150974).
+  * Remove some duplication from the postinst's ssh-keysign setuid code.
+  * Replace db_text with db_input throughout debian/config. (db_text has
+    been a compatibility wrapper since debconf 0.1.5.)
+  * Warn about PermitUserEnvironment on upgrade (closes: #167895).
+  * Use 'make install-nokeys', and disable unused debhelper commands,
+    thereby forward-porting the last pieces of Zack Weinberg's patch
+    (closes: #68341).
+  * Move the man page for gnome-ssh-askpass from the ssh package to
+    ssh-askpass-gnome (closes: #174449).
+  * Build with -DLOGIN_NO_ENDOPT, since Debian's /bin/login doesn't accept
+    '--' to terminate the list of options (closes: #171554).
+  * Add Jonathan Amery's ssh-argv0 script (closes: #111341).
+  * Update Danish debconf template (thanks, Morten Brix Pedersen;
+    closes: #174757).
+  * Document setgid ssh-agent's effect on certain environment variables in
+    README.Debian (closes: #167974).
+  * Document interoperability problems between scp and ssh.com's server in
+    README.Debian, and suggest some workarounds (closes: #174662).
+
+ -- Colin Watson <cjwatson@debian.org>  Wed,  1 Jan 2003 14:18:30 +0000
+
+openssh (1:3.5p1-2) unstable; urgency=low
+
+  * Mention in the ssh package description that it provides both ssh and
+    sshd (closes: #99680).
+  * Create a system group for ssh-agent, not a user group (closes: #167669).
+
+ -- Colin Watson <cjwatson@debian.org>  Mon,  4 Nov 2002 13:43:53 +0000
+
+openssh (1:3.5p1-1) unstable; urgency=low
+
+  * New upstream release.
+    - Fixes typo in ssh-add usage (closes: #152239).
+    - Fixes 'PermitRootLogin forced-commands-only' (closes: #166184).
+    - ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys
+      are deprecated for security reasons and will eventually go away. For
+      now they can be re-enabled by setting 'PermitUserEnvironment yes' in
+      sshd_config.
+    - ssh-agent is installed setgid to prevent ptrace() attacks. The group
+      actually doesn't matter, as it drops privileges immediately, but to
+      avoid confusion the postinst creates a new 'ssh' group for it.
+  * Obsolete patches:
+    - Solar Designer's privsep+compression patch for Linux 2.2 (see
+      1:3.3p1-0.0woody1).
+    - Hostbased auth ssh-keysign backport (see 1:3.4p1-4).
+
+  * Remove duplicated phrase in ssh_config(5) (closes: #152404).
+  * Source the debconf confmodule at the top of the postrm rather than at
+    the bottom, to avoid making future non-idempotency problems worse (see
+    #151035).
+  * Debconf templates:
+    - Add Polish (thanks, Grzegorz Kusnierz).
+    - Update French (thanks, Denis Barbier; closes: #132509).
+    - Update Spanish (thanks, Carlos Valdivia Yagüe; closes: #164716).
+  * Write a man page for gnome-ssh-askpass, and link it to ssh-askpass.1 if
+    this is the selected ssh-askpass alternative (closes: #67775).
+
+ -- Colin Watson <cjwatson@debian.org>  Sat, 26 Oct 2002 19:41:51 +0100
+
+openssh (1:3.4p1-4) unstable; urgency=low
+
+  * Allow ssh-krb5 in ssh-askpass-gnome's dependencies (closes: #129532).
+  * Restore Russia to list of countries where encryption is problematic (see
+    #148951 and http://www.average.org/freecrypto/).
+  * Drop ssh-askpass-gnome's priority to optional, per the override file.
+  * Drop the PAM special case for hurd-i386 (closes: #99157).
+  * s/dile/idle/ in ssh_config(5) (closes: #118331).
+  * Note in README.Debian that you need xauth from xbase-clients on the
+    server for X11 forwarding (closes: #140269).
+  * Use correct path to upstream README in copyright file (closes: #146037).
+  * Document the units for ProtocolKeepAlives (closes: #159479).
+  * Backport upstream patch to fix hostbased auth (closes: #117114).
+  * Add -g to CFLAGS.
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 13 Oct 2002 18:58:53 +0100
+
+openssh (1:3.4p1-3) unstable; urgency=low
+
+  * Add myself to Uploaders: and begin acting as temporary maintainer, at
+    Matthew's request. (Normal service will resume in some months' time.)
+  * Add sharutils to Build-Depends (closes: #138465).
+  * Stop creating the /usr/doc/ssh symlink.
+
+  * Fix some debconf template typos (closes: #160358).
+  * Split debconf templates into one file per language.
+  * Add debconf template translations:
+    - Brazilian Portuguese (thanks, Andre Luis Lopes; closes: #106173).
+    - Danish (thanks, Claus Hindsgaul; closes: #126607).
+    - Japanese (thanks, Tomohiro KUBOTA; closes: #137427).
+    - Russian (thanks, Ilgiz Kalmetev; closes: #136610).
+    - Spanish (thanks, Carlos Valdivia Yagüe; closes: #129041).
+  * Update debconf template translations:
+    - French (thanks, Igor Genibel; closes: #151361).
+    - German (thanks, Axel Noetzold; closes: #147069).
+  * Some of these translations are fuzzy. Please send updates.
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 13 Oct 2002 14:09:57 +0100
+
+openssh (1:3.4p1-2) unstable; urgency=high
+
+  * Get a security-fixed version into unstable
+  * Also tidy README.Debian up a little
+
+ -- Matthew Vernon <matthew@debian.org>  Fri, 28 Jun 2002 17:20:59 +0100
+
+openssh (1:3.4p1-1) testing; urgency=high
+
+  * Extend my tendrils back into this package (Closes: #150915, #151098)
+  * thanks to the security team for their work
+  * no thanks to ISS/Theo de Raadt for their handling of these bugs
+  * save old sshd_configs to sshd_config.dpkg-old when auto-generating a
+    new one
+  * tell/ask the user about PriviledgeSeparation
+  * /etc/init.d/ssh run will now create the chroot empty dir if necessary 
+  * Remove our previous statoverride on /usr/bin/ssh (only for people 
+    upgrading from a version where we'd put one in ourselves!)
+  * Stop slandering Russia, since someone asked so nicely (Closes: #148951)
+  * Reduce the sleep time in /etc/init.d/ssh during a restart
+
+ -- Matthew Vernon <matthew@debian.org>  Fri, 28 Jun 2002 15:52:10 +0100
+
+openssh (1:3.4p1-0.0woody1) testing-security; urgency=high
+
+  * NMU by the security team.
+  * New upstream version
+
+ -- Michael Stone <mstone@debian.org>  Wed, 26 Jun 2002 15:40:38 -0400
+
+openssh (1:3.3p1-0.0woody4) testing-security; urgency=high
+
+  * NMU by the security team.
+  * fix error when /etc/ssh/sshd_config exists on new install
+  * check that user doesn't exist before running adduser
+  * use openssl internal random unconditionally
+
+ -- Michael Stone <mstone@debian.org>  Tue, 25 Jun 2002 19:44:39 -0400
+
+openssh (1:3.3p1-0.0woody3) testing-security; urgency=high
+
+  * NMU by the security team.
+  * use correct home directory when sshd user is created
+
+ -- Michael Stone <mstone@debian.org>  Tue, 25 Jun 2002 08:59:50 -0400
+
+openssh (1:3.3p1-0.0woody2) testing-security; urgency=high
+
+  * NMU by the security team.
+  * Fix rsa1 key creation (Closes: #150949)
+  * don't fail if sshd user removal fails
+  * depends: on adduser (Closes: #150907)
+
+ -- Michael Stone <mstone@debian.org>  Tue, 25 Jun 2002 08:59:50 -0400
+
+openssh (1:3.3p1-0.0woody1) testing-security; urgency=high
+
+  * NMU by the security team.
+  * New upstream version.
+    - Enable privilege separation by default.
+  * Include patch from Solar Designer for privilege separation and
+    compression on 2.2.x kernels.
+  * Remove --disable-suid-ssh from configure.
+  * Support setuid ssh-keysign binary instead of setuid ssh client.
+  * Check sshd configuration before restarting.
+
+ -- Daniel Jacobowitz <dan@debian.org>  Mon, 24 Jun 2002 13:43:44 -0400
+
+openssh (1:3.0.2p1-9) unstable; urgency=high
+
+  * Thanks to those who NMUd
+  * The only change in this version is to debian/control - I've removed
+    the bit that says you can't export it from the US - it would look 
+    pretty daft to say this about a package in main! Also, it's now OK
+    to use crypto in France, so I've edited that comment slightly
+  * Correct a path in README.Debian too (Closes: #138634)
+
+ -- Matthew Vernon <matthew@debian.org>  Sun,  4 Apr 2002 09:52:59 +0100
+
+openssh (1:3.0.2p1-8.3) unstable; urgency=medium
+
+  * NMU
+  * Really set urgency to medium this time (oops)
+  * Fix priority to standard per override while I'm at it
+
+ -- Aaron M. Ucko <ucko@debian.org>  Sun, 24 Mar 2002 09:00:08 -0500
+
+openssh (1:3.0.2p1-8.2) unstable; urgency=low
+
+  * NMU with maintainer's permission
+  * Prepare for upcoming ssh-nonfree transitional packages per
+    <http://lists.debian.org/debian-ssh/2002/debian-ssh-200203/msg00008.html>
+  * Urgency medium because it would really be good to get this into woody
+    before it releases
+  * Fix sections to match override file
+  * Reissued due to clash with non-US -> main move
+
+ -- Aaron M. Ucko <ucko@debian.org>  Sat, 23 Mar 2002 21:21:52 -0500
+
+openssh (1:3.0.2p1-8.1) unstable; urgency=low
+
+  * NMU
+  * Move from non-US to mani
+
+ -- LaMont Jones <lamont@debian.org>  Thu, 21 Mar 2002 09:33:50 -0700
+
+openssh (1:3.0.2p1-8) unstable; urgency=critical
+
+  * Security fix - patch from upstream (Closes: #137209, #137210)
+  * Undo the changes in the unreleased -7, since they appear to break 
+    things here. Accordingly, the code change is minimal, and I'm 
+    happy to get it into testing ASAP
+
+ -- Matthew Vernon <matthew@debian.org>  Thu,  7 Mar 2002 14:25:23 +0000
+
+openssh (1:3.0.2p1-7) unstable; urgency=high
+
+  * Build to support IPv6 and IPv4 by default again
+
+ -- Matthew Vernon <matthew@debian.org>  Sat,  2 Mar 2002 00:25:05 +0000
+
+openssh (1:3.0.2p1-6) unstable; urgency=high
+
+  * Correct error in the clean target (Closes: #130868)
+
+ -- Matthew Vernon <matthew@debian.org>  Sat, 26 Jan 2002 00:32:00 +0000
+
+openssh (1:3.0.2p1-5) unstable; urgency=medium
+
+  * Include the Debian version in our identification, to make it easier to
+    audit networks for patched versions in future
+
+ -- Matthew Vernon <matthew@debian.org>  Mon, 21 Jan 2002 17:16:10 +0000
+
+openssh (1:3.0.2p1-4) unstable; urgency=medium
+
+  * If we're asked to not run sshd, stop any running sshd's first 
+    (Closes: #129327)
+
+ -- Matthew Vernon <matthew@debian.org>  Wed, 16 Jan 2002 21:24:16 +0000
+
+openssh (1:3.0.2p1-3) unstable; urgency=high
+
+  * Fix /etc/pam.d/ssh to not set $MAIL (Closes: #128913)
+  * Remove extra debconf suggestion (Closes: #128094)
+  * Mmm. speedy bug-fixing :-)
+
+ -- Matthew Vernon <matthew@debian.org>  Sat, 12 Jan 2002 17:23:58 +0000
+
+openssh (1:3.0.2p1-2) unstable; urgency=high
+
+  * Fix postinst to not automatically overwrite sshd_config (!) 
+    (Closes: #127842, #127867)
+  * Add section in README.Debian about the PermitRootLogin setting
+
+ -- Matthew Vernon <matthew@debian.org>  Sat,  5 Jan 2003 05:26:30 +0000
+
+openssh (1:3.0.2p1-1) unstable; urgency=high
+
+  * Incorporate fix from Colin's NMU
+  * New upstream version (fixes the bug Wichert fixed) (Closes: #124035)
+  * Capitalise IETF (Closes: #125379)
+  * Refer to the correct sftp-server location (Closes: #126854, #126224)
+  * Do what we're asked re SetUID ssh (Closes: #124065, #124154, #123247)
+  * Ask people upgrading from potato if they want a new conffile 
+    (Closes: #125642)
+  * Fix a typo in postinst (Closes: #122192, #122410, #123440)
+  * Frob the default config a little (Closes: #122284, #125827, #125696,
+    #123854)
+  * Make /etc/init.d/ssh be more clear about ssh not running (Closes:
+    #123552)
+  * Fix typo in templates file (Closes: #123411)
+
+ -- Matthew Vernon <matthew@debian.org>  Fri,  4 Jan 2002 16:01:52 +0000
+
+openssh (1:3.0.1p1-1.2) unstable; urgency=high
+
+  * Non-maintainer upload
+  * Prevent local users from passing environment variables to the login
+    process when UseLogin is enabled
+
+ -- Wichert Akkerman <wakkerma@debian.org>  Mon,  3 Dec 2001 19:34:45 +0100
+
+openssh (1:3.0.1p1-1.1) unstable; urgency=low
+
+  * Non-maintainer upload, at Matthew's request.
+  * Remove sa_restorer assignment to fix compilation on alpha, hppa, and
+    ia64 (closes: #122086).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun,  2 Dec 2001 18:54:16 +0000
+
+openssh (1:3.0.1p1-1) unstable; urgency=high
+
+  * New upstream version (Closes: #113646, #113513, #114707, #118564)
+  * Building with a libc that works (!) (Closes: #115228)
+  * Patches forward-ported are -1/-2 options for scp, the improvement to
+    'waiting for forwarded connections to terminate...'
+  * Fix /etc/init.d/ssh to stop sshd properly (Closes: #115228)
+  * /etc/ssh/sshd_config is no longer a conffile but generated in the postinst
+  * Remove suidregister leftover from postrm
+  * Mention key we are making in the postinst
+  * Default to not enable SSH protocol 1 support, since protocol 2 is
+    much safer anyway.
+  * New version of the vpn-fixes patch, from Ian Jackson
+  * New handling of -q, and added new -qq option; thanks to Jon Amery
+  * Experimental smartcard support not enabled, since I have no way of
+    testing it.
+
+ -- Matthew Vernon <matthew@debian.org>  Thu, 28 Nov 2001 17:43:01 +0000
+
+openssh (1:2.9p2-6) unstable; urgency=low
+
+  * check for correct file in /etc/init.d/ssh (Closes: #110876)
+  * correct location of version 2 keys in ssh.1 (Closes: #110439)
+  * call update-alternatives --quiet (Closes: #103314)
+  * hack ssh-copy-id to chmod go-w (Closes: #95551)
+  * TEMPORARY fix to provide largefile support using a -D in the cflags
+    line. long-term, upstream will patch the autoconf stuff
+    (Closes: #106809, #111849)
+  * remove /etc/rc references in ssh-keygen.1 (Closes: #68350)
+  * scp.1 patch from Adam McKenna to document -r properly (Closes: #76054)
+  * Check for files containing a newline character (Closes: #111692)
+
+ -- Matthew Vernon <matthew@debian.org>  Thu, 13 Sep 2001 16:47:36 +0100
+
+openssh (1:2.9p2-5) unstable; urgency=high
+
+  * Thanks to all the bug-fixers who helped!
+  * remove sa_restorer assignment (Closes: #102837)
+  * patch from Peter Benie to DTRT wrt X forwarding if the server refuses
+    us access (Closes: #48297)
+  * patch from upstream CVS to fix port forwarding (Closes: #107132)
+  * patch from Jonathan Amery to document ssh-keygen behaviour 
+    (Closes:#106643, #107512)
+  * patch to postinst from Jonathan Amery (Closes: #106411)
+  * patch to manpage from Jonathan Amery (Closes: #107364)
+  * patch from Matthew Vernon to make -q emit fatal errors as that is the
+    documented behaviour (Closes: #64347)
+  * patch from Ian Jackson to cause us to destroy a file when we scp it
+    onto itself, rather than dumping bits of our memory into it, which was
+    a security hole (see #51955)
+  * patch from Jonathan Amery to document lack of Kerberos support 
+    (Closes: #103726)
+  * patch from Matthew Vernon to make the 'waiting for connections to
+    terminate' message more helpful (Closes: #50308)
+
+ -- Matthew Vernon <matthew@debian.org>  Thu, 23 Aug 2001 02:14:09 +0100
+
+openssh (1:2.9p2-4) unstable; urgency=high
+
+  * Today's build of ssh is strawberry flavoured
+  * Patch from mhp to reduce length of time sshd is stopped for (Closes: #106176)
+  * Tidy up debconf template (Closes: #106152)
+  * If called non-setuid, then setgid()'s failure should not be fatal (see
+    #105854)
+
+ -- Matthew Vernon <matthew@debian.org>  Sun, 22 Jul 2001 14:19:43 +0100
+
+openssh (1:2.9p2-3) unstable; urgency=low
+
+  * Patch from yours truly to add -1 and -2 options to scp (Closes: #106061)
+  * Improve the IdentityFile section in the man page (Closes: #106038)
+
+ -- Matthew Vernon <matthew@debian.org>  Sat, 21 Jul 2001 14:47:27 +0100
+
+openssh (1:2.9p2-2) unstable; urgency=low
+
+  * Document the protocol version 2 and IPV6 changes (Closes: #105845, #105868)
+  * Make PrintLastLog 'no' by default (Closes: #105893)
+
+ -- Matthew Vernon <matthew@debian.org>  Thu, 19 Jul 2001 18:36:41 +0100
+
+openssh (1:2.9p2-1) unstable; urgency=low
+
+  * new (several..) upstream version (Closes: #96726, #81856, #96335)
+  * Hopefully, this will close some other bugs too
+
+ -- Matthew Vernon <matthew@debian.org>  Tue, 17 Jul 2001 19:41:58 +0100
+
+openssh (1:2.5.2p2-3) unstable; urgency=low
+
+  * Taking Over this package
+  * Patches from Robert Bihlmeyer for the Hurd (Closes: #102991)
+  * Put PermitRootLogin back to yes (Closes: #67334, #67371, #78274)
+  * Don't fiddle with conf-files any more (Closes: #69501)
+
+ -- Matthew Vernon <matthew@debian.org>  Tue, 03 Jul 2001 02:58:13 +0100
+
+openssh (1:2.5.2p2-2.2) unstable; urgency=low
+
+  * NMU
+  * Include Hurd compatibility patches from Robert Bihlmeyer (Closes: #76033)
+  * Patch from Richard Kettlewell for protocolkeepalives (Closes: #99273)
+  * Patch from Matthew Vernon for BannerTimeOut, batchmode, and
+    documentation for protocolkeepalives. Makes ssh more generally useful
+    for scripting uses (Closes: #82877, #99275)
+  * Set a umask, so ourpidfile isn't world-writable (closes: #100012,
+    #98286, #97391)
+
+ -- Matthew Vernon <matthew@debian.org>  Thu, 28 Jun 2001 23:15:42 +0100
+
+openssh (1:2.5.2p2-2.1) unstable; urgency=low
+  * NMU
+  * Remove duplicate Build-Depends for libssl096-dev and change it to 
+    depend on libssl-dev instaed.  Also adding in virtual | real package
+    style build-deps.  (Closes: #93793, #75228)
+  * Removing add-log entry (Closes: #79266)
+  * This was a pam bug from a while back (Closes: #86908, #88457, #86843)
+  * pam build-dep already exists (Closes: #93683)
+  * libgnome-dev build-dep already exists (Closes: #93694)
+  * No longer in non-free (Closes: #85401)
+  * Adding in fr debconf translations (Closes: #83783)
+  * Already suggests xbase-clients (Closes: #79741)
+  * No need to suggest libpam-pwdb anymore (Closes: #81658)
+  * Providing rsh-client (Closes: #79437)
+  * hurd patch was already applied (Closes: #76033)
+  * default set to no (Closes: #73682)
+  * Adding in a suggests for dnsutils (Closes: #93265)
+  * postinst bugs fixed (Closes: #88057, #88066, #88196, #88405, #88612)
+    (Closes: #88774, #88196, #89556, #90123, #90228, #90833, #87814, #85465)
+  * Adding in debconf dependency
+ -- Ivan E. Moore II <rkrusty@debian.org>  Mon, 16 Apr 2001 14:11:04 +0100
+
+openssh (1:2.5.2p2-2) unstable; urgency=high
+
+  * disable the OpenSSL version check in entropy.c
+    (closes: #93581, #93588, #93590, #93614, #93619, #93635, #93648)
+
+ -- Philip Hands <phil@uk.alcove.com>  Wed, 11 Apr 2001 20:30:04 +0100
+
+openssh (1:2.5.2p2-1) unstable; urgency=low
+
+  * New upstream release
+  * removed make-ssh-known-hosts, since ssh-keyscan does that job (closes: #86069, #87748)
+  * fix double space indent in german templates (closes: #89493)
+  * make postinst check for ssh_host_rsa_key
+  * get rid of the last of the misguided debian/rules NMU debris  :-/
+
+ -- Philip Hands <phil@hands.com>  Sat, 24 Mar 2001 20:59:33 +0000
+
+openssh (1:2.5.1p2-2) unstable; urgency=low
+
+  * rebuild with new debhelper (closes: #89558, #89536, #90225)
+  * fix broken dpkg-statoverride test in postinst
+    (closes: #89612, #90474, #90460, #89605)
+  * NMU bug fixed but not closed in last upload  (closes: #88206)
+  
+ -- Philip Hands <phil@hands.com>  Fri, 23 Mar 2001 16:11:33 +0000
+
+openssh (1:2.5.1p2-1) unstable; urgency=high
+
+  * New upstream release
+  * fix typo in postinst (closes: #88110)
+  * revert to setting PAM service name in debian/rules, backing out last
+    NMU, which also (closes: #88101)
+  * restore the pam lastlog/motd lines, lost during the NMUs, and sshd_config
+  * restore printlastlog option patch
+  * revert to using debhelper, which had been partially disabled in NMUs
+
+ -- Philip Hands <phil@hands.com>  Tue, 13 Mar 2001 01:41:34 +0000
+
+openssh (1:2.5.1p1-1.8) unstable; urgency=high
+
+  * And now the old pam-bug s/sshd/ssh in ssh.c is also fixed
+
+ -- Christian Kurz <shorty@debian.org>  Thu,  1 Mar 2001 19:48:01 +0100
+
+openssh (1:2.5.1p1-1.7) unstable; urgency=high
+
+  * And now we mark the correct binary as setuid, when a user requested
+    to install it setuid.
+
+ -- Christian Kurz <shorty@debian.org>  Thu,  1 Mar 2001 07:19:56 +0100
+
+openssh (1:2.5.1p1-1.6) unstable; urgency=high
+
+  * Fixes postinst to handle overrides that are already there. Damn, I 
+    should have noticed the bug earlier.
+
+ -- Christian Kurz <shorty@debian.org>  Wed, 28 Feb 2001 22:35:00 +0100
+
+openssh (1:2.5.1p1-1.5) unstable; urgency=high
+
+  * Rebuild ssh with pam-support.
+
+ -- Christian Kurz <shorty@debian.org>  Mon, 26 Feb 2001 21:55:51 +0100
+
+openssh (1:2.5.1p1-1.4) unstable; urgency=low
+
+  * Added Build-Depends on libssl096-dev.
+  * Fixed sshd_config file to disallow root logins again.
+
+ -- Christian Kurz <shorty@debian.org>  Sun, 25 Feb 2001 20:03:55 +0100
+
+openssh (1:2.5.1p1-1.3) unstable; urgency=low
+
+  * Fixed missing manpages for sftp.1 and ssh-keyscan.1
+  * Made package policy 3.5.2 compliant.
+
+ -- Christian Kurz <shorty@debian.org>  Sun, 25 Feb 2001 15:46:26 +0100
+
+openssh (1:2.5.1p1-1.2) unstable; urgency=low
+
+  * Added Conflict with sftp, since we now provide our own sftp-client.
+  * Added a fix for our broken dpkg-statoverride call in the 
+    2.3.0p1-13.
+  * Fixed some config pathes in the comments of sshd_config.
+  * Removed ssh-key-exchange-vulnerability-patch since it's not needed
+    anymore because upstream included the fix.
+
+ -- Christian Kurz <shorty@debian.org>  Sun, 25 Feb 2001 13:46:58 +0100
+
+openssh (1:2.5.1p1-1.1) unstable; urgency=high
+
+  * Another NMU to get the new upstream version 2.5.1p1 into
+    unstable. (Closes: #87123)
+  * Corrected postinst to mark ssh as setuid. (Closes: #86391, #85766)
+  * Key Exchange patch is already included by upstream. (Closes: #86015)
+  * Upgrading should be possible now. (Closes: #85525, #85523)
+  * Added --disable-suid-ssh as compile option, so ssh won't get installed
+    suid per default.
+  * Fixed postinst to run dpkg-statoverride only, when dpkg-statoverride
+    is available and the mode of the binary should be 4755. And also added
+    suggestion for a newer dpkg.
+    (Closes: #85734, #85741, #86876)
+  * sftp and ssh-keyscan will also be included from now on. (Closes: #79994)
+  * scp now understands spaces in filenames (Closes: #53783, #58958,
+    #66723)
+  * ssh-keygen now supports showing DSA fingerprints. (Closes: #68623)
+  * ssh doesn' t show motd anymore when switch -t is used. (Closes #69035)
+  * ssh supports the usage of other dsa keys via the ssh command line
+    options. (Closes: #81250)
+  * Documentation in sshd_config fixed. (Closes: #81088)
+  * primes file included by upstream and included now. (Closes: #82101)
+  * scp now allows dots in the username. (Closes: #82477)
+  * Spelling error in ssh-copy-id.1 corrected by upstream. (Closes: #78124)
+
+ -- Christian Kurz <shorty@debian.org>  Sun, 25 Feb 2001 10:06:08 +0100
+
+openssh (1:2.3.0p1-1.13) unstable; urgency=low
+
+  * Config should now also be fixed with this hopefully last NMU.
+
+ -- Christian Kurz <shorty@debian.org>  Sat, 10 Feb 2001 22:56:36 +0100
+
+openssh (1:2.3.0p1-1.12) unstable; urgency=high
+
+  * Added suggest for xbase-clients to control-file. (Closes #85227)
+  * Applied patch from Markus Friedl to fix a vulnerability in 
+    the rsa keyexchange.
+  * Fixed position of horizontal line. (Closes: #83613)
+  * Fixed hopefully the grep problem in the config-file. (Closes: #78802)
+  * Converted package from suidregister to dpkg-statoverride.
+
+ -- Christian Kurz <shorty@debian.org>  Fri,  9 Feb 2001 19:43:55 +0100
+
+openssh (1:2.3.0p1-1.11) unstable; urgency=medium
+
+  * Fixed some typos in the german translation of the debconf
+    template.
+
+ -- Christian Kurz <shorty@debian.org>  Wed, 24 Jan 2001 18:22:38 +0100
+
+openssh (1:2.3.0p1-1.10) unstable; urgency=medium
+
+  * Fixed double printing of motd. (Closes: #82618)
+
+ -- Christian Kurz <shorty@debian.org>  Tue, 23 Jan 2001 21:03:43 +0100
+
+openssh (1:2.3.0p1-1.9) unstable; urgency=high
+
+  * And the next NMU which includes the patch from Andrew Bartlett
+    and Markus Friedl to fix the root privileges handling of openssh.
+    (Closes: #82657)
+
+ -- Christian Kurz <shorty@debian.org>  Wed, 17 Jan 2001 22:20:54 +0100
+
+openssh (1:2.3.0p1-1.8) unstable; urgency=high
+
+  * Applied fix from Ryan Murray to allow building on other architectures
+    since the hurd patch was wrong. (Closes: #82471)
+
+ -- Christian Kurz <shorty@debian.org>  Tue, 16 Jan 2001 22:45:51 +0100
+
+openssh (1:2.3.0p1-1.7) unstable; urgency=medium
+
+  * Fixed another typo on sshd_config
+
+ -- Christian Kurz <shorty@debian.org>  Sun, 14 Jan 2001 19:01:31 +0100
+
+openssh (1:2.3.0p1-1.6) unstable; urgency=high
+
+  * Added Build-Dependency on groff (Closes: #81886)
+  * Added Build-Depencency on debhelper (Closes: #82072)
+  * Fixed entry for known_hosts in sshd_config (Closes: #82096)
+
+ -- Christian Kurz <shorty@debian.org>  Thu, 11 Jan 2001 23:08:16 +0100
+
+openssh (1:2.3.0p1-1.5) unstable; urgency=high
+
+  * Fixed now also the problem with sshd used as default ipv4 and
+    didn't use IPv6. This should be now fixed.
+
+ -- Christian Kurz <shorty@debian.org>  Thu, 11 Jan 2001 21:25:55 +0100
+
+openssh (1:2.3.0p1-1.4) unstable; urgency=high
+
+  * Fixed buggy entry in postinst.
+
+ -- Christian Kurz <shorty@debian.org>  Wed, 10 Jan 2001 23:12:16 +0100
+
+openssh (1:2.3.0p1-1.3) unstable; urgency=high
+
+  * After finishing the rewrite of the rules-file I had to notice that
+    the manpage installation was broken. This should now work again.
+
+ -- Christian Kurz <shorty@debian.org>  Wed, 10 Jan 2001 22:11:59 +0100
+
+openssh (1:2.3.0p1-1.2) unstable; urgency=high
+
+  * Fixed the screwed up build-dependency.
+  * Removed --with-ipv4-default to support ipv6.
+  * Changed makefile to use /etc/pam.d/ssh instead of /etc/pam.d/sshd.
+  * Fixed location to sftp-server in config.
+  * Since debian still relies on /etc/pam.d/ssh instead of moving to
+    /etc/pam.d/sshd, I had to hack ssh.h to get ssh to use this name.
+  * Fixed path to host key in sshd_config.
+
+ -- Christian Kurz <shorty@debian.org>  Wed, 10 Jan 2001 08:23:47 +0100
+
+openssh (1:2.3.0p1-1.1) unstable; urgency=medium
+
+  * NMU with permission of Phil Hands.
+  * New upstream release
+  * Update Build-Depends to point to new libssl096.
+  * This upstream release doesn't leak any information depending
+    on the setting of PermitRootLogin (Closes: #59933)
+  * New upstream release contains fix against forcing a client to 
+    do X/agent forwarding (Closes: #76788)
+  * Changed template to contain correct path to the documentation 
+    (Closes: #67245)
+  * Added --with-4in6 switch as compile option into debian/rules.      
+  * Added --with-ipv4-default as compile option into debian/rules. 
+    (Closes: #75037)
+  * Changed default path to also contain /usr/local/bin and 
+    /usr/X11R6/bin (Closes: #62472,#54567,#62810)
+  * Changed path to sftp-server in sshd_config to match the
+    our package (Closes: #68347)
+  * Replaced OpenBSDh with OpenBSD in the init-script. 
+  * Changed location to original source in copyright.head
+  * Changed behaviour of init-script when invoked with the option
+    restart (Closes: #68706,#72560)
+  * Added a note about -L option of scp to README.Debian       
+  * ssh won't print now the motd if invoked with -t option
+    (Closes: #59933)
+  * RFC.nroff.gz get's now converted into RFC.gz. (Closes: #63867)     
+  * Added a note about tcp-wrapper support to README.Debian 
+    (Closes: #72807,#22190)
+  * Removed two unneeded options from building process.        
+  * Added sshd.pam into debian dir and install it.
+  * Commented out unnecessary call to dh_installinfo.
+  * Added a line to sshd.pam so that limits will be paid attention
+    to (Closes: #66904)
+  * Restart Option has a Timeout of 10 seconds (Closes: 51264)
+  * scp won't override files anymore (Closes: 51955)
+  * Removed pam_lastlog module, so that the lastlog is now printed
+    only once (Closes: #71742, #68335, #69592, #71495, #77781)
+  * If password is expired, openssh now forces the user to change it.
+    (Closes: #51747)
+  * scp should now have no more problems with shell-init-files that
+    produces ouput (Closes: #56280,#59873)
+  * ssh now prints the motd correctly (Closes: #66926) 
+  * ssh upgrade should disable ssh daemon only if users has choosen
+    to do so (Closes: #67478)
+  * ssh can now be installed suid (Closes: #70879)     
+  * Modified debian/rules to support hurd.
+
+ -- Christian Kurz <shorty@debian.org>  Wed, 27 Dec 2000 20:06:57 +0100
+
+openssh (1:2.2.0p1-1.1) unstable; urgency=medium
+
+  * Non-Maintainer Upload
+  * Check for new returns in the new libc
+    (closes: #72803, #74393, #72797, #71307, #71702)
+  * Link against libssl095a (closes: #66304)
+  * Correct check for PermitRootLogin (closes: #69448)
+
+ -- Ryan Murray <rmurray@debian.org>  Wed, 18 Oct 2000 00:48:18 -0700
+
+openssh (1:2.2.0p1-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Philip Hands <phil@hands.com>  Mon, 11 Sep 2000 14:49:43 +0100
+
+openssh (1:2.1.1p4-3) unstable; urgency=low
+
+  * add rsh alternatives
+  * add -S option to scp (using Tommi Virtanen's patch) (closes: #63097)
+  * do the IPV4_DEFAULT thing properly this time
+
+ -- Philip Hands <phil@hands.com>  Fri, 11 Aug 2000 18:14:37 +0100
+
+openssh (1:2.1.1p4-2) unstable; urgency=low
+
+  * reinstate manpage .out patch from 1:1.2.3
+  * fix typo in postinst
+  * only compile ssh with IPV4_DEFAULT
+  * apply James Troup's patch to add a -o option to scp and updated manpage
+
+ -- Philip Hands <phil@hands.com>  Sun, 30 Jul 2000 00:12:49 +0100
+
+openssh (1:2.1.1p4-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Philip Hands <phil@hands.com>  Sat, 29 Jul 2000 14:46:16 +0100
+
+openssh (1:1.2.3-10) unstable; urgency=low
+
+  * add version to libpam-modules dependency, because old versions of
+    pam_motd make it impossible to log in.
+
+ -- Philip Hands <phil@hands.com>  Sat, 29 Jul 2000 13:28:22 +0100
+
+openssh (1:1.2.3-9) frozen unstable; urgency=low
+
+  * force location of /usr/bin/X11/xauth
+    (closes: #64424, #66437, #66859)  *RC*
+  * typos in config (closes: #66779, #66780)
+  * sshd_not_to_be_run could be assumed to be true, in error, if the config
+    script died in an unusual way --- I've reversed this (closes: #66335)  
+  * Apply Zack Weinberg <zack@wolery.cumb.org>'s patch to ssh-askpass-ptk
+    (closes: #65981)
+  * change default for PermitRootLogin to "no" (closes: #66406)
+
+ -- Philip Hands <phil@hands.com>  Tue, 11 Jul 2000 20:51:18 +0100
+
+openssh (1:1.2.3-8) frozen unstable; urgency=low
+
+  * get rid of Provides: rsh-server (this will mean that rstartd
+    will need to change it's depends to deal with #63948, which I'm
+    reopening)  (closes: #66257)
+    Given that this is also a trivial change, and is a reversal of a
+    change that was mistakenly made after the freeze, I think this should
+    also go into frozen.
+
+ -- Philip Hands <phil@hands.com>  Wed, 28 Jun 2000 03:26:30 +0100
+
+openssh (1:1.2.3-7) frozen unstable; urgency=low
+
+  * check if debconf is installed before calling db_stop in postinst.
+    This is required to allow ssh to be installed when debconf is not
+    wanted, which probably makes it an RC upload (hopefully the last of
+    too many).
+
+ -- Philip Hands <phil@hands.com>  Wed, 28 Jun 2000 03:19:47 +0100
+
+openssh (1:1.2.3-6) frozen unstable; urgency=low
+
+  * fixed depressing little bug involving a line wrap looking like
+    a blank line in the templates file   *RC*
+    (closes: #66090, #66078, #66083, #66182)
+
+ -- Philip Hands <phil@hands.com>  Mon, 26 Jun 2000 00:45:05 +0100
+
+openssh (1:1.2.3-5) frozen unstable; urgency=low
+
+  * add code to prevent UseLogin exploit, although I think our PAM
+    conditional code breaks UseLogin in a way that protects us from this
+    exploit anyway. ;-)  (closes: #65495)  *RC*
+  * Apply Zack Weinberg <zack@wolery.cumb.org>'s patch to fix keyboard
+    grab vulnerability in ssh-askpass-gnome (closes: #64795) *RC*
+  * stop redirection of sshd's file descriptors (introduced in 1:1.2.3-3)
+    and use db_stop in the postinst to solve that problem instead
+    (closes: #65104)
+  * add Provides: rsh-server to ssh (closes: #63948)
+  * provide config option not to run sshd
+
+ -- Philip Hands <phil@hands.com>  Mon, 12 Jun 2000 23:05:11 +0100
+
+openssh (1:1.2.3-4) frozen unstable; urgency=low
+
+  * fixes #63436 which is *RC*
+  * add 10 second pause in init.d restart (closes: #63844)
+  * get rid of noenv in PAM mail line (closes: #63856)
+  * fix host key path in make-ssh-known-hosts (closes: #63713)
+  * change wording of SUID template (closes: #62788, #63436)
+
+ -- Philip Hands <phil@hands.com>  Sat, 27 May 2000 11:18:06 +0100
+
+openssh (1:1.2.3-3) frozen unstable; urgency=low
+
+  * redirect sshd's file descriptors to /dev/null in init to
+    prevent debconf from locking up during installation 
+    ** grave bug just submited by me **
+
+ -- Philip Hands <phil@hands.com>  Thu, 20 Apr 2000 17:10:59 +0100
+
+openssh (1:1.2.3-2) frozen  unstable; urgency=low
+
+  * allow user to select SUID status of /usr/bin/ssh (closes: 62462) ** RC **
+  * suggest debconf
+  * conflict with debconf{,-tiny} (<<0.2.17) so I can clean up the preinst
+
+ -- Philip Hands <phil@hands.com>  Wed, 19 Apr 2000 17:49:15 +0100
+
+openssh (1:1.2.3-1) frozen unstable; urgency=low
+
+  * New upstream release
+  * patch sshd to create extra xauth key required for localhost
+    (closes: #49944)  *** RC ***
+  * FallbacktoRsh now defaults to ``no'' to match impression
+    given in sshd_config
+  * stop setting suid bit on ssh (closes: #58711, #58558)
+    This breaks Rhosts authentication (which nobody uses) and allows
+    the LD_PRELOAD trick to get socks working, so seems like a net benefit.
+
+ -- Philip Hands <phil@hands.com>  Thu, 13 Apr 2000 20:01:54 +0100
+
+openssh (1:1.2.2-1.4) frozen unstable; urgency=low
+
+  * Recompile for frozen, contains fix for RC bug.
+
+ -- Tommi Virtanen <tv@debian.org>  Tue, 29 Feb 2000 22:14:58 +0200
+
+openssh (1:1.2.2-1.3) unstable; urgency=low
+
+  * Integrated man page addition for PrintLastLog.
+    This bug was filed on "openssh", and I ended up
+    creating my own patch for this (closes: #59054)
+  * Improved error message when ssh_exchange_identification
+    gets EOF (closes: #58904)
+  * Fixed typo (your -> you're) in debian/preinst.
+  * Added else-clauses to config to make this upgradepath possible:
+    oldssh -> openssh preinst fails due to upgrade_to_openssh=false
+    -> ssh-nonfree -> openssh. Without these, debconf remembered
+    the old answer, config didn't force asking it, and preinst always
+    aborted (closes: #56596, #57782)
+  * Moved setting upgrade_to_openssh isdefault flag to the place
+    where preinst would abort. This means no double question to most
+    users, people who currently suffer from "can't upgrade" may need
+    to run apt-get install ssh twice. Did not do the same for 
+    use_old_init_script, as the situation is a bit different, and
+    less common (closes: #54010, #56224)
+  * Check for existance of ssh-keygen before attempting to use it in
+    preinst, added warning for non-existant ssh-keygen in config. This
+    happens when the old ssh is removed (say, due to ssh-nonfree getting
+    installed).
+
+ -- Tommi Virtanen <tv@debian.org>  Sun, 27 Feb 2000 21:36:43 +0200
+
+openssh (1:1.2.2-1.2) frozen unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Added configuration option PrintLastLog, default off due to PAM
+    (closes: #54007, #55042)
+  * ssh-askpass-{gnome,ptk} now provide ssh-askpass, making ssh's
+    Suggests: line more accurate. Also closing related bugs fixed
+    earlier, when default ssh-askpass moved to /usr/bin.
+    (closes: #52403, #54741, #50607, #52298, #50967, #51661)
+  * Patched to call vhangup, with autoconf detection and all
+    (closes: #55379)
+  * Added --with-ipv4-default workaround to a glibc bug causing
+    slow DNS lookups, as per UPGRADING. Use -6 to really use
+    IPv6 addresses. (closes: #57891, #58744, #58713, #57970)
+  * Added noenv to PAM pam_mail line. Thanks to Ben Collins.
+    (closes: #58429)
+  * Added the UPGRADING file to the package.
+  * Added frozen to the changelog line and recompiled before
+    package was installed into the archive.
+
+ -- Tommi Virtanen <tv@debian.org>  Fri, 25 Feb 2000 22:08:57 +0200
+
+openssh (1:1.2.2-1.1) frozen unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Integrated scp pipe buffer patch from Ben Collins
+    <benc@debian.org>, should now work even if reading
+    a pipe gives less than fstat st_blksize bytes. 
+    Should now work on Alpha and Sparc Linux (closes: #53697, #52071)
+  * Made ssh depend on libssl09 (>= 0.9.4-3) (closes: #51393)
+  * Integrated patch from Ben Collins <benc@debian.org>
+    to do full shadow account locking and expiration
+    checking (closes: #58165, #51747)
+
+ -- Tommi Virtanen <tv@debian.org>  Tue, 22 Feb 2000 20:46:12 +0200
+
+openssh (1:1.2.2-1) frozen unstable; urgency=medium
+
+  * New upstream release (closes: #56870, #56346)
+  * built against new libesd (closes: #56805)
+  * add  Colin Watson <cjw44@cam.ac.uk> =NULL patch
+    (closes: #49902, #54894)
+  * use socketpairs as suggested by Andrew Tridgell to eliminate rsync
+    (and other) lockups
+  * patch SSHD_PAM_SERVICE back into auth-pam.c, again :-/
+    (closes: #49902, #55872, #56959)
+  * uncoment the * line in ssh_config (closes: #56444)
+  
+  * #54894 & #49902 are release critical, so this should go in frozen
+
+ -- Philip Hands <phil@hands.com>  Wed,  9 Feb 2000 04:52:04 +0000
+
+openssh (1:1.2.1pre24-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Philip Hands <phil@hands.com>  Fri, 31 Dec 1999 02:47:24 +0000
+
+openssh (1:1.2.1pre23-1) unstable; urgency=low
+
+  * New upstream release
+  * excape ? in /etc/init.d/ssh (closes: #53269)
+
+ -- Philip Hands <phil@hands.com>  Wed, 29 Dec 1999 16:50:46 +0000
+
+openssh (1:1.2pre17-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Philip Hands <phil@hands.com>  Thu,  9 Dec 1999 16:50:40 +0000
+
+openssh (1:1.2pre16-1) unstable; urgency=low
+
+  * New upstream release
+  * upstream release (1.2pre14) (closes: #50299)
+  * make ssh depend on libwrap0 (>= 7.6-1.1) (closes: #50973, #50776)
+  * dispose of grep -q broken pipe message in config script (closes: #50855)
+  * add make-ssh-known-hosts (closes: #50660)
+  * add -i option to ssh-copy-id (closes: #50657)
+  * add check for *LK* in password, indicating a locked account
+
+ -- Philip Hands <phil@hands.com>  Wed,  8 Dec 1999 22:59:38 +0000
+
+openssh (1:1.2pre13-1) unstable; urgency=low
+
+  * New upstream release
+  * make sshd.c use SSHD_PAM_SERVICE and define it as "ssh" in debian/rules
+  * remove duplicate line in /etc/pam.d/ssh (closes: #50310)
+  * mention ssh -A option in ssh.1 & ssh_config
+  * enable forwarding to localhost in default ssh_config (closes: #50373)
+  * tweak preinst to deal with debconf being `unpacked'
+  * use --with-tcp-wrappers (closes: #49545)
+
+ -- Philip Hands <phil@hands.com>  Sat, 20 Nov 1999 14:20:04 +0000
+
+openssh (1:1.2pre11-2) unstable; urgency=low
+
+  * oops, just realised that I forgot to strip out the unpleasant
+    fiddling mentioned below (which turned not to be a fix anyway)
+
+ -- Philip Hands <phil@hands.com>  Mon, 15 Nov 1999 01:35:23 +0000
+
+openssh (1:1.2pre11-1) unstable; urgency=low
+
+  * New upstream release (closes: #49722)
+  * add 2>/dev/null to dispose of spurious message casused by grep -q
+    (closes: #49876, #49604)
+  * fix typo in debian/control (closes: #49841)
+  * Do some unpleasant fiddling with upgraded keys in the preinst, which
+    should make the keylength problem go away.   (closes: #49676)
+  * make pam_start in sshd use ``ssh'' as the service name (closes: #49956)
+  * If /etc/ssh/NOSERVER exist, stop sshd from starting (closes: #47107)
+  * apply Ben Collins <bcollins@debian.org>'s shadow patch
+  * disable lastlogin and motd printing if using pam (closes: #49957)
+  * add ssh-copy-id script and manpage
+
+ -- Philip Hands <phil@hands.com>  Fri, 12 Nov 1999 01:03:38 +0000
+
+openssh (1:1.2pre9-1) unstable; urgency=low
+
+  * New upstream release
+  * apply Chip Salzenberg <chip@valinux.com>'s SO_REUSEADDR patch
+    to channels.c, to make forwarded ports instantly reusable
+  * replace Pre-Depend: debconf with some check code in preinst
+  * make the ssh-add ssh-askpass failure message more helpful
+  * fix the ssh-agent getopts bug (closes: #49426)
+  * fixed typo on Suggests: line (closes: #49704, #49571)
+  * tidy up ssh package description (closes: #49642)
+  * make ssh suid (closes: #49635)
+  * in preinst upgrade code, ensure ssh_host_keys is mode 600 (closes: #49606)
+  * disable agent forwarding by default, for the similar reasons as
+    X forwarding (closes: #49586)
+
+ -- Philip Hands <phil@hands.com>  Tue,  9 Nov 1999 09:57:47 +0000
+
+openssh (1:1.2pre7-4) unstable; urgency=low
+
+  * predepend on debconf (>= 0.2.17) should now allow preinst questions
+
+ -- Philip Hands <phil@hands.com>  Sat,  6 Nov 1999 10:31:06 +0000
+
+openssh (1:1.2pre7-3) unstable; urgency=low
+
+  * add ssh-askpass package using Tommi Virtanen's perl-tk script
+  * add ssh-preconfig package cludge
+  * add usage hints to ssh-agent.1
+
+ -- Philip Hands <phil@hands.com>  Fri,  5 Nov 1999 00:38:33 +0000
+
+openssh (1:1.2pre7-2) unstable; urgency=low
+
+  * use pam patch from Ben Collins <bcollins@debian.org>
+  * add slogin symlink to Makefile.in
+  * change /usr/bin/login to LOGIN_PROGRAM define of /bin/login 
+  * sort out debconf usage
+  * patch from Tommi Virtanen <tv@debian.org>'s makes ssh-add use ssh-askpass
+
+ -- Philip Hands <phil@hands.com>  Thu,  4 Nov 1999 11:08:54 +0000
+
+openssh (1:1.2pre7-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Philip Hands <phil@hands.com>  Tue,  2 Nov 1999 21:02:37 +0000
+
+openssh (1:1.2.0.pre6db1-2) unstable; urgency=low
+
+  * change the binary package name to ssh (the non-free branch of ssh has
+    been renamed to ssh-nonfree)
+  * make pam file comply with Debian standards
+  * use an epoch to make sure openssh supercedes ssh-nonfree
+
+ -- Philip Hands <phil@hands.com>  Sat, 30 Oct 1999 16:26:05 +0100
+
+openssh (1.2pre6db1-1) unstable; urgency=low
+
+  * New upstream source
+  * sshd accepts logins now!
+
+ -- Dan Brosemer <odin@linuxfreak.com>  Fri, 29 Oct 1999 11:13:38 -0500
+
+openssh (1.2.0.19991028-1) unstable; urgency=low
+
+  * New upstream source
+  * Added test for -lnsl to configure script
+
+ -- Dan Brosemer <odin@linuxfreak.com>  Thu, 28 Oct 1999 18:52:09 -0500
+
+openssh (1.2.0.19991027-3) unstable; urgency=low
+
+  * Initial release
+
+ -- Dan Brosemer <odin@linuxfreak.com>  Wed, 27 Oct 1999 19:39:46 -0500
diff --git a/debian/clean b/debian/clean
new file mode 100644 (file)
index 0000000..5da17f8
--- /dev/null
@@ -0,0 +1 @@
+config.log
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7f8f011
--- /dev/null
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..8ea645d
--- /dev/null
@@ -0,0 +1,133 @@
+Source: openssh
+Section: net
+Priority: standard
+Maintainer: Debian OpenSSH Maintainers <debian-ssh@lists.debian.org>
+Build-Depends: libwrap0-dev | libwrap-dev, zlib1g-dev (>= 1:1.2.3-1), libssl-dev (>= 0.9.8g), libpam0g-dev | libpam-dev, libgtk2.0-dev, libedit-dev, debhelper (>= 7.4.2~), libselinux1-dev [linux-any], libkrb5-dev | heimdal-dev, hardening-includes
+Standards-Version: 3.8.4
+Uploaders: Colin Watson <cjwatson@debian.org>, Matthew Vernon <matthew@debian.org>
+Homepage: http://www.openssh.org/
+Vcs-Bzr: http://anonscm.debian.org/bzr/pkg-ssh/openssh/trunk
+Vcs-Browser: http://anonscm.debian.org/loggerhead/pkg-ssh/openssh/trunk
+
+Package: openssh-client
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, debconf (>= 1.2.0) | debconf-2.0, adduser (>= 3.10), dpkg (>= 1.7.0), passwd
+Recommends: xauth, openssh-blacklist, openssh-blacklist-extra
+Conflicts: ssh (<< 1:3.8.1p1-9), sftp, rsh-client (<<0.16.1-1), ssh-krb5 (<< 1:4.3p2-7)
+Replaces: ssh, ssh-krb5
+Suggests: ssh-askpass, libpam-ssh, keychain, monkeysphere
+Provides: rsh-client, ssh-client
+Description: secure shell (SSH) client, for secure access to remote machines
+ This is the portable version of OpenSSH, a free implementation of
+ the Secure Shell protocol as specified by the IETF secsh working
+ group.
+ .
+ Ssh (Secure Shell) is a program for logging into a remote machine
+ and for executing commands on a remote machine.
+ It provides secure encrypted communications between two untrusted
+ hosts over an insecure network. X11 connections and arbitrary TCP/IP
+ ports can also be forwarded over the secure channel.
+ It can be used to provide applications with a secure communication
+ channel.
+ .
+ This package provides the ssh, scp and sftp clients, the ssh-agent
+ and ssh-add programs to make public key authentication more convenient,
+ and the ssh-keygen, ssh-keyscan, ssh-copy-id and ssh-argv0 utilities.
+ .
+ In some countries it may be illegal to use any encryption at all
+ without a special permit.
+ .
+ ssh replaces the insecure rsh, rcp and rlogin programs, which are
+ obsolete for most purposes.
+
+Package: openssh-server
+Priority: optional
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, debconf (>= 1.2.0) | debconf-2.0, libpam-runtime (>= 0.76-14), libpam-modules (>= 0.72-9), adduser (>= 3.9), dpkg (>= 1.9.0), openssh-client (= ${binary:Version}), lsb-base (>= 3.2-13), procps
+Recommends: xauth, openssh-blacklist, openssh-blacklist-extra, ${openssh-server:Recommends}
+Conflicts: ssh (<< 1:3.8.1p1-9), ssh-nonfree (<<2), ssh-socks, ssh2, sftp, rsh-client (<<0.16.1-1), ssh-krb5 (<< 1:4.3p2-7)
+Replaces: ssh, openssh-client (<< 1:3.8.1p1-11), ssh-krb5
+Suggests: ssh-askpass, rssh, molly-guard, ufw, monkeysphere
+Provides: ssh-server
+Description: secure shell (SSH) server, for secure access from remote machines
+ This is the portable version of OpenSSH, a free implementation of
+ the Secure Shell protocol as specified by the IETF secsh working
+ group.
+ .
+ Ssh (Secure Shell) is a program for logging into a remote machine
+ and for executing commands on a remote machine.
+ It provides secure encrypted communications between two untrusted
+ hosts over an insecure network. X11 connections and arbitrary TCP/IP
+ ports can also be forwarded over the secure channel.
+ It can be used to provide applications with a secure communication
+ channel.
+ .
+ This package provides the sshd server.
+ .
+ In some countries it may be illegal to use any encryption at all
+ without a special permit.
+ .
+ sshd replaces the insecure rshd program, which is obsolete for most
+ purposes.
+
+Package: ssh
+Priority: extra
+Architecture: all
+Depends: ${misc:Depends}, openssh-client, openssh-server
+Description: secure shell client and server (metapackage)
+ This metapackage is a convenient way to install both the OpenSSH client
+ and the OpenSSH server. It provides nothing in and of itself, so you
+ may remove it if nothing depends on it.
+
+Package: ssh-krb5
+Priority: extra
+Architecture: all
+Depends: ${misc:Depends}, openssh-client, openssh-server
+Description: secure shell client and server (transitional package)
+ This is a transitional package depending on the regular Debian OpenSSH
+ client and server, which now support GSSAPI natively. It will add the
+ necessary GSSAPI options to the server configuration file. You can
+ remove it once the upgrade is complete and nothing depends on it.
+
+Package: ssh-askpass-gnome
+Section: gnome
+Priority: optional
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, openssh-client | ssh (>= 1:1.2pre7-4) | ssh-krb5
+Replaces: ssh (<< 1:3.5p1-3)
+Provides: ssh-askpass
+Description: interactive X program to prompt users for a passphrase for ssh-add
+ This has been split out of the main openssh-client package so that
+ openssh-client does not need to depend on GTK+.
+ .
+ You probably want the ssh-askpass package instead, but this is
+ provided to add to your choice and/or confusion.
+
+Package: openssh-client-udeb
+XC-Package-Type: udeb
+Section: debian-installer
+Priority: optional
+Architecture: any
+Depends: ${shlibs:Depends}, libnss-files-udeb
+XB-Installer-Menu-Item: 99999
+Description: secure shell client for the Debian installer
+ This is the portable version of OpenSSH, a free implementation of
+ the Secure Shell protocol as specified by the IETF secsh working
+ group.
+ .
+ This package provides the ssh client for use in debian-installer.
+
+Package: openssh-server-udeb
+XC-Package-Type: udeb
+Section: debian-installer
+Priority: optional
+Architecture: any
+Depends: ${shlibs:Depends}, libnss-files-udeb
+Description: secure shell server for the Debian installer
+ This is the portable version of OpenSSH, a free implementation of
+ the Secure Shell protocol as specified by the IETF secsh working
+ group.
+ .
+ This package provides the sshd server for use in debian-installer.
+ Since it is expected to be used in specialized situations (e.g. S/390
+ installs with no console), it does not provide any configuration.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..15f3017
--- /dev/null
@@ -0,0 +1,391 @@
+This package was debianized by Philip Hands <phil@hands.com> on 31 Oct 1999
+(with help from  Dan Brosemer <odin@linuxfreak.com>)
+
+It was downloaded from here:
+  ftp://ftp.fu-berlin.de/unix/security/openssh/openssh-2.3.0p1.tar.gz
+
+worldwide mirrors are listed here:
+  http://www.openssh.com/ftp.html
+
+The Debian specific parts of the package are mostly taken from the
+original ssh package, which has since been renamed as ssh-nonfree.
+
+The Debian patch is distributed under the terms of the GPL, which you
+can find in /usr/share/common-licenses/GPL.
+
+In addition, as a special exception, Matthew Vernon gives permission
+to link the code of the Debian patch with any version of the OpenSSH
+code which is distributed under a license identical to that listed in
+the included Copyright file, and distribute linked combinations
+including the two.  You must obey the GNU General Public License in
+all respects for all of the code used other than OpenSSH.  If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so.  If you do not wish to do
+so, delete this exception statement from your version.
+
+The upstream source for this package is a combination of the ssh
+branch that is being maintained by the OpenBSD team (starting from
+the last version of SSH that was distributed under a free license),
+and porting work by Damien Miller <damien@ibs.com.au> to get it
+working on Linux.  Other people also contributed to this, and are
+credited in /usr/share/doc/ssh/README.
+
+This package contains Kerberos version 5 patches from
+http://www.sxw.org.uk/computing/patches/openssh.html; this is Copyright
+(c) 2001-2009 Simon Wilkinson and provided under the standard 2-term BSD
+licence used elsewhere in OpenSSH.
+
+Copyright:
+
+Code in helper.[ch] is Copyright Internet Business Solutions and is
+released under a X11-style license (see source file for details).
+
+(A)RC4 code in rc4.[ch] is Copyright Damien Miller. It too is under a
+X11-style license (see source file for details).
+
+make-ssh-known-hosts is Copyright Tero Kivinen <Tero.Kivinen@hut.fi>,
+and is distributed under the GPL (see source file for details).
+
+The copyright for the original SSH version follows.  It has been
+modified with [comments] to reflect the changes that the OpenBSD folks
+have made:
+
+This file is part of the OpenSSH software.
+
+The licences which components of this software fall under are as
+follows.  First, we will summarize and say that all components
+are under a BSD licence, or a licence more free than that.
+
+OpenSSH contains no GPL code.
+
+1)
+     * Copyright (c) 1995 Tatu Ylonen <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".
+
+    [Tatu continues]
+     *  However, I am not implying to give any licenses to any patents or
+     * copyrights held by third parties, and the software includes parts that
+     * are not under my direct control.  As far as I know, all included
+     * source code is used in accordance with the relevant license agreements
+     * and can be used freely for any purpose (the GNU license being the most
+     * restrictive); see below for details.
+
+    [However, none of that term is relevant at this point in time.  All of
+    these restrictively licenced software components which he talks about
+    have been removed from OpenSSH, i.e.,
+
+     - RSA is no longer included, found in the OpenSSL library
+     - IDEA is no longer included, its use is deprecated
+     - DES is now external, in the OpenSSL library
+     - GMP is no longer used, and instead we call BN code from OpenSSL
+     - Zlib is now external, in a library
+     - The make-ssh-known-hosts script is no longer included
+     - TSS has been removed
+     - MD5 is now external, in the OpenSSL library
+     - RC4 support has been replaced with ARC4 support from OpenSSL
+     - Blowfish is now external, in the OpenSSL library
+
+    [The licence continues]
+
+    Note that any information and cryptographic algorithms used in this
+    software are publicly available on the Internet and at any major
+    bookstore, scientific library, and patent office worldwide.  More
+    information can be found e.g. at "http://www.cs.hut.fi/crypto".
+
+    The legal status of this program is some combination of all these
+    permissions and restrictions.  Use only at your own responsibility.
+    You will be responsible for any legal consequences yourself; I am not
+    making any claims whether possessing or using this is legal or not in
+    your country, and I am not taking any responsibility on your behalf.
+
+
+                           NO WARRANTY
+
+    BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+    REPAIR OR CORRECTION.
+
+    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+    POSSIBILITY OF SUCH DAMAGES.
+
+2)
+    The 32-bit CRC compensation attack detector in deattack.c was
+    contributed by CORE SDI S.A. under a BSD-style license.
+
+     * Cryptographic attack detector for ssh - source code
+     *
+     * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
+     *
+     * All rights reserved. Redistribution and use in source and binary
+     * forms, with or without modification, are permitted provided that
+     * this copyright notice is retained.
+     *
+     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+     * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
+     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
+     * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
+     * SOFTWARE.
+     *
+     * Ariel Futoransky <futo@core-sdi.com>
+     * <http://www.core-sdi.com>
+
+3)
+    ssh-keyscan was contributed by David Mazieres under a BSD-style
+    license.
+
+     * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
+     *
+     * Modification and redistribution in source and binary forms is
+     * permitted provided that due credit is given to the author and the
+     * OpenBSD project by leaving this copyright notice intact.
+
+4)
+    The Rijndael implementation by Vincent Rijmen, Antoon Bosselaers
+    and Paulo Barreto is in the public domain and distributed
+    with the following license:
+
+     * @version 3.0 (December 2000)
+     *
+     * Optimised ANSI C code for the Rijndael cipher (now AES)
+     *
+     * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+     * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+     * @author Paulo Barreto <paulo.barreto@terra.com.br>
+     *
+     * This code is hereby placed in the public domain.
+     *
+     * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+     * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+     * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+     * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+5)
+    One component of the ssh source code is under a 3-clause BSD license,
+    held by the University of California, since we pulled these parts from
+    original Berkeley code.
+
+     * Copyright (c) 1983, 1990, 1992, 1993, 1995
+     *      The Regents of the University of California.  All rights reserved.
+     *
+     * Redistribution and use in source and binary forms, with or without
+     * modification, are permitted provided that the following conditions
+     * are met:
+     * 1. Redistributions of source code must retain the above copyright
+     *    notice, this list of conditions and the following disclaimer.
+     * 2. Redistributions in binary form must reproduce the above copyright
+     *    notice, this list of conditions and the following disclaimer in the
+     *    documentation and/or other materials provided with the distribution.
+     * 3. Neither the name of the University nor the names of its contributors
+     *    may be used to endorse or promote products derived from this software
+     *    without specific prior written permission.
+     *
+     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+     * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+     * SUCH DAMAGE.
+
+6)
+    Remaining components of the software are provided under a standard
+    2-term BSD licence with the following names as copyright holders:
+
+       Markus Friedl
+       Theo de Raadt
+       Niels Provos
+       Dug Song
+       Aaron Campbell
+       Damien Miller
+       Kevin Steves
+       Daniel Kouril
+       Wesley Griffin
+       Per Allansson
+       Nils Nordman
+       Simon Wilkinson
+
+    Portable OpenSSH additionally includes code from the following copyright
+    holders, also under the 2-term BSD license:
+
+       Ben Lindstrom
+       Tim Rice
+       Andre Lucas
+       Chris Adams
+       Corinna Vinschen
+       Cray Inc.
+       Denis Parker
+       Gert Doering
+       Jakob Schlyter
+       Jason Downs
+       Juha Yrjölä
+       Michael Stone
+       Networks Associates Technology, Inc.
+       Solar Designer
+       Todd C. Miller
+       Wayne Schroeder
+       William Jones
+       Darren Tucker
+       Sun Microsystems
+       The SCO Group
+       Daniel Walsh
+       Red Hat, Inc
+
+     * Redistribution and use in source and binary forms, with or without
+     * modification, are permitted provided that the following conditions
+     * are met:
+     * 1. Redistributions of source code must retain the above copyright
+     *    notice, this list of conditions and the following disclaimer.
+     * 2. Redistributions in binary form must reproduce the above copyright
+     *    notice, this list of conditions and the following disclaimer in the
+     *    documentation and/or other materials provided with the distribution.
+     *
+     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+     * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+     * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+8) Portable OpenSSH contains the following additional licenses:
+
+    a) md5crypt.c, md5crypt.h
+
+        * "THE BEER-WARE LICENSE" (Revision 42):
+        * <phk@login.dknet.dk> wrote this file.  As long as you retain this
+        * notice you can do whatever you want with this stuff. If we meet
+        * some day, and you think this stuff is worth it, you can buy me a
+        * beer in return.   Poul-Henning Kamp
+
+    b) snprintf replacement
+
+       * Copyright Patrick Powell 1995
+       * This code is based on code written by Patrick Powell
+       * (papowell@astart.com) It may be used for any purpose as long as this
+       * notice remains intact on all source code distributions
+
+    c) Compatibility code (openbsd-compat)
+
+       Apart from the previously mentioned licenses, various pieces of code
+       in the openbsd-compat/ subdirectory are licensed as follows:
+
+       Some code is licensed under a 3-term BSD license, to the following
+       copyright holders:
+
+       Todd C. Miller
+       Theo de Raadt
+       Damien Miller
+       Eric P. Allman
+       The Regents of the University of California
+       Constantin S. Svintsoff
+
+       * Redistribution and use in source and binary forms, with or without
+       * modification, are permitted provided that the following conditions
+       * are met:
+       * 1. Redistributions of source code must retain the above copyright
+       *    notice, this list of conditions and the following disclaimer.
+       * 2. Redistributions in binary form must reproduce the above copyright
+       *    notice, this list of conditions and the following disclaimer in the
+       *    documentation and/or other materials provided with the distribution.
+       * 3. Neither the name of the University nor the names of its contributors
+       *    may be used to endorse or promote products derived from this software
+       *    without specific prior written permission.
+       *
+       * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+       * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+       * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+       * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+       * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+       * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+       * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+       * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+       * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+       * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+       * SUCH DAMAGE.
+
+       Some code is licensed under an ISC-style license, to the following
+       copyright holders:
+
+       Internet Software Consortium.
+       Todd C. Miller
+       Reyk Floeter
+       Chad Mynhier
+
+       * Permission to use, copy, modify, and distribute this software for any
+       * purpose with or without fee is hereby granted, provided that the above
+       * copyright notice and this permission notice appear in all copies.
+       *
+       * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+       * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+       * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+       * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+       * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+       * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+       * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+       Some code is licensed under a MIT-style license to the following
+       copyright holders:
+
+       Free Software Foundation, Inc.
+
+       * Permission is hereby granted, free of charge, to any person obtaining a  *
+       * copy of this software and associated documentation files (the            *
+       * "Software"), to deal in the Software without restriction, including      *
+       * without limitation the rights to use, copy, modify, merge, publish,      *
+       * distribute, distribute with modifications, sublicense, and/or sell       *
+       * copies of the Software, and to permit persons to whom the Software is    *
+       * furnished to do so, subject to the following conditions:                 *
+       *                                                                          *
+       * The above copyright notice and this permission notice shall be included  *
+       * in all copies or substantial portions of the Software.                   *
+       *                                                                          *
+       * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+       * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+       * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+       * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+       * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+       * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+       * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+       *                                                                          *
+       * Except as contained in this notice, the name(s) of the above copyright   *
+       * holders shall not be used in advertising or otherwise to promote the     *
+       * sale, use or other dealings in this Software without prior written       *
+       * authorization.                                                           *
+       ****************************************************************************/
+
+
+------
+$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $
diff --git a/debian/copyright.head b/debian/copyright.head
new file mode 100644 (file)
index 0000000..311a06a
--- /dev/null
@@ -0,0 +1,52 @@
+This package was debianized by Philip Hands <phil@hands.com> on 31 Oct 1999
+(with help from  Dan Brosemer <odin@linuxfreak.com>)
+
+It was downloaded from here:
+  ftp://ftp.fu-berlin.de/unix/security/openssh/openssh-2.3.0p1.tar.gz
+
+worldwide mirrors are listed here:
+  http://www.openssh.com/ftp.html
+
+The Debian specific parts of the package are mostly taken from the
+original ssh package, which has since been renamed as ssh-nonfree.
+
+The Debian patch is distributed under the terms of the GPL, which you
+can find in /usr/share/common-licenses/GPL.
+
+In addition, as a special exception, Matthew Vernon gives permission
+to link the code of the Debian patch with any version of the OpenSSH
+code which is distributed under a license identical to that listed in
+the included Copyright file, and distribute linked combinations
+including the two.  You must obey the GNU General Public License in
+all respects for all of the code used other than OpenSSH.  If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so.  If you do not wish to do
+so, delete this exception statement from your version.
+
+The upstream source for this package is a combination of the ssh
+branch that is being maintained by the OpenBSD team (starting from
+the last version of SSH that was distributed under a free license),
+and porting work by Damien Miller <damien@ibs.com.au> to get it
+working on Linux.  Other people also contributed to this, and are
+credited in /usr/share/doc/ssh/README.
+
+This package contains Kerberos version 5 patches from
+http://www.sxw.org.uk/computing/patches/openssh.html; this is Copyright
+(c) 2001-2009 Simon Wilkinson and provided under the standard 2-term BSD
+licence used elsewhere in OpenSSH.
+
+Copyright:
+
+Code in helper.[ch] is Copyright Internet Business Solutions and is
+released under a X11-style license (see source file for details).
+
+(A)RC4 code in rc4.[ch] is Copyright Damien Miller. It too is under a
+X11-style license (see source file for details).
+
+make-ssh-known-hosts is Copyright Tero Kivinen <Tero.Kivinen@hut.fi>,
+and is distributed under the GPL (see source file for details).
+
+The copyright for the original SSH version follows.  It has been
+modified with [comments] to reflect the changes that the OpenBSD folks
+have made:
+
diff --git a/debian/faq.html b/debian/faq.html
new file mode 100644 (file)
index 0000000..f856fa3
--- /dev/null
@@ -0,0 +1,1187 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>OpenSSH FAQ</title>
+<link rev= "made" href= "mailto:www@openbsd.org">
+<meta name= "resource-type" content= "document">
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta name= "description"   content= "the OpenSSH FAQ page">
+<meta name= "keywords"      content= "OpenSSH,SSH,Secure Shell,faq">
+<meta name= "distribution"  content= "global">
+<meta name= "copyright"     content= "This document copyright 1999-2010 OpenBSD.">
+</head>
+
+<body bgcolor= "#ffffff" text= "#000000" link= "#23238E">
+<a href="http://www.openssh.org/index.html"><img alt="[OpenSSH]" height="30" width="141" src="images/smalltitle.gif" border="0"></a>
+<p>
+
+<h1>OpenSSH FAQ (Frequently asked questions)</h1>
+
+<hr>
+
+<blockquote>
+<h3><a href= "#1.0">1.0 - What Is OpenSSH and Where Can I Get It?</a></h3>
+<ul>
+<li><a href= "#1.1">1.1 - What is OpenSSH and where can I download it?</a>
+<li><a href= "#1.2">1.2 - Why should it be used?</a>
+<li><a href= "#1.3">1.3 - What Operating Systems are supported?</a>
+<li><a href= "#1.4">1.4 - What about copyright, usage and patents?</a>
+<li><a href= "#1.5">1.5 - Where should I ask for help?</a>
+<li><a href= "#1.6">1.6 - I have found a bug. Where do I report it?</a>
+</ul>
+
+<h3><a href= "#2.0">2.0 - General Questions</a></h3>
+<ul>
+<li><a href= "#2.1">2.1 - Why does ssh/scp make connections from low-numbered ports. My firewall blocks these.</a>
+<li><a href= "#2.2">2.2 - Why is the ssh client setuid root?</a>
+<li><a href= "#2.3">2.3 - Why does SSH 2.3 have problems interoperating with OpenSSH 2.1.1?</a>
+<li><a href= "#2.4">2.4 - Why does OpenSSH print: Dispatch protocol error: type 20</a>
+<li><a href= "#2.5">2.5 - Old versions of commercial SSH encrypt host keys with IDEA.</a>
+<li><a href= "#2.6">2.6 - What are these warning messages about key lengths?</a>
+<li><a href= "#2.7">2.7 - X11 and/or agent forwarding does not work.</a>
+<li><a href= "#2.8">2.8 - After upgrading OpenSSH I lost SSH2 support.</a>
+<li><a href= "#2.9">2.9 - sftp/scp fails at connection, but ssh is OK.</a>
+<li><a href= "#2.10">2.10 - Will you add [foo] to scp?</a>
+<li><a href= "#2.11">2.11 - How do I use port forwarding?</a>
+<li><a href= "#2.12">2.12 - My ssh connection freezes or drops out after N minutes of inactivity.</a>
+<li><a href= "#2.13">2.13 - How do I use scp to copy a file with a colon in it?</a>
+<li><a href= "#2.14">2.14 - Why does OpenSSH report its version to clients?</a>
+</ul>
+
+<h3><a href= "#3.0">3.0 - Portable OpenSSH Questions</a></h3>
+<ul>
+<li><a href= "#3.1">3.1 - Spurious PAM authentication messages in logfiles.</a>
+<li><a href= "#3.2">3.2 - Empty passwords not allowed with PAM authentication.</a>
+<li><a href= "#3.3">3.3 - ssh(1) takes a long time to connect or log in</a>
+<li><a href= "#3.4">3.4 - "Can't locate module net-pf-10" messages in log under Linux.</a>
+<li><a href= "#3.5">3.5 - Password authentication doesn't work (eg on Slackware 7.0 or Red Hat Linux 6.x)</a>
+<li><a href= "#3.6">3.6 - Configure or sshd(8) complain about lack of RSA support</a>
+<li><a href= "#3.7">3.7 - "scp: command not found" errors</a>
+<li><a href= "#3.8">3.8 - Unable to read passphrase</a>
+<li><a href= "#3.9">3.9 - 'configure' missing or make fails</a>
+<li><a href= "#3.10">3.10 - Hangs when exiting ssh</a>
+<li><a href= "#3.11">3.11 - Why does ssh hang on exit?</a>
+<li><a href= "#3.12">3.12 - I upgraded to OpenSSH 3.1 and X11 forwarding stopped working.</a>
+<li><a href= "#3.13">3.13 - I upgraded to OpenSSH 3.8 and some X11 programs stopped working.</a>
+<li><a href= "#3.14">3.14 - I copied my public key to authorized_keys but public-key authentication still doesn't work.</a>
+<li><a href= "#3.15">3.15 - OpenSSH versions and PAM behaviour.</a>
+<li><a href= "#3.16">3.16 - Why doesn't "w" or "who" on AIX 5.x show users logged in via ssh?</a>
+</ul>
+
+</blockquote>
+
+<hr>
+
+<h2><u><a name= "1.0">1.0 - What Is OpenSSH and Where Can I Get It?</a></u></h2>
+
+<h2><a name= "1.1">1.1 - What is OpenSSH and where can I download it?</a></h2>
+
+OpenSSH provides end-to-end encrypted replacement of applications such as
+telnet, rlogin, and ftp.
+Unlike these legacy applications, OpenSSH never passes anything
+(including username and password) over the wire in unencrypted form, and
+provides host authentication, to verify that you really are talking to
+the system that you think you are and that no one else can take over
+that session.
+
+<p>
+The OpenSSH suite includes the 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh&amp;sektion=1">ssh(1)</a> 
+program which replaces rlogin and telnet, and 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=scp&amp;sektion=1">scp(1)</a> 
+which replaces 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=rcp&amp;sektion=1">rcp(1)</a> and 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ftp&amp;sektion=1">ftp(1)</a>. 
+OpenSSH has also added 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sftp&amp;sektion=1">sftp(1)</a> and 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sftp-server&amp;sektion=8">sftp-server(8)</a> 
+which implement an easier solution for file-transfer. This is based upon the 
+<a href="http://www.openssh.org/txt/draft-ietf-secsh-filexfer-02.txt">secsh-filexfer</a> IETF draft.
+
+
+<p><strong>OpenSSH consists of a number of programs.</strong>
+
+<ul>
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sshd&amp;sektion=8">sshd(8)</a> - Server program run on the server machine. This listens for connections from client machines, and whenever it receives a connection, it performs authentication and starts serving the client.
+Its behaviour is controlled by the config file <i><a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config&amp;sektion=5">
+sshd_config(5)</a></i>.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh&amp;sektion=1">ssh(1)</a> - This is the client program used to log into another machine or to execute commands on the other machine. <i>slogin</i> is another name for this program.
+Its behaviour is controlled by the global config file <i><a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh_config&amp;sektion=5">
+ssh_config(5)</a></i> and individual users' <i>$HOME/.ssh/config</i> files.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=scp&amp;sektion=1">scp(1)</a> - Securely copies files from one machine to another.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-keygen&amp;sektion=1">ssh-keygen(1)</a> - Used to create Pubkey Authentication (RSA or DSA) keys (host keys and user authentication keys).
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-agent&amp;sektion=1">ssh-agent(1)</a> - Authentication agent.  This can be used to hold RSA keys for authentication.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-add&amp;sektion=1">ssh-add(1)</a> - Used to register new keys with the agent.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sftp-server&amp;sektion=8">sftp-server(8)</a> - SFTP server subsystem.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sftp&amp;sektion=1">sftp(1)</a> - Secure file transfer program.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-keyscan&amp;sektion=1">ssh-keyscan(1)</a> - gather ssh public keys.
+<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-keysign&amp;sektion=8">ssh-keysign(8)</a> - ssh helper program for hostbased authentication.
+</ul>
+
+<h3>Downloading</h3>
+
+<p>
+The most recent version of OpenSSH is included with the current
+distribution of <a href="http://www.openbsd.org/">OpenBSD</a>, and
+installed as part of a basic install.
+
+<p>
+Today, most other operating systems include some version of OpenSSH
+(often re-badged or privately labeled), so most users can immediately
+use it.
+However, sometimes the included versions are quite old, and missing
+features of the current release of OpenSSH, and you may wish to install
+the current version, or install it on one of the few OSs that lacked it,
+and where the OS publisher does not make a modern version available.
+You may also wish to use OpenSSH on your embedded application.
+
+<p>
+Non-OpenBSD users will want to download, compile and install the
+multi-platform <a href="http://www.openssh.org/portable.html">Portable</a> distribution from a
+<a href="http://www.openssh.org/portable.html#mirrors">mirror</a> near you.
+
+
+<h2><a name= "1.2">1.2 - Why should it be used?</a></h2>
+
+<p>
+OpenSSH is a suite of tools to help secure your network 
+connections. Here is a list of features:
+
+
+<ul>
+       <li>Strong authentication.  Closes several security holes (e.g., IP, routing, and DNS spoofing).
+       <li>Improved privacy.  All communications are automatically and transparently encrypted.
+       <li>Secure X11 sessions.  The program automatically sets DISPLAY on the server machine, and forwards any X11 connections over the secure channel.
+       <li>Arbitrary TCP/IP ports can be redirected through the encrypted channel in both directions (e.g., for e-cash transactions).
+       <li>No retraining needed for normal users.
+       <li>Never trusts the network. Minimal trust on the remote side of the connection. Minimal trust on domain name servers. Pure RSA authentication never trusts anything but the private key.
+       <li>Client RSA-authenticates the server machine in the beginning of every connection to prevent trojan horses (by routing or DNS spoofing) and man-in-the-middle attacks, and the server RSA-authenticates the client machine before accepting <i>.rhosts</i> or <i>/etc/hosts.equiv</i> authentication (to prevent DNS, routing, or IP-spoofing).
+       <li>Host authentication key distribution can be centrally by the administration, automatically when the first connection is made to a machine.
+       <li>Any user can create any number of user authentication RSA keys for his/her own use.
+       <li>The server program has its own server RSA key which is automatically regenerated every hour.
+       <li>An authentication agent, running in the user's laptop or local workstation, can be used to hold the user's RSA authentication keys.
+       <li>The software can be installed and used (with restricted functionality) even without root privileges.
+       <li>The client is customizable in system-wide and per-user configuration files.
+       <li>Optional compression of all data with gzip (including forwarded X11 and TCP/IP port data), which may result in significant speedups on slow connections.
+       <li>Complete replacement for rlogin, rsh, and rcp.
+</ul>
+
+<p>
+Currently, almost all communications in computer networks are done
+without encryption.  As a consequence, anyone who has access to any
+machine connected to the network can listen in on any communication.
+This is being done by hackers, curious administrators, employers,
+criminals, industrial spies, and governments.  Some networks leak off
+enough electromagnetic radiation that data may be captured even from a
+distance.
+
+
+<p>
+When you log in, your password goes in the network in plain
+text.  Thus, any listener can then use your account to do any evil he
+likes.  Many incidents have been encountered worldwide where crackers
+have started programs on workstations without the owner's knowledge
+just to listen to the network and collect passwords.  Programs for
+doing this are available on the Internet, or can be built by a
+competent programmer in a few hours.
+
+
+<p>
+Businesses have trade secrets, patent applications in preparation,
+pricing information, subcontractor information, client data, personnel
+data, financial information, etc.  Currently, anyone with access to
+the network (any machine on the network) can listen to anything that
+goes in the network, without any regard to normal access restrictions.
+
+
+<p>
+Many companies are not aware that information can so easily be
+recovered from the network.  They trust that their data is safe
+since nobody is supposed to know that there is sensitive information
+in the network, or because so much other data is transferred in the
+network.  This is not a safe policy.
+
+
+<h2><a name= "1.3">1.3 - What operating systems are supported?</a></h2>
+
+<p>
+Even though OpenSSH is developed on 
+<a href="http://www.openbsd.org/">OpenBSD</a> a wide variety of 
+ports to other operating systems exist. The portable version of OpenSSH 
+is headed by <a href="mailto:djm@openbsd.org">Damien Miller</a>. 
+For a quick overview of the portable version of OpenSSH see 
+<a href="http://www.openssh.org/portable.html">OpenSSH Portable Release</a>.
+Currently, the supported operating systems are:
+
+
+<ul>
+       <li>OpenBSD
+       <li>NetBSD
+       <li>FreeBSD
+       <li>AIX 
+       <li>HP-UX 
+       <li>IRIX 
+       <li>Linux 
+       <li>NeXT 
+       <li>SCO 
+       <li>SNI/Reliant Unix 
+       <li>Solaris 
+       <li>Digital Unix/Tru64/OSF 
+       <li>Mac OS X 
+       <li>Cygwin
+</ul>
+
+<p>
+A list of vendors that include OpenSSH in their distributions 
+is located in the <a href="http://www.openssh.org/users.html">OpenSSH Users page</a>.
+
+<h2><a name= "1.4">1.4 - What about copyrights, usage and patents?</a></h2>
+<p>
+The OpenSSH developers have tried very hard to keep OpenSSH free of any 
+patent or copyright problems. To do this, some options had to be 
+stripped from OpenSSH. Namely support for patented algorithms.
+
+<p>
+OpenSSH does not support any patented transport algorithms. In SSH1 mode, 
+only 3DES and Blowfish are available options. In SSH2 mode, only 3DES, 
+Blowfish, CAST128, Arcfour and AES can be selected. 
+The patented IDEA algorithm is not supported.
+
+<p>
+OpenSSH provides support for both SSH1 and SSH2 protocols. 
+
+<p>
+Since the RSA patent has expired, there are no restrictions on the use 
+of RSA algorithm using software, including OpenBSD.
+
+<h2><a name= "1.5">1.5 - Where should I ask for help?</a></h2>
+<p>
+There are many places to turn to for help. In addition to the main
+<a href="http://www.openssh.org/index.html">OpenSSH website</a>, 
+there are many mailing lists to try. Before trying any mailing lists, 
+please search through all mailing list archives to see if your question 
+has already been answered. The OpenSSH Mailing List has been archived and 
+put in searchable form and can be found at 
+<a href="http://marc.info/?l=openssh-unix-dev&amp;r=1&amp;w=2">marc.info</a>.
+
+<p>
+For more information on subscribing to OpenSSH related mailing lists, 
+please see <a href="http://www.openssh.org/list.html">OpenSSH Mailing lists</a>.
+
+<h2><a name= "1.6">1.6 - I have found a bug. Where do I report it?</a></h2>
+<p>
+Information about submitting bug reports can be found at the OpenSSH
+<a href="http://www.openssh.org/report.html">Reporting bugs</a> page.
+<p>
+If you wish to report a security bug, please contact the private developers
+list &lt;<a href="mailto:openssh@openssh.com">openssh@openssh.com</a>&gt;.
+
+<h2><u><a name= "2.0">2.0 - General Questions</a></u></h2>
+
+<h2><a name= "2.1">2.1 - Why does ssh/scp make connections from low-numbered ports.</a></h2>
+<p>
+The OpenSSH client uses low numbered ports for rhosts and rhosts-rsa 
+authentication because the server needs to trust the username provided by 
+the client. To get around this, you can add the below example to your 
+<i>ssh_config</i> or <i>~/.ssh/config</i> file.
+
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+<b>UsePrivilegedPort no</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+Or you can specify this option on the command line, using the <b>-o</b> 
+option to 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh&amp;sektion=1">ssh(1)</a> command.
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+$ <b>ssh -o "UsePrivilegedPort no" host.com</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<h2><a name= "2.2">2.2 - Why is the ssh client setuid root?</a></h2>
+
+<p>
+In conjunction with the previous question, (<a href="#2.1">2.1</a>)
+OpenSSH needs root authority to be able to bind to low-numbered ports to 
+facilitate <i>rhosts authentication</i>.
+A privileged port is also required for rhosts-rsa authentication to older
+SSH releases.
+
+<p>
+Additionally, for both <i>rhosts-rsa authentication</i> (in protocol 
+version 1) and <i>hostbased authentication</i> (in protocol version 2) 
+the ssh client needs to access the <i>private host key</i> in order to 
+authenticate the client machine to the server.
+OpenSSH versions prior to 3.3 required the <code>ssh</code> binary to be
+setuid root to enable this, and you may safely remove it if you don't
+want to use these authentication methods.
+
+<p>
+Starting in OpenSSH 3.3, <code>ssh</code> is not setuid by default.  <a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-keysign">ssh-keysign</a>,
+is used for access to the private hosts keys, and ssh does not use privileged
+source ports by default.  If you wish to use a privileged source port, you must
+manually set the setuid bit on <code>ssh</code>.
+
+<h2><a name= "2.3">2.3 - Why does SSH 2.3 have problems interoperating with OpenSSH 2.1.1?</a></h2>
+
+<p>
+SSH 2.3 and earlier versions contain a flaw in their HMAC implementation. 
+Their code was not supplying the full data block output from the digest, 
+and instead always provided 128 bits. For longer digests, this caused 
+SSH 2.3 to not interoperate with OpenSSH.
+
+<p>
+OpenSSH 2.2.0 detects that SSH 2.3 has this flaw. Recent versions of SSH 
+will have this bug fixed. Or you can add the following to 
+SSH 2.3 <i>sshd2_config</i>.
+
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+<b>Mac hmac-md5</b>
+               </td>
+        </tr>
+</table>
+</blockquote>
+
+<h2><a name= "2.4">2.4 - Why does OpenSSH print: Dispatch protocol error: type 20</a></h2>
+
+<p>
+Problems in interoperation have been seen because older versions of 
+OpenSSH did not support session rekeying. However the commercial SSH 2.3 
+tries to negotiate this feature, and you might experience connection 
+freezes or see the error message &quot;<b>Dispatch protocol error: 
+type 20 </b>&quot;. 
+To solve this problem, either upgrade to a recent OpenSSH release or 
+disable rekeying by adding the following to your commercial SSH 2.3's
+<i>ssh2_config</i> or <i>sshd2_config</i>.
+
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+<b>RekeyIntervalSeconds 0</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<h2><a name= "2.5">2.5 - Old versions of commercial SSH encrypt host keys with IDEA.</a></h2>
+
+<p>
+The old versions of SSH used a patented algorithm to encrypt their 
+<i>/etc/ssh/ssh_host_key</i>. This problem will manifest as 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sshd&amp;sektion=8">sshd(8)</a> 
+not being able to read its host key. To solve this, use the command below 
+to convert your ssh_host_key to use 3DES. 
+<b>NOTE:</b> Use the 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-keygen&amp;sektion=1">ssh-keygen(1)</a> 
+program from the Commercial SSH product, *NOT* OpenSSH for the example 
+below.
+
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+# <b>ssh-keygen -u -f /etc/ssh/ssh_host_key</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<h2><a name= "2.6">2.6 - What are these warning messages about key lengths</a></h2>
+
+<p>
+Commercial SSH's 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh-keygen&amp;sektion=1">ssh-keygen(1)</a> 
+program contained a bug which caused it to occasionally generate Pubkey 
+Authentication (RSA or DSA) keys which had their Most Significant Bit 
+(MSB) unset. Such keys were advertised as being full-length, but are 
+actually, half the time, smaller than advertised.
+
+<p>
+OpenSSH will print warning messages when it encounters such keys. To rid 
+yourself of these message, edit your <i>known_hosts</i> files and replace the 
+incorrect key length (usually "1024") with the correct key length 
+(usually "1023").
+
+<h2><a name= "2.7">2.7 - X11 and/or agent forwarding does not work.</a></h2>
+
+<p>
+Check your <i>ssh_config</i> and <i>sshd_config</i>. The default 
+configuration files disable authentication agent and X11 forwarding. To 
+enable it, put the line below in <i>sshd_config</i>:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+<b>X11Forwarding yes</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+and put the following lines in <i>ssh_config</i>:
+
+<blockquote>
+<table border=0 width="800">
+       <tr>
+               <td nowrap bgcolor="#EEEEEE">
+<b>ForwardAgent yes</b><br>
+<b>ForwardX11 yes</b>
+               </td>
+       </tr>
+</table>
+</blockquote>
+
+<p>
+X11 forwarding requires a working <a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=xauth&amp;sektion=1"
+>xauth(1)</a> binary.  On OpenBSD this is in the <i>xbase</i> file
+set but will probably be different on other platforms.  For OpenSSH
+Portable, xauth must be either found at configure time or specified
+via <b>XAuthLocation</b> in sshd_config(5) and ssh_config(5).
+
+<p>
+Note on agent interoperability: There are two different and
+incompatible agent forwarding mechanisms within the SSH2 protocol.
+OpenSSH has always used an extension of the original SSH1 agent
+requests, however some commercial products use a different, non-free
+agent forwarding protocol.  This means that agent forwarding cannot
+be used between OpenSSH and those products.
+
+<p>
+<b>NOTE:</b> For users of Linux Mandrake 7.2, Mandrake modifies the 
+<i>XAUTHORITY</i> environment variable in <i>/etc/skel/.bashrc</i>, 
+and thus any bash user's home directory. This variable is set by OpenSSH 
+and for either of the above options to work, you need to comment out 
+the line:
+
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+<b># export XAUTHORITY=$HOME/.Xauthority</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<h2><a name= "2.8">2.8 - After upgrading OpenSSH I lost SSH2 support.</a></h2>
+
+<p>
+Between versions changes can be made to <i>sshd_config</i> or 
+<i>ssh_config</i>. You should always check on these changes when upgrading 
+versions of OpenSSH. After OpenSSH Version 2.3.0 you need to add the 
+following to your <i>sshd_config</i>:
+
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+<b>HostKey /etc/ssh_host_dsa_key</b><br>
+<b>HostKey /etc/ssh_host_rsa_key</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<h2><a name= "2.9">2.9 - sftp/scp fails at connection, but ssh is OK.</a></h2>
+
+<p>
+sftp and/or scp may fail at connection time if you have shell 
+initialization (.profile, .bashrc, .cshrc, etc) which produces output 
+for non-interactive sessions. This output confuses the sftp/scp client.  
+You can verify if your shell is doing this by executing:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+<b>ssh yourhost /usr/bin/true</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+If the above command produces any output, then you need to modify your 
+shell initialization.
+
+<h2><a name= "2.10">2.10 - Will you add [foo] to scp?</a></h2>
+
+<p>
+Short Answer: no.
+
+<p>
+Long Answer: scp is not standardized. The closest thing it has to a
+specification is "what rcp does".  Since the same command is used on both ends
+of the connection, adding features or options risks breaking interoperability with other
+implementations.
+
+<p>
+New features are more likely in sftp, since the protocol is standardized
+(well, a <a href="http://www.ietf.org/html.charters/OLD/secsh-charter.html">
+draft standard</a>), extensible, and the client and server are decoupled.
+
+<h2><a name= "2.11">2.11 - How do I use port forwarding?</a></h2>
+
+<p>
+If the remote server is running sshd(8), it may be possible to
+``tunnel'' certain services via ssh.  This may be desirable, for
+example, to encrypt POP or SMTP connections, even though the software
+does not directly support encrypted communications.  Tunnelling uses
+port forwarding to create a connection between the client and server.
+The client software must be able to specify a non-standard port to
+connect to for this to work.
+
+<p>
+The idea is that the user connects to the remote host using ssh,
+and specifies which port on the client's machine should be used to
+forward connections to the remote server.  After that it is possible
+to start the service which is to be encrypted (e.g. fetchmail, irc)
+on the client machine, specifying the same local port passed to
+ssh, and the connection will be tunnelled through ssh.  By default,
+the system running the forward will only accept connections from
+itself.
+
+<p>
+The options most relevant to tunnelling are the -L and -R options,
+which allow the user to forward connections, the -D option, which
+permits dynamic port forwarding, the -g option, which permits other
+hosts to use port forwards, and the -f option, which instructs ssh
+to put itself in the background after authentication.  See the <a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh&amp;sektion=1"
+>ssh(1)</a> man page for further details.
+
+<p>
+This is an example of tunnelling an IRC session from client machine
+``127.0.0.1'' (localhost) to remote server ``server.example.com'':
+
+<blockquote>
+<table border=0 width="800">
+       <tr>
+               <td nowrap bgcolor="#EEEEEE">
+<b>ssh -f -L 1234:server.example.com:6667 server.example.com sleep 10<br>
+irc -c '#users' -p 1234 pinky 127.0.0.1</b>
+       </td>
+       </tr>
+</table>
+</blockquote>
+
+<p>
+This tunnels a connection to IRC server server.example.com, joining
+channel ``#users'', using the nickname ``pinky''.  The local port used
+in this example is 1234.  It does not matter which port is used, as
+long as it's greater than 1023 (remember, only root can open sockets on
+privileged ports) and doesn't conflict with any ports already in use.
+The connection is forwarded to port 6667 on the remote server, since
+that's the standard port for IRC services.
+
+<p>
+The remote command ``sleep 10'' was specified to allow an amount
+of time (10 seconds, in the example) to start the service which is to
+be tunnelled.  If no connections are made within the time specified,
+ssh will exit.  If more time is required, the sleep(1) value can be
+increased appropriately or, alternatively, the example above could
+be added as a function to the user's shell.  See ksh(1) and csh(1)
+for more details about user-defined functions.
+
+<p>
+ssh also has an -N option, convenient for use with port forwarding:
+if -N is specified, it is not necessary to specify a remote command
+(``sleep 10'' in the example above).  However, use of this option
+causes ssh to wait around for ever (as opposed to exiting after a
+remote command has completed), and the user must take care to manually
+kill(1) the process afterwards.
+
+<h2><a name= "2.12">2.12 - My ssh connection freezes or drops out after N minutes of inactivity.</a></h2>
+
+<p>
+This is usually the result of a packet filter or NAT device
+timing out your TCP connection due to inactivity.  You can enable
+<b>ClientAliveInterval</b> in the server's <i><a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config&amp;sektion=5">
+sshd_config</a></i>, or enable <b>ServerAliveInterval</b> in the
+client's <i><a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh_config&amp;sektion=5">
+ssh_config</a></i> (the latter is available in OpenSSH 3.8 and newer).
+
+<p>
+Enabling either option and setting the interval for less than the time
+it takes to time out your session will ensure that the connection is
+kept "fresh" in the device's connection table.
+
+<h2><a name= "2.13">2.13 - How do I use scp to copy a file with a colon in it?</a></h2>
+
+<b><a
+href="http://www.openbsd.org/cgi-bin/man.cgi?query=scp&amp;sektion=1">
+scp</a></b> will interpret the component before the colon to be a remote
+server name and attempt to connect to it.  To prevent this, refer to
+the file by a relative or absolute path, eg:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+$ scp ./source:file sshserver:
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<h2><a name= "2.14">2.14 - Why does OpenSSH report its version to clients?</a></h2>
+
+<p>
+OpenSSH, like most SSH implementations, reports its name and version to clients
+when they connect, e.g.
+</p>
+
+<blockquote>
+SSH-2.0-OpenSSH_3.9
+</blockquote>
+
+<p>
+This information is used by clients and servers to enable protocol 
+compatibility tweaks to work around changed, buggy or missing features in 
+the implementation they are talking to. This protocol feature checking is 
+still required at present because versions with incompatibilities are still
+in wide use.
+</p>
+
+<h2><u><a name= "3.0">3.0 - Portable OpenSSH Questions</a></u></h2>
+
+<h2><a name= "3.1">3.1 - Spurious PAM authentication messages in logfiles.</a></h2>
+
+<p>
+The portable version of OpenSSH will generate spurious authentication 
+failures at every login, similar to:
+
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+&quot;<b>authentication failure; (uid=0) -&gt; root for sshd service</b>&quot;
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+These are generated because OpenSSH first tries to determine whether a 
+user needs authentication to login (e.g. empty password). Unfortunately 
+PAM likes to log all authentication events, this one included.
+
+<p>
+If it annoys you too much, set &quot;<b>PermitEmptyPasswords no</b>&quot; 
+in <i>sshd_config</i>. This will quiet the error message at the expense 
+of disabling logins to accounts with no password set. 
+This is the default if you use the supplied <i>sshd_config</i> file.
+
+<h2><a name= "3.2">3.2 - Empty passwords not allowed with PAM authentication.</a></h2>
+
+<p>
+To enable empty passwords with a version of OpenSSH built with PAM you 
+must add the flag nullok to the end of the password checking module 
+in the <i>/etc/pam.d/sshd</i> file. For example:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+auth required/lib/security/pam_unix.so shadow nodelay nullok
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+This must be done in addition to setting &quot;<b>PermitEmptyPasswords 
+yes</b>&quot; in the <i>sshd_config</i> file. 
+
+<p>
+There is one caveat when using empty passwords with PAM authentication: 
+PAM will allow any password when authenticating an account with an empty 
+password. This breaks the check that 
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sshd&amp;sektion=8">sshd(8)</a> 
+uses to determine whether an account has no password set and grant 
+users access to the account regardless of the policy specified by 
+<b>PermitEmptyPasswords</b>. For this reason, it is recommended that you 
+do not add the <b>nullok</b> directive to your PAM configuration file 
+unless you specifically wish to allow empty passwords.
+
+
+<h2><a name= "3.3">3.3 - ssh(1) takes a long time to connect or log
+in</a></h2>
+
+<p>
+Large delays (more than 10 seconds) are typically caused by a problem with
+name resolution:
+<ul>
+<li>Some versions of glibc (notably glibc 2.1 shipped with Red Hat 6.1)
+can take a long time to resolve "IPv6 or IPv4" addresses from domain
+names. This can be worked around with by specifying <b>AddressFamily
+inet</b> option in <i>ssh_config</i>.</li>
+
+<li>There may be a DNS lookup problem, either at the client or server.
+You can use the <code>nslookup</code> command to check this on both client
+and server by looking up the other end's name and IP address.  In
+addition, on the server look up the name returned by the client's
+IP-name lookup.  You can disable most of the server-side lookups by
+setting <b>UseDNS no</b> in <i>sshd_config</i>.</li>
+</ul>
+
+<p>
+Delays less than 10 seconds can have other causes.
+
+<ul>
+
+<li>OpenSSH releases prior to 3.8 had an <i>moduli</i> file with
+moduli that were just smaller than what sshd would look for, and
+as a result, sshd would end up using moduli significantly larger
+than requested, which resulted in a speed penalty.  Replacing the
+<i>moduli</i> file will resolve this (note that in most cases this
+file will not be replaced during an upgrade and must be replaced
+manually).</li>
+
+<li>OpenSSH releases prior to 3.8 had a flaw in <code>ssh</code> that
+would cause it to request moduli larger than intended (which when
+combined with the above resulted in significant slowdowns).
+Upgrading the client to 3.8 or higher will resolve this issue.</li>
+
+<li>If either the client or server lack a kernel-based random number
+device (eg Solaris &lt; 9, AIX &lt; 5.2, HP-UX &lt; 11.11) and no
+substitute is available (eg <a href=
+"ftp://ftp.ayamura.org/pub/prngd/">prngd</a>) it's possible that
+one of the programs called by <code>ssh-rand-helper</code> to
+generate entropy is hanging.  This can be investigated by running
+it in debug mode:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+/usr/local/libexec/ssh-rand-helper -vvv
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+Any significant delays should be investigated and rectified, or the
+corresponding commands should be removed from <i>ssh_prng_cmds</i>.
+</li>
+
+</ul>
+
+<h3>How slow is "slow"?</h3>
+Under normal conditions, the speed of SSH logins is dependant on
+CPU speed of client and server.  For comparison the following are
+typical connect times for <code>time ssh localhost true</code>
+with a 1024-bit RSA key on otherwise unloaded hosts.  OpenSSH and
+OpenSSL were compiled with gcc 3.3.x.
+
+<p>
+<table>
+<tr><th>CPU</th><th>Time (SSHv1)<a href="#3.3fn1">[1]</a></th>
+       <th>Time (SSHv2)</th></tr>
+<tr><td>170MHz SPARC/sun4m</td><td>0.74 sec</td><td>1.25 sec</td></tr>
+<tr><td>236MHz HPPA/8200<a href="#3.3fn2">[2]</a></td><td>0.44 sec</td>
+       <td>0.79 sec</td></tr>
+<tr><td>375MHz PowerPC/604e</td><td>0.38 sec</td><td>0.51 sec</td></tr>
+<tr><td>933MHz VIA Ezra</td><td>0.34 sec</td><td>0.44 sec</td></tr>
+<tr><td>2.1GHz Athlon XP 2600+</td><td>0.14 sec</td><td>0.22 sec</td></tr>
+</table>
+
+<br>
+
+<a name="3.3fn1">[1]</a> The SSHv1 protocol is faster but is
+cryptographically weaker than SSHv2.<br>
+
+<a name="3.3fn2">[2]</a> At the time of writing, gcc generates
+relatively slow code on HPPA for RSA and Diffie-Hellman operations
+(see <a href= "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7625">gcc
+bug #7625</a> and <a
+href="http://marc.info/?l=openssh-unix-dev&amp;m=102646106016694">
+discussion on openssh-unix-dev</a>).
+
+<h2><a name= "3.4">3.4 - "Can't locate module net-pf-10" messages in log under Linux.</a></h2>
+
+<p>
+The Linux kernel is looking (via modprobe) for protocol family 10 (IPv6). 
+Either load the appropriate kernel module, enter the correct alias in 
+<i>/etc/modules.conf</i> or disable IPv6 in <i>/etc/modules.conf</i>.
+
+
+<p>
+For some silly reason <i>/etc/modules.conf</i> may also be named 
+<i>/etc/conf.modules</i>.
+
+
+<h2><a name= "3.5">3.5 - Password authentication doesn't work (eg on Slackware 7.0 or Red Hat 6.x)</a></h2>
+
+<p>
+If the password is correct password the login is still denied, the
+usual cause is that the system is configured to use MD5-type passwords
+but the
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=crypt&amp;sektion=3"
+>crypt(3)</a> function used by sshd doesn't understand them.
+
+<p>
+Affected accounts will have password strings in <i>/etc/passwd</i>
+or <i>/etc/shadow</i> that start with <b>$1$</b>.
+If password authentication fails for new accounts or accounts with
+recently changed passwords, but works for old accounts, this is the
+likely culprit.
+
+<p>
+The underlying cause is that some versions of OpenSSL have a crypt(3)
+function that does not understand MD5 passwords, and the link order of
+sshd means that OpenSSL's crypt(3) is used instead of the system's.
+OpensSSH's configure attempts to correct for this but is not always
+successful.
+
+<p>
+There are several possible solutions:
+
+<ul>
+<li>
+<p>
+Enable sshd's built-in support for MD5 passwords at build time.
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+./configure --with-md5-passwords [options]
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+This is safe even if you have both types of encryption as sshd will
+select the correct algorithm for each account automatically.
+
+<li>
+<p>
+If your system has a separate libcrypt library (eg Slackware 7) then you
+can manually add -lcrypt to the LIBS list so it's used instead of
+OpenSSL's:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+LIBS=-lcrypt ./configure [options]
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<li>
+<p>
+If your platforms supports PAM, you may configure sshd to use it
+(see <a href= "#3.15" >section 3.15</a>).  This will mean that sshd will
+not verify passwords itself but will defer to the configured PAM modules.
+</ul>
+
+<h2><a name= "3.6">3.6 - Configure or sshd(8) complain about lack of RSA or DSA support</a></h2>
+
+<p>
+Ensure that your OpenSSL libraries have been built to include RSA or DSA 
+support either internally or through RSAref.
+
+
+<h2><a name= "3.7">3.7 - "scp: command not found" errors</a></h2>
+
+<p>
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=scp&amp;sektion=1">scp(1)</a> 
+must be in the default PATH on both the client and the server. You may 
+need to use the <b>--with-default-path</b> option to specify a custom 
+path to search on the server. This option replaces the default path, 
+so you need to specify all the current directories on your path as well 
+as where you have installed scp. For example:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+$ <b>./configure --with-default-path=/bin:/usr/bin:/usr/local/bin:/path/to/scp</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+Note that configuration by the server's admin will take precedence over the
+setting of <b>--with-default-path</b>.  This includes resetting PATH in
+<i>/etc/profile</i>, PATH in <i>/etc/environment</i> on AIX, or (for 3.7p1 and
+above) setting PATH or SUPATH in <i>/etc/default/login</i> on Solaris or
+Reliant Unix.
+
+<h2><a name= "3.8">3.8 - Unable to read passphrase</a></h2>
+
+<p>
+Some operating systems set <i>/dev/tty</i> with incorrect modes, causing 
+the reading of passwords to fail with the following error:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+You have no controlling tty.  Cannot read passphrase.
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+The solution to this is to reset the permissions on <i>/dev/tty</i> 
+to mode 0666 and report the error as a bug to your OS vendor. 
+
+
+<h2><a name= "3.9">3.9 - 'configure' missing or make fails</a></h2>
+
+<p>
+If there is no 'configure' file in the tar.gz file that you downloaded 
+or make fails with "missing separator" errors, you have probably 
+downloaded the OpenBSD distribution of OpenSSH and are attempting to 
+compile it on another platform. Please refer to the information on the 
+<a href="http://www.openssh.org/portable.html">portable version</a>.
+
+
+<h2><a name= "3.10">3.10 - Hangs when exiting ssh</a></h2>
+
+<p>
+OpenSSH may hang when exiting.  This can occur when there is an active 
+background process.  This is known to occur on Linux and HP-UX.  
+The problem can be verified by doing the following:
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+$ <b>sleep 20 &amp; exit</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+Try to use this instead:
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+$ <b>sleep 20 &lt; /dev/null &gt; /dev/null 2&gt;&amp;1 &amp;</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+<p>
+A work around for bash users is to place <b>"shopt -s huponexit"</b> 
+in either /etc/bashrc  or ~/.bashrc.  Otherwise, consult your shell's 
+man page for an option to enable it to send a HUP signal to active 
+jobs when exiting.  See <a
+href="http://bugzilla.mindrot.org/show_bug.cgi?id=52">bug #52</a>
+for other workarounds.
+
+<h2><a name= "3.11">3.11 - Why does ssh hang on exit?</a></h2>
+
+<p>
+When executing
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+$ <b>ssh host command</b>
+                </td>
+        </tr>
+</table>
+</blockquote>
+ssh <b>needs</b> to hang, because it needs to wait:
+<ul>
+<li>
+until it can be sure that <code>command</code> does not need
+more input.
+<li>
+until it can be sure that <code>command</code> does not produce
+more output. 
+<li>
+until <code>command</code> exits because sshd needs to tell
+the exit status from <code>command</code> to ssh.
+</ul>
+<p>
+
+<h2><a name= "3.12">3.12 - I upgraded to OpenSSH 3.1 and X11
+forwarding stopped working.</a></h2>
+
+Starting with OpenSSH 3.1, the sshd x11 forwarding server listens on
+localhost by default; see the sshd <b>X11UseLocalhost</b> option to
+revert to prior behaviour if your older X11 clients do not function
+with this configuration.<p>
+
+In general, X11 clients using X11 R6 should work with the default
+setting.  Some vendors, including HP, ship X11 clients with R6
+and R5 libs, so some clients will work, and others will not work.
+This is true for HP-UX 11.X.<p>
+
+<h2><a name= "3.13">3.13 - I upgraded to OpenSSH 3.8 and some
+X11 programs stopped working.</a></h2>
+
+<p>
+As documented in the <a href="http://www.openssh.org/txt/release-3.8">3.8 release notes</a>,
+<code>ssh</code> will now use untrusted X11 cookies by 
+default.  The previous behaviour can be restored by setting
+<b>ForwardX11Trusted yes</b> in <i>ssh_config</i>.
+
+<p>
+Possible symptoms include:<br>
+<code>BadWindow (invalid Window parameter)<br>
+BadAccess (attempt to access private resource denied)<br>
+X Error of failed request:  BadAtom (invalid Atom parameter)<br>
+Major opcode of failed request:  20 (X_GetProperty)<br></code>
+
+<h2><a name= "3.14">3.14 - I copied my public key to authorized_keys
+but public-key authentication still doesn't work.</a></h2>
+
+<p>
+Typically this is caused by the file permissions on $HOME, $HOME/.ssh or
+$HOME/.ssh/authorized_keys being more permissive than sshd allows by default.
+
+<p>
+In this case, it can be solved by executing the following on the server.
+<blockquote>
+<table border=0 width="800">
+<tr>
+  <td nowrap bgcolor="#EEEEEE">
+$ <b>chmod go-w $HOME $HOME/.ssh</b><br>
+$ <b>chmod 600 $HOME/.ssh/authorized_keys</b>
+$ <b>chown `whoami` $HOME/.ssh/authorized_keys</b><br>
+  </td>
+</tr>
+</table>
+</blockquote>
+
+<p>
+If this is not possible for some reason, an alternative is to set
+<b>StrictModes no</b> in <i>sshd_config</i>, however this is not
+recommended.
+
+<h2><a name= "3.15">3.15 - OpenSSH versions and PAM behaviour.</a></h2>
+
+Portable OpenSSH has a configure-time option to enable sshd's use of the
+<a href="http://www.opengroup.org/onlinepubs/008329799/">PAM</a>
+(Pluggable Authentication Modules) interface.
+
+<blockquote>
+<table border=0 width="800">
+        <tr>
+                <td nowrap bgcolor="#EEEEEE">
+./configure --with-pam [options]
+                </td>
+        </tr>
+</table>
+</blockquote>
+
+To use PAM at all, this option must be provided at build time.
+The run-time behaviour when PAM is built in varies with the version of
+Portable OpenSSH, and on later versions it must also be enabled by setting
+<b>UsePAM</b> to <b>yes</b> in <i>sshd_config</i>.
+
+<p>
+The behaviour of the relevant authentications options when PAM support is built
+in is summarised by the following table.
+
+<p>
+<table border="1">
+  <tr> <th>Version</th> <th>UsePAM</th> <th>PasswordAuthentication</th> <th>ChallengeResponseAuthentication</th> </tr>
+  <tr>
+    <td>&lt;=3.6.1p2</td>
+    <td>Not applicable</td>
+    <td>Uses PAM</td>
+    <td>Uses PAM if <b>PAMAuthenticationViaKbdInt</b> is enabled</td>
+  </tr>
+  <tr>
+    <td>3.7p1 - 3.7.1p1</td>
+    <td>Defaults to <b>yes</b></td>
+    <td>Does not use PAM</td>
+    <td>Uses PAM if <b>UsePAM</b> is enabled</td>
+  </tr>
+  <tr>
+    <td>3.7.1p2 - 3.8.1p1</td>
+    <td>Defaults to <b>no</b></td>
+    <td>Does not use PAM <a href="#3.15fn1">[1]</a></td>
+    <td>Uses PAM if <b>UsePAM</b> is enabled</td>
+  </tr>
+  <tr>
+    <td>3.9p1</td>
+    <td>Defaults to <b>no</b></td>
+    <td>Uses PAM if <b>UsePAM</b> is enabled</td>
+    <td>Uses PAM if <b>UsePAM</b> is enabled</td>
+  </tr>
+</table>
+<p>
+
+<a name= "3.15fn1">[1]</a> Some vendors, notably Redhat/Fedora, have
+backported the PasswordAuthentication from 3.9p1 to their 3.8x based
+packages.  If you're using a vendor-supplied package then consult their
+documentation.
+
+<p>
+OpenSSH Portable's PAM interface still has problems with a few modules,
+however we hope that this number will reduce in the future.  As at the
+3.9p1 release, the known problems are:
+
+<ul>
+  <li>Modules relying on module-private data (eg pam_dhkeys, pam_krb5, AFS)
+  may fail to correctly establish credentials (bug <a
+  href="http://bugzilla.mindrot.org/show_bug.cgi?id=688">#688</a>) when
+  authenticating via <b>ChallengeResponseAuthentication</b>.
+  <b>PasswordAuthentication</b> with 3.9p1 and above should work.
+</ul>
+
+You can also check <a
+href="http://bugzilla.mindrot.org/buglist.cgi?product=Portable+OpenSSH&amp;bug_status=RESOLVED&amp;bug_status=NEW&amp;bug_status=ACCEPTED&amp;component=PAM+support"
+>bugzilla for current PAM issues</a>.
+
+<h2><a name= "3.16">3.16 - Why doesn't "w" or "who" on AIX 5.x show users
+logged in via ssh?</a></h2>
+
+Between AIX 4.3.3 and AIX 5.x, the format of the wtmp struct changed.  This
+means that sshd binaries built on AIX 4.x will not correctly write wtmp
+entries when run on AIX 5.x.  This can be fixed by simply recompiling 
+sshd on an AIX 5.x system and using that.
+
+<hr>
+<a href="http://www.openssh.org/index.html"><img height=24 width=24 src="back.gif" border=0 alt=OpenSSH></a>
+<a href="mailto:www@openbsd.org">www@openbsd.org</a>
+<br>
+<small>$OpenBSD: faq.html,v 1.112 2010/09/15 02:41:42 nick Exp $</small>
+
+</body>
+</html>
diff --git a/debian/gnome-ssh-askpass.1 b/debian/gnome-ssh-askpass.1
new file mode 100644 (file)
index 0000000..b74c410
--- /dev/null
@@ -0,0 +1,51 @@
+.TH GNOME-SSH-ASKPASS 1
+.SH NAME
+gnome\-ssh\-askpass \- prompts a user for a passphrase using GNOME
+.SH SYNOPSIS
+.B gnome\-ssh\-askpass
+.SH DESCRIPTION
+.B gnome\-ssh\-askpass
+is a GNOME-based passphrase dialog for use with OpenSSH.
+It is intended to be called by the
+.BR ssh\-add (1)
+program and not invoked directly.
+It allows
+.BR ssh\-add (1)
+to obtain a passphrase from a user, even if not connected to a terminal
+(assuming that an X display is available).
+This happens automatically in the case where
+.B ssh\-add
+is invoked from one's
+.B ~/.xsession
+or as one of the GNOME startup programs, for example.
+.PP
+In order to be called automatically by
+.BR ssh\-add ,
+.B gnome\-ssh\-askpass
+should be installed as
+.IR /usr/bin/ssh\-askpass .
+.SH "ENVIRONMENT VARIABLES"
+The following environment variables are recognized:
+.TP
+.I GNOME_SSH_ASKPASS_GRAB_SERVER
+Causes
+.B gnome\-ssh\-askpass
+to grab the X server before asking for a passphrase.
+.TP
+.I GNOME_SSH_ASKPASS_GRAB_POINTER
+Causes
+.B gnome\-ssh\-askpass
+to grab the mouse pointer using
+.IR gdk_pointer_grab ()
+before asking for a passphrase.
+.PP
+Regardless of whether either of these environment variables is set,
+.B gnome\-ssh\-askpass
+will grab the keyboard using
+.IR gdk_keyboard_grab ().
+.SH AUTHOR
+This manual page was written by Colin Watson <cjwatson@debian.org>
+for the Debian system (but may be used by others).
+It was based on that for
+.B x11\-ssh\-askpass
+by Philip Hands.
diff --git a/debian/openssh-client-udeb.dirs b/debian/openssh-client-udeb.dirs
new file mode 100644 (file)
index 0000000..e772481
--- /dev/null
@@ -0,0 +1 @@
+usr/bin
diff --git a/debian/openssh-client-udeb.install b/debian/openssh-client-udeb.install
new file mode 100644 (file)
index 0000000..b3891f0
--- /dev/null
@@ -0,0 +1,3 @@
+scp usr/bin
+sftp usr/bin
+ssh usr/bin
diff --git a/debian/openssh-client.config b/debian/openssh-client.config
new file mode 100644 (file)
index 0000000..736e464
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+action=$1
+version=$2
+
+# Source debconf library.
+. /usr/share/debconf/confmodule
+db_version 2.0
+
+if [ -d /etc/ssh-nonfree ] && [ ! -d /etc/ssh ]; then
+  version=1.2.27
+  cp -a /etc/ssh-nonfree /etc/ssh
+fi
+
+# Was ssh-keysign's setuid bit turned off using the obsolete debconf
+# question? If so, turn this into a statoverride. (Ugh.)
+if dpkg --compare-versions "$2" lt 1:4.1p1-2 && \
+    db_get ssh/SUID_client && [ "$RET" = false ] &&
+    [ -x /usr/sbin/dpkg-statoverride ] && \
+    ! dpkg-statoverride --list /usr/lib/ssh-keysign && \
+    ! dpkg-statoverride --list /usr/lib/openssh/ssh-keysign; then
+       dpkg-statoverride --update --add root root 0755 \
+               /usr/lib/openssh/ssh-keysign
+fi
+
+exit 0
diff --git a/debian/openssh-client.dirs b/debian/openssh-client.dirs
new file mode 100644 (file)
index 0000000..1da8fba
--- /dev/null
@@ -0,0 +1 @@
+usr/share/lintian/overrides
diff --git a/debian/openssh-client.docs b/debian/openssh-client.docs
new file mode 100644 (file)
index 0000000..00fd691
--- /dev/null
@@ -0,0 +1,7 @@
+ChangeLog.gssapi
+OVERVIEW
+README
+README.dns
+README.tun
+debian/faq.html
+debian/README.compromised-keys
diff --git a/debian/openssh-client.install b/debian/openssh-client.install
new file mode 100644 (file)
index 0000000..fd9e8fe
--- /dev/null
@@ -0,0 +1,29 @@
+etc/ssh/moduli
+etc/ssh/ssh_config
+usr/bin/scp
+usr/bin/sftp
+usr/bin/slogin
+usr/bin/ssh
+usr/bin/ssh-add
+usr/bin/ssh-agent
+usr/bin/ssh-keygen
+usr/bin/ssh-keyscan
+usr/bin/ssh-vulnkey
+usr/lib/openssh/ssh-keysign
+usr/lib/openssh/ssh-pkcs11-helper
+usr/share/man/man1/scp.1
+usr/share/man/man1/sftp.1
+usr/share/man/man1/slogin.1
+usr/share/man/man1/ssh-add.1
+usr/share/man/man1/ssh-agent.1
+usr/share/man/man1/ssh-keygen.1
+usr/share/man/man1/ssh-keyscan.1
+usr/share/man/man1/ssh-vulnkey.1
+usr/share/man/man1/ssh.1
+usr/share/man/man5/moduli.5
+usr/share/man/man5/ssh_config.5
+usr/share/man/man8/ssh-keysign.8
+usr/share/man/man8/ssh-pkcs11-helper.8
+
+contrib/ssh-copy-id usr/bin
+debian/ssh-argv0 usr/bin
diff --git a/debian/openssh-client.lintian-overrides b/debian/openssh-client.lintian-overrides
new file mode 100644 (file)
index 0000000..8c4bd17
--- /dev/null
@@ -0,0 +1,2 @@
+openssh-client: setuid-binary usr/lib/openssh/ssh-keysign 4755 root/root
+openssh-client: no-debconf-templates
diff --git a/debian/openssh-client.manpages b/debian/openssh-client.manpages
new file mode 100644 (file)
index 0000000..690bd8a
--- /dev/null
@@ -0,0 +1,2 @@
+contrib/ssh-copy-id.1
+debian/ssh-argv0.1
diff --git a/debian/openssh-client.postinst b/debian/openssh-client.postinst
new file mode 100644 (file)
index 0000000..cff282d
--- /dev/null
@@ -0,0 +1,115 @@
+#!/bin/sh -e
+
+action="$1"
+oldversion="$2"
+
+. /usr/share/debconf/confmodule
+db_version 2.0
+
+umask 022
+
+if [ "$action" != configure ]
+  then
+  exit 0
+fi
+
+
+fix_rsh_diversion() {
+# get rid of mistaken rsh diversion (circa 1.2.27-1)
+
+       if [ -L /usr/bin/rsh ] &&
+               dpkg-divert --list '/usr/bin/rsh.real/rsh' | grep -q ' ssh$' ; then
+               for cmd in rlogin  rsh rcp ; do
+                       [ -L /usr/bin/$cmd ] && rm /usr/bin/$cmd
+                       dpkg-divert --package ssh --remove --rename \
+                               --divert /usr/bin/rsh.real/$cmd /usr/bin/$cmd
+
+                       [ -L /usr/man/man1/$cmd.1.gz ] && rm /usr/man/man1/$$cmd.1.gz
+                       dpkg-divert --package ssh --remove --rename \
+                               --divert /usr/man/man1/$cmd.real.1.gz /usr/man/man1/$cmd.1.gz
+               done
+
+               rmdir /usr/bin/rsh.real
+       fi
+}
+
+create_alternatives() {
+# Create alternatives for the various r* tools.
+# Make sure we don't change existing alternatives that a user might have
+# changed, but clean up after some old alternatives that mistakenly pointed
+# rlogin and rcp to ssh.
+       update-alternatives --quiet --remove rlogin /usr/bin/ssh
+       update-alternatives --quiet --remove rcp /usr/bin/ssh
+       for cmd in rsh rlogin rcp; do
+               scmd="s${cmd#r}"
+               if ! update-alternatives --display "$cmd" 2>/dev/null | \
+                               grep -q "$scmd"; then
+                       update-alternatives --quiet --install "/usr/bin/$cmd" "$cmd" "/usr/bin/$scmd" 20 \
+                               --slave "/usr/share/man/man1/$cmd.1.gz" "$cmd.1.gz" "/usr/share/man/man1/$scmd.1.gz"
+               fi
+       done
+}
+
+set_ssh_permissions() {
+       if dpkg --compare-versions "$oldversion" lt-nl 1:3.4p1-1 ; then
+           if [ -x /usr/sbin/dpkg-statoverride ] ; then
+               if dpkg-statoverride --list /usr/bin/ssh >/dev/null; then
+                   dpkg-statoverride --remove /usr/bin/ssh >/dev/null
+               fi 
+           fi
+       fi
+
+       # libexecdir changed, so migrate old statoverrides.
+       if [ -x /usr/sbin/dpkg-statoverride ] &&
+           override="$(dpkg-statoverride --list /usr/lib/ssh-keysign)"; then
+               override_user="${override%% *}"
+               override="${override#* }"
+               override_group="${override%% *}"
+               override="${override#* }"
+               override_mode="${override%% *}"
+               if dpkg-statoverride --update --add \
+                   "$override_user" "$override_group" "$override_mode" \
+                   /usr/lib/openssh/ssh-keysign; then
+                       dpkg-statoverride --remove /usr/lib/ssh-keysign || true
+               fi
+       fi
+}
+
+fix_ssh_group() {
+       # Try to remove non-system group mistakenly created by 1:3.5p1-1.
+       # set_ssh_agent_permissions() below will re-create it properly.
+       if getent group ssh >/dev/null; then
+               delgroup --quiet ssh || true
+       fi
+}
+
+set_ssh_agent_permissions() {
+       if ! getent group ssh >/dev/null; then
+               addgroup --system --quiet ssh
+       fi
+       if ! [ -x /usr/sbin/dpkg-statoverride ] || \
+           ! dpkg-statoverride --list /usr/bin/ssh-agent >/dev/null ; then
+               chgrp ssh /usr/bin/ssh-agent
+               chmod 2755 /usr/bin/ssh-agent
+       fi
+}
+
+commit_transfer_conffile () {
+       CONFFILE="$1"
+       if [ -e "$CONFFILE.moved-by-preinst" ]; then
+               rm -f "$CONFFILE.moved-by-preinst"
+       fi
+}
+
+
+fix_rsh_diversion
+create_alternatives
+set_ssh_permissions
+if [ "$2" = "1:3.5p1-1" ]; then
+    fix_ssh_group
+fi
+set_ssh_agent_permissions
+commit_transfer_conffile /etc/ssh/moduli
+commit_transfer_conffile /etc/ssh/ssh_config
+
+exit 0
diff --git a/debian/openssh-client.postrm b/debian/openssh-client.postrm
new file mode 100644 (file)
index 0000000..eb6fde0
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+
+#DEBHELPER#
+
+abort_transfer_conffile () {
+       CONFFILE="$1"
+       if [ -e "$CONFFILE.moved-by-preinst" ]; then
+               echo >&2 "Aborting ownership transfer of conffile $CONFFILE ..."
+               mv -f "$CONFFILE.moved-by-preinst" "$CONFFILE"
+               return 0
+       fi
+}
+
+case $1 in
+       abort-install|abort-upgrade)
+               abort_transfer_conffile /etc/ssh/moduli
+               abort_transfer_conffile /etc/ssh/ssh_config
+               ;;
+       purge)
+               # Remove all non-conffiles that ssh might create, so that we
+               # can smoothly remove /etc/ssh if and only if the user
+               # hasn't dropped some other files in there. Conffiles have
+               # already been removed at this point.
+               rm -f /etc/ssh/moduli /etc/ssh/primes
+               rm -f /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2
+               rmdir --ignore-fail-on-non-empty /etc/ssh
+
+               if which delgroup; then
+                       delgroup --quiet ssh > /dev/null || true
+               fi
+               ;;
+esac
+
+exit 0
diff --git a/debian/openssh-client.preinst b/debian/openssh-client.preinst
new file mode 100644 (file)
index 0000000..0b29c05
--- /dev/null
@@ -0,0 +1,49 @@
+#! /bin/sh -e
+
+ETC_SSH_MODULI=@ETC_SSH_MODULI@
+
+ETC_SSH_SSH_CONFIG=@ETC_SSH_SSH_CONFIG@
+
+action="$1"
+version="$2"
+
+prepare_transfer_conffile () {
+       CONFFILE="$1"
+       TEXT="$2"
+       MODE="$3"
+       [ "$CONFFILES" ] || return 0
+       [ -e "$CONFFILE" ] || return 0
+
+       md5sum="$(md5sum "$CONFFILE" |sed -e 's/ .*//')"
+       old_md5sum="$(echo "$CONFFILES" | awk '$1 == "'"$CONFFILE"'" { print $2 }')"
+       if [ "$md5sum" = "$old_md5sum" ]; then
+               echo >&2 "Transferring ownership of conffile $CONFFILE ..."
+               # We have to write out the desired new text of the conffile,
+               # which is tricky in the preinst, hence the nasty way we
+               # have to hardcode the text here. Fortunately, this is only
+               # necessary with sarge's dpkg and older.
+               if echo "$TEXT" | head -n1 | grep -q '^@.*@$'; then
+                       echo >&2 'Unsubstituted conffile text! Please report this bug.'
+                       exit 1
+               fi
+               printf '%s' "$TEXT" >"$CONFFILE.dpkg-new"
+               chmod "$MODE" "$CONFFILE.dpkg-new"
+               mv -f "$CONFFILE" "$CONFFILE.moved-by-preinst"
+               mv -f "$CONFFILE.dpkg-new" "$CONFFILE"
+               return 0
+       fi
+}
+
+case $action in
+       install|upgrade)
+               if dpkg --compare-versions "$version" lt 0; then
+                       CONFFILES="$(dpkg-query -W -f '${Conffiles}\n' ssh 2>/dev/null | sed 's/^ *//')"
+                       prepare_transfer_conffile /etc/ssh/moduli "$ETC_SSH_MODULI" 0644
+                       prepare_transfer_conffile /etc/ssh/ssh_config "$ETC_SSH_SSH_CONFIG" 0644
+               fi
+               ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/openssh-client.prerm b/debian/openssh-client.prerm
new file mode 100644 (file)
index 0000000..2d631cb
--- /dev/null
@@ -0,0 +1,39 @@
+#! /bin/sh
+# prerm script for ssh
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <prerm> `remove'
+#        * <old-prerm> `upgrade' <new-version>
+#        * <new-prerm> `failed-upgrade' <old-version>
+#        * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+#        * <deconfigured's-prerm> `deconfigure' `in-favour'
+#          <package-being-installed> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see /usr/share/doc/packaging-manual/
+
+case "$1" in
+    remove|deconfigure)
+       update-alternatives --quiet --remove rsh /usr/bin/ssh
+       update-alternatives --quiet --remove rlogin /usr/bin/slogin
+       update-alternatives --quiet --remove rcp /usr/bin/scp
+       ;;
+    upgrade)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 0
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/openssh-server-udeb.dirs b/debian/openssh-server-udeb.dirs
new file mode 100644 (file)
index 0000000..f2b0bd9
--- /dev/null
@@ -0,0 +1,3 @@
+usr/bin
+usr/sbin
+var/run/sshd
diff --git a/debian/openssh-server-udeb.install b/debian/openssh-server-udeb.install
new file mode 100644 (file)
index 0000000..05ccbf7
--- /dev/null
@@ -0,0 +1,2 @@
+sshd usr/sbin
+ssh-keygen usr/bin
diff --git a/debian/openssh-server.config b/debian/openssh-server.config
new file mode 100644 (file)
index 0000000..2a01aa8
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh 
+
+action=$1
+version=$2
+
+# Source debconf library.
+. /usr/share/debconf/confmodule
+db_version 2.0
+
+
+get_config_option() {
+       option="$1"
+
+       [ -f /etc/ssh/sshd_config ] || return
+
+       # TODO: actually only one '=' allowed after option
+       perl -ne 'print if s/^[[:space:]]*'"$option"'[[:space:]=]+//i' \
+          /etc/ssh/sshd_config 2>/dev/null
+}
+
+
+if [ -e /etc/init.d/ssh ] && ! grep -q pidfile /etc/init.d/ssh
+then
+  db_fset ssh/use_old_init_script seen false
+  db_input medium ssh/use_old_init_script || true
+  db_go
+
+  db_get ssh/use_old_init_script
+  [ "$RET" = "false" ] && exit 0
+else
+  db_set ssh/use_old_init_script true
+  db_fset ssh/use_old_init_script seen true
+fi
+
+if [ -e /etc/ssh/sshd_config ]
+then
+    # An empty version means we're upgrading from before the package split,
+    # so check.
+    if dpkg --compare-versions "$version" lt 1:3.8.1p1-11
+    then
+       passwordauth="$(get_config_option PasswordAuthentication)"
+       crauth="$(get_config_option ChallengeResponseAuthentication)"
+       if [ "$passwordauth" = no ] && \
+          ([ -z "$crauth" ] || [ "$crauth" = yes ])
+       then
+           db_input critical ssh/disable_cr_auth || true
+       fi
+    fi
+fi 
+
+key=/etc/ssh/ssh_host_key
+export key
+if [ -n "$version" ] && [ -f $key ] && [ ! -x /usr/bin/ssh-keygen ] &&
+     dpkg --compare-versions "$version" lt 1.2.28
+then
+  # make sure that keys get updated to get rid of IDEA; preinst
+  # actually does the work, but if the old ssh-keygen is not found,
+  # it can't do that -- thus, we tell the user that he must create
+  # a new host key.
+  printf '\0\0' | 3<&0 sh -c \
+      'dd if=$key bs=1 skip=32 count=2 2>/dev/null | cmp -s - /dev/fd/3' || {
+    # this means that bytes 32&33 of the key were not both zero, in which
+    # case the key is encrypted, which we need to fix
+    db_input high ssh/encrypted_host_key_but_no_keygen || true
+  }
+fi
+
+
+db_go
+
+exit 0
diff --git a/debian/openssh-server.dirs b/debian/openssh-server.dirs
new file mode 100644 (file)
index 0000000..b008fbf
--- /dev/null
@@ -0,0 +1,9 @@
+etc/init.d
+etc/default
+etc/network/if-up.d
+etc/ufw/applications.d
+usr/lib/openssh
+usr/sbin
+usr/share/lintian/overrides
+usr/share/man/man5
+usr/share/man/man8
diff --git a/debian/openssh-server.examples b/debian/openssh-server.examples
new file mode 100644 (file)
index 0000000..0d0e55a
--- /dev/null
@@ -0,0 +1 @@
+sshd_config
diff --git a/debian/openssh-server.if-up b/debian/openssh-server.if-up
new file mode 100644 (file)
index 0000000..ce5d4dd
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# Reload the OpenSSH server when an interface comes up, to allow it to start
+# listening on new addresses.
+
+set -e
+
+# Don't bother to restart sshd when lo is configured.
+if [ "$IFACE" = lo ]; then
+       exit 0
+fi
+
+# Only run from ifup.
+if [ "$MODE" != start ]; then
+       exit 0
+fi
+
+# OpenSSH only cares about inet and inet6. Get ye gone, strange people
+# still using ipx.
+if [ "$ADDRFAM" != inet ] && [ "$ADDRFAM" != inet6 ]; then
+       exit 0
+fi
+
+# Is /usr mounted?
+if [ ! -e /usr/sbin/sshd ]; then
+       exit 0
+fi
+
+if [ ! -f /var/run/sshd.pid ] || \
+   [ "$(ps -p "$(cat /var/run/sshd.pid)" -o comm=)" != sshd ]; then
+       exit 0
+fi
+
+# We'd like to use 'reload' here, but it has some problems; see #502444.
+if [ -x /usr/sbin/invoke-rc.d ]; then
+       invoke-rc.d ssh restart >/dev/null 2>&1 || true
+else
+       /etc/init.d/ssh restart >/dev/null 2>&1 || true
+fi
+
+exit 0
diff --git a/debian/openssh-server.install b/debian/openssh-server.install
new file mode 100644 (file)
index 0000000..8e04c41
--- /dev/null
@@ -0,0 +1,6 @@
+usr/lib/openssh/sftp-server
+usr/sbin/sshd
+usr/share/man/man5/authorized_keys.5
+usr/share/man/man5/sshd_config.5
+usr/share/man/man8/sftp-server.8
+usr/share/man/man8/sshd.8
diff --git a/debian/openssh-server.links b/debian/openssh-server.links
new file mode 100644 (file)
index 0000000..2d98b1d
--- /dev/null
@@ -0,0 +1 @@
+usr/lib/openssh/sftp-server usr/lib/sftp-server
diff --git a/debian/openssh-server.lintian-overrides b/debian/openssh-server.lintian-overrides
new file mode 100644 (file)
index 0000000..17d912c
--- /dev/null
@@ -0,0 +1 @@
+openssh-server: package-contains-empty-directory usr/share/doc/openssh-client/
diff --git a/debian/openssh-server.postinst b/debian/openssh-server.postinst
new file mode 100644 (file)
index 0000000..cf3fa68
--- /dev/null
@@ -0,0 +1,482 @@
+#!/bin/sh -e
+
+action="$1"
+oldversion="$2"
+
+. /usr/share/debconf/confmodule
+db_version 2.0
+
+umask 022
+
+if [ "$action" != configure ]
+  then
+  exit 0
+fi
+
+
+fix_doc_symlink() {
+       if [ ! -L /usr/share/doc/openssh-server ] && \
+          dpkg --compare-versions "$oldversion" lt-nl 1:4.1p1-5; then
+               rm -rf /usr/share/doc/openssh-server
+               ln -s openssh-client /usr/share/doc/openssh-server
+       fi
+}
+
+
+get_config_option() {
+       option="$1"
+
+       [ -f /etc/ssh/sshd_config ] || return
+
+       # TODO: actually only one '=' allowed after option
+       perl -lne 's/\s+/ /g; print if s/^\s*'"$option"'[[:space:]=]+//i' \
+          /etc/ssh/sshd_config
+}
+
+
+set_config_option() {
+       option="$1"
+       value="$2"
+
+       perl -le '
+               $option = $ARGV[0]; $value = $ARGV[1]; $done = 0;
+               while (<STDIN>) {
+                       chomp;
+                       (my $match = $_) =~ s/\s+/ /g;
+                       if ($match =~ s/^\s*\Q$option\E\s+.*/$option $value/) {
+                               $_ = $match;
+                               $done = 1;
+                       }
+                       print;
+               }
+               print "$option $value" unless $done;' \
+               "$option" "$value" \
+               < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
+       chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
+       chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
+       mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
+}
+
+
+disable_config_option() {
+       option="$1"
+
+       value="$(get_config_option "$option")"
+       [ "$value" ] || return 0
+
+       perl -le '
+               $option = $ARGV[0];
+               while (<STDIN>) {
+                       chomp;
+                       (my $match = $_) =~ s/\s+/ /g;
+                       # TODO: actually only one "=" allowed after option
+                       if ($match =~ s/^(\s*\Q$option\E[[:space:]=]+.*)/#$1/i) {
+                               $_ = $match;
+                       }
+                       print;
+               }' \
+               "$option" \
+               < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
+       chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
+       chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
+       mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
+}
+
+
+rename_config_option() {
+       oldoption="$1"
+       newoption="$2"
+
+       value="$(get_config_option "$oldoption")"
+       [ "$value" ] || return 0
+
+       perl -le '
+               $oldoption = $ARGV[0]; $newoption = $ARGV[1];
+               while (<STDIN>) {
+                       chomp;
+                       (my $match = $_) =~ s/\s+/ /g;
+                       # TODO: actually only one "=" allowed after option
+                       if ($match =~ s/^(\s*)\Q$oldoption\E([[:space:]=]+)/$1$newoption$2/i) {
+                               $_ = $match;
+                       }
+                       print;
+               }' \
+               "$oldoption" "$newoption" \
+               < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
+       chown --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
+       chmod --reference /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-new
+       mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
+}
+
+
+remove_obsolete_gssapi() {
+       disable_config_option GSSAPINoMICAuthentication
+       disable_config_option GSSUseSessionCCache
+       disable_config_option GSSAPIUseSessionCredCache
+}
+
+
+host_keys_required() {
+       hostkeys="$(get_config_option HostKey)"
+       if [ "$hostkeys" ]; then
+               echo "$hostkeys"
+       else
+               # No HostKey directives at all, so the server picks some
+               # defaults depending on the setting of Protocol.
+               protocol="$(get_config_option Protocol)"
+               [ "$protocol" ] || protocol=1,2
+               if echo "$protocol" | grep 1 >/dev/null; then
+                       echo /etc/ssh/ssh_host_key
+               fi
+               if echo "$protocol" | grep 2 >/dev/null; then
+                       echo /etc/ssh/ssh_host_rsa_key
+                       echo /etc/ssh/ssh_host_dsa_key
+                       echo /etc/ssh/ssh_host_ecdsa_key
+               fi
+       fi
+}
+
+
+create_key() {
+       msg="$1"
+       shift
+       hostkeys="$1"
+       shift
+       file="$1"
+       shift
+
+       if echo "$hostkeys" | grep -x "$file" >/dev/null && \
+          [ ! -f "$file" ] ; then
+               echo -n $msg
+               ssh-keygen -q -f "$file" -N '' "$@"
+               echo
+               if which restorecon >/dev/null 2>&1; then
+                       restorecon "$file.pub"
+               fi
+       fi
+}
+
+
+create_keys() {
+       hostkeys="$(host_keys_required)"
+
+       create_key "Creating SSH1 key; this may take some time ..." \
+               "$hostkeys" /etc/ssh/ssh_host_key -t rsa1
+
+       create_key "Creating SSH2 RSA key; this may take some time ..." \
+               "$hostkeys" /etc/ssh/ssh_host_rsa_key -t rsa
+       create_key "Creating SSH2 DSA key; this may take some time ..." \
+               "$hostkeys" /etc/ssh/ssh_host_dsa_key -t dsa
+       create_key "Creating SSH2 ECDSA key; this may take some time ..." \
+               "$hostkeys" /etc/ssh/ssh_host_ecdsa_key -t ecdsa
+}
+
+
+vulnerable_host_keys() {
+       # If the admin has explicitly put the vulnerable keys back, we
+       # assume they can look after themselves.
+       db_fget ssh/vulnerable_host_keys seen
+       if [ "$RET" = true ]; then
+               return 0
+       fi
+
+       hostkeys="$(host_keys_required)"
+       vulnerable=
+       for hostkey in $hostkeys; do
+               [ -f "$hostkey" ] || continue
+               if ssh-vulnkey -q "$hostkey"; then
+                       vulnerable="${vulnerable:+$vulnerable }$hostkey"
+               fi
+       done
+       if [ "$vulnerable" ]; then
+               db_subst ssh/vulnerable_host_keys HOST_KEYS "$vulnerable"
+               db_input critical ssh/vulnerable_host_keys || true
+               db_go
+               for hostkey in $vulnerable; do
+                       mv "$hostkey" "$hostkey.broken" || true
+                       mv "$hostkey.pub" "$hostkey.pub.broken" || true
+               done
+               create_keys
+       fi
+}
+
+
+check_password_auth() {
+       passwordauth="$(get_config_option PasswordAuthentication)"
+       crauth="$(get_config_option ChallengeResponseAuthentication)"
+       if [ "$passwordauth" = no ] && \
+          ([ -z "$crauth" ] || [ "$crauth" = yes ]); then
+               db_get ssh/disable_cr_auth
+               if [ "$RET" = true ]; then
+                       set_config_option ChallengeResponseAuthentication no
+               fi
+       fi
+}
+
+
+move_subsystem_sftp() {
+       subsystem_sftp="$(get_config_option 'Subsystem sftp')"
+       if [ "$subsystem_sftp" = /usr/lib/sftp-server ] || \
+          [ "$subsystem_sftp" = /usr/libexec/sftp-server ]; then
+               set_config_option 'Subsystem sftp' /usr/lib/openssh/sftp-server
+       fi
+}
+
+
+fix_loglevel_silent() {
+       if [ "$(get_config_option LogLevel)" = SILENT ]; then
+               set_config_option LogLevel QUIET
+       fi
+}
+
+
+create_sshdconfig() {
+       if [ -e /etc/ssh/sshd_config ] ; then
+           # Upgrade an existing sshd configuration.
+
+           if (dpkg --compare-versions "$oldversion" lt-nl 1:3.8p1-1 && \
+               ! grep -iq ^UsePAM /etc/ssh/sshd_config) || \
+              grep -Eiq '^(PAMAuthenticationViaKbdInt|RhostsAuthentication)' \
+                /etc/ssh/sshd_config ; then
+               # Upgrade from pre-3.7: UsePAM needed to maintain standard
+               # Debian configuration.
+               # Note that --compare-versions is sadly not reliable enough
+               # here due to the package split of ssh into openssh-client
+               # and openssh-server. The extra grep for some deprecated
+               # options should with any luck be a good enough heuristic.
+               echo -n 'Upgrading sshd_config (old version in .dpkg-old) ...'
+               cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-old
+               perl -pe 's/^(PAMAuthenticationViaKbdInt|RhostsAuthentication)\b/#$1/i' \
+                   /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
+               echo >> /etc/ssh/sshd_config.dpkg-new
+               echo 'UsePAM yes' >> /etc/ssh/sshd_config.dpkg-new
+               chown --reference /etc/ssh/sshd_config \
+                                 /etc/ssh/sshd_config.dpkg-new
+               chmod --reference /etc/ssh/sshd_config \
+                                 /etc/ssh/sshd_config.dpkg-new
+               mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
+               echo
+           fi
+
+           # An empty version means we're upgrading from before the
+           # package split, so check.
+           if dpkg --compare-versions "$oldversion" lt 1:3.8.1p1-11; then
+               check_password_auth
+           fi
+
+           # libexecdir changed, so fix up 'Subsystem sftp'.
+           if dpkg --compare-versions "$oldversion" lt 1:4.1p1-1; then
+               move_subsystem_sftp
+           fi
+
+           # Remove obsolete GSSAPI options.
+           if dpkg --compare-versions "$oldversion" lt 1:4.3p2-8; then
+               remove_obsolete_gssapi
+           fi
+
+           # This option was renamed in 3.8p1, but we never took care
+           # of adjusting the configuration file until now.
+           if dpkg --compare-versions "$oldversion" lt 1:4.7p1-8; then
+               rename_config_option KeepAlive TCPKeepAlive
+           fi
+
+           # 'LogLevel SILENT' is now equivalent to QUIET.
+           if dpkg --compare-versions "$oldversion" lt 1:5.4p1-1; then
+               fix_loglevel_silent
+           fi
+
+           return 0
+       fi
+
+       cat <<EOF > /etc/ssh/sshd_config
+# Package generated configuration file
+# See the sshd_config(5) manpage for details
+
+# What ports, IPs and protocols we listen for
+Port 22
+# Use these options to restrict which interfaces/protocols sshd will bind to
+#ListenAddress ::
+#ListenAddress 0.0.0.0
+Protocol 2
+# HostKeys for protocol version 2
+HostKey /etc/ssh/ssh_host_rsa_key
+HostKey /etc/ssh/ssh_host_dsa_key
+HostKey /etc/ssh/ssh_host_ecdsa_key
+#Privilege Separation is turned on for security
+UsePrivilegeSeparation yes
+
+# Lifetime and size of ephemeral version 1 server key
+KeyRegenerationInterval 3600
+ServerKeyBits 768
+
+# Logging
+SyslogFacility AUTH
+LogLevel INFO
+
+# Authentication:
+LoginGraceTime 120
+PermitRootLogin yes
+StrictModes yes
+
+RSAAuthentication yes
+PubkeyAuthentication yes
+#AuthorizedKeysFile    %h/.ssh/authorized_keys
+
+# Don't read the user's ~/.rhosts and ~/.shosts files
+IgnoreRhosts yes
+# For this to work you will also need host keys in /etc/ssh_known_hosts
+RhostsRSAAuthentication no
+# similar for protocol version 2
+HostbasedAuthentication no
+# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
+#IgnoreUserKnownHosts yes
+
+# To enable empty passwords, change to yes (NOT RECOMMENDED)
+PermitEmptyPasswords no
+
+# Change to yes to enable challenge-response passwords (beware issues with
+# some PAM modules and threads)
+ChallengeResponseAuthentication no
+
+# Change to no to disable tunnelled clear text passwords
+#PasswordAuthentication yes
+
+# Kerberos options
+#KerberosAuthentication no
+#KerberosGetAFSToken no
+#KerberosOrLocalPasswd yes
+#KerberosTicketCleanup yes
+
+# GSSAPI options
+#GSSAPIAuthentication no
+#GSSAPICleanupCredentials yes
+
+X11Forwarding yes
+X11DisplayOffset 10
+PrintMotd no
+PrintLastLog yes
+TCPKeepAlive yes
+#UseLogin no
+
+#MaxStartups 10:30:60
+#Banner /etc/issue.net
+
+# Allow client to pass locale environment variables
+AcceptEnv LANG LC_*
+
+Subsystem sftp /usr/lib/openssh/sftp-server
+
+# Set this to 'yes' to enable PAM authentication, account processing,
+# and session processing. If this is enabled, PAM authentication will
+# be allowed through the ChallengeResponseAuthentication and
+# PasswordAuthentication.  Depending on your PAM configuration,
+# PAM authentication via ChallengeResponseAuthentication may bypass
+# the setting of "PermitRootLogin without-password".
+# If you just want the PAM account and session checks to run without
+# PAM authentication, then enable this but set PasswordAuthentication
+# and ChallengeResponseAuthentication to 'no'.
+UsePAM yes
+EOF
+}
+
+fix_statoverride() {
+# Remove an erronous override for sshd (we should have overridden ssh)
+       if [ -x /usr/sbin/dpkg-statoverride ]; then
+               if dpkg-statoverride --list /usr/sbin/sshd >/dev/null ; then
+                       dpkg-statoverride --remove /usr/sbin/sshd
+               fi
+       fi
+}
+
+fix_sshd_shell() {
+       if getent passwd sshd | grep -q ':/bin/false$'; then
+               usermod -s /usr/sbin/nologin sshd || true
+       fi
+}
+
+setup_sshd_user() {
+       if ! getent passwd sshd >/dev/null; then
+               adduser --quiet --system --no-create-home --home /var/run/sshd --shell /usr/sbin/nologin sshd
+       fi
+}
+
+fix_conffile_permissions() {
+       # Clean up after executable /etc/default/ssh in 1:3.5p1-5. dpkg
+       # doesn't do this for us; see bug #192981.
+       chmod 644 /etc/default/ssh
+}
+
+remove_old_init_links() {
+       # Yes, this only works with the SysV init script layout. I know.
+       # The important thing is that it doesn't actually *break* with
+       # file-rc ...
+       if [ -e /etc/rc2.d/S20ssh ]; then
+               update-rc.d -f ssh remove >/dev/null 2>&1
+       fi
+       rm -f /etc/rc0.d/K??ssh /etc/rc1.d/K??ssh /etc/rc6.d/K??ssh
+}
+
+setup_init() {
+       if [ -x /etc/init.d/ssh ]; then
+               update-rc.d ssh start 16 2 3 4 5 . >/dev/null
+               if [ -x /usr/sbin/invoke-rc.d ]; then
+                       invoke-rc.d ssh restart
+               else
+                       /etc/init.d/ssh restart
+               fi
+       fi
+}
+
+commit_transfer_conffile () {
+       CONFFILE="$1"
+       if [ -e "$CONFFILE.moved-by-preinst" ]; then
+               rm -f "$CONFFILE.moved-by-preinst"
+       fi
+}
+
+commit_mv_conffile () {
+       OLDCONFFILE="$1"
+       NEWCONFFILE="$2"
+
+       if [ -e "$OLDCONFFILE.moving" ]; then
+               echo "Preserving user changes to $NEWCONFFILE ..."
+               mv -f "$NEWCONFFILE" "$NEWCONFFILE.dpkg-new"
+               mv -f "$OLDCONFFILE.moving" "$NEWCONFFILE"
+       elif [ -e "$OLDCONFFILE.dpkg-old" ]; then
+               rm -f "$OLDCONFFILE.dpkg-old"
+       fi
+}
+
+
+fix_doc_symlink
+create_sshdconfig
+create_keys
+vulnerable_host_keys
+fix_statoverride
+if dpkg --compare-versions "$2" lt 1:4.3p2-3; then
+    fix_sshd_shell
+fi
+setup_sshd_user
+if dpkg --compare-versions "$2" lt 1:3.6.1p2-2; then
+    fix_conffile_permissions
+fi
+if dpkg --compare-versions "$2" lt 1:5.2p1-1; then
+    remove_old_init_links
+fi
+setup_init
+commit_transfer_conffile /etc/default/ssh
+commit_transfer_conffile /etc/init.d/ssh
+commit_transfer_conffile /etc/pam.d/ssh
+commit_mv_conffile /etc/pam.d/ssh /etc/pam.d/sshd
+# Renamed to /etc/ssh/moduli in 2.9.9 (!)
+if dpkg --compare-versions "$2" lt 1:4.7p1-1; then
+    rm -f /etc/ssh/primes
+fi
+if dpkg --compare-versions "$2" lt 1:5.5p1-6; then
+    rm -f /var/run/sshd/.placeholder
+fi
+
+
+db_stop
+
+exit 0
diff --git a/debian/openssh-server.postrm b/debian/openssh-server.postrm
new file mode 100644 (file)
index 0000000..655c1ae
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/sh -e
+
+#DEBHELPER#
+
+abort_mv_conffile () {
+       CONFFILE="$1"
+
+       if [ ! -e "$CONFFILE" ]; then
+               if [ -e "$CONFFILE.dpkg-old" ]; then
+                       mv -f "$CONFFILE.dpkg-old" "$CONFFILE"
+               elif [ -e "$CONFFILE.moving" ]; then
+                       mv -f "$CONFFILE.moving" "$CONFFILE"
+               fi
+       fi
+}
+
+finish_mv_conffile () {
+       CONFFILE="$1"
+
+       if [ -e "$CONFFILE.dpkg-old" ]; then
+               rm -f "$CONFFILE.dpkg-old"
+       fi
+}
+
+abort_transfer_conffile () {
+       CONFFILE="$1"
+       if [ -e "$CONFFILE.moved-by-preinst" ]; then
+               echo >&2 "Aborting ownership transfer of conffile $CONFFILE ..."
+               mv -f "$CONFFILE.moved-by-preinst" "$CONFFILE"
+               return 0
+       fi
+}
+
+case $1 in
+       abort-install|abort-upgrade)
+               if dpkg --compare-versions "$2" lt 1:4.7p1-4; then
+                       abort_mv_conffile /etc/pam.d/ssh
+               fi
+               abort_transfer_conffile /etc/default/ssh
+               abort_transfer_conffile /etc/init.d/ssh
+               abort_transfer_conffile /etc/pam.d/ssh
+               ;;
+       purge)
+               # Remove all non-conffiles that ssh might create, so that we
+               # can smoothly remove /etc/ssh if and only if the user
+               # hasn't dropped some other files in there. Conffiles have
+               # already been removed at this point.
+               rm -f /etc/ssh/ssh_host_key /etc/ssh/ssh_host_key.pub
+               rm -f /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_rsa_key.pub
+               rm -f /etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_dsa_key.pub
+               rm -f /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ecdsa_key.pub
+               rm -f /etc/ssh/sshd_config
+               rm -f /etc/ssh/sshd_not_to_be_run
+               rmdir --ignore-fail-on-non-empty /etc/ssh
+
+               update-rc.d ssh remove >/dev/null
+
+               if which deluser >/dev/null 2>&1; then
+                       deluser --quiet sshd > /dev/null || true
+               fi
+
+               finish_mv_conffile /etc/pam.d/ssh
+               ;;
+esac
+
+exit 0
diff --git a/debian/openssh-server.preinst b/debian/openssh-server.preinst
new file mode 100644 (file)
index 0000000..5100706
--- /dev/null
@@ -0,0 +1,145 @@
+#!/bin/sh -e
+
+ETC_DEFAULT_SSH=@ETC_DEFAULT_SSH@
+
+ETC_INIT_D_SSH=@ETC_INIT_D_SSH@
+
+ETC_PAM_D_SSH=@ETC_PAM_D_SSH@
+
+action=$1
+version=$2
+
+prepare_transfer_conffile () {
+       CONFFILE="$1"
+       TEXT="$2"
+       MODE="$3"
+       [ "$CONFFILES" ] || return 0
+       [ -e "$CONFFILE" ] || return 0
+
+       md5sum="$(md5sum "$CONFFILE" |sed -e 's/ .*//')"
+       old_md5sum="$(echo "$CONFFILES" | awk '$1 == "'"$CONFFILE"'" { print $2 }')"
+       if [ "$md5sum" = "$old_md5sum" ]; then
+               echo >&2 "Transferring ownership of conffile $CONFFILE ..."
+               # We have to write out the desired new text of the conffile,
+               # which is tricky in the preinst, hence the nasty way we
+               # have to hardcode the text here. Fortunately, this is only
+               # necessary with sarge's dpkg and older.
+               if echo "$TEXT" | head -n1 | grep -q '^@.*@$'; then
+                       echo >&2 'Unsubstituted conffile text! Please report this bug.'
+                       exit 1
+               fi
+               printf '%s' "$TEXT" >"$CONFFILE.dpkg-new"
+               chmod "$MODE" "$CONFFILE.dpkg-new"
+               mv -f "$CONFFILE" "$CONFFILE.moved-by-preinst"
+               mv -f "$CONFFILE.dpkg-new" "$CONFFILE"
+               return 0
+       fi
+}
+
+prepare_mv_conffile () {
+       CONFFILE="$1"
+       [ -e "$CONFFILE" ] || return 0
+
+       md5sum="$(md5sum "$CONFFILE" | sed -e 's/ .*//')"
+       old_md5sum="$(dpkg-query -W -f '${Conffiles}\n' openssh-server 2>/dev/null | sed 's/^ *//' | awk '$1 == "'"$CONFFILE"'" { print $2 }')"
+       if [ "$md5sum" = "$old_md5sum" ]; then
+               mv -f "$CONFFILE" "$CONFFILE.dpkg-old"
+       else
+               mv -f "$CONFFILE" "$CONFFILE.moving"
+       fi
+}
+
+if [ -d /etc/ssh-nonfree ] && [ ! -d /etc/ssh ]; then
+  version=1.2.27
+fi
+
+if [ "$action" = upgrade ] || [ "$action" = install ]
+then
+  # check if debconf is missing
+  if ! test -f /usr/share/debconf/confmodule
+  then
+    cat <<EOF
+
+WARNING: ssh's pre-configuration script relies on debconf to tell you
+about some problems that might prevent you from logging in if you are
+upgrading from the old, Non-free version of ssh.
+
+If this is a new installation, you don't need to worry about this.
+Just go ahead and install ssh (make sure to read .../ssh/README.Debian).
+
+If you are upgrading, but you have alternative ways of logging into
+the machine (i.e. you're sitting in front of it, or you have telnetd
+running), then you also don't need to worry too much, because you can
+fix it up afterwards if there's a problem.
+
+If you're upgrading from an older (non-free) version of ssh, and ssh
+is the only way you have to access this machine, then you should
+probably abort the installation of ssh, install debconf, and then
+retry the installation of ssh.
+
+EOF
+    echo -n "Do you want to install SSH anyway [yN]: "
+    read input
+    expr "$input" : '[Yy]' >/dev/null || exit 1
+
+    # work around for missing debconf
+    db_get() { : ; }
+    RET=true
+    if [ -d /etc/ssh-nonfree ] && [ ! -d /etc/ssh ]; then
+      cp -a /etc/ssh-nonfree /etc/ssh
+    fi
+  else
+    # Source debconf library.
+    . /usr/share/debconf/confmodule
+    db_version 2.0
+  fi
+
+  db_get ssh/use_old_init_script
+  if [ "$RET" = "false" ]; then
+    echo "ssh config: Aborting because ssh/use_old_init_script = false" >&2
+    exit 1
+  fi
+
+  # deal with upgrading from pre-OpenSSH versions
+  key=/etc/ssh/ssh_host_key
+  export key
+  if [ -n "$version" ] && [ -x /usr/bin/ssh-keygen ] && [ -f $key ] &&
+     dpkg --compare-versions "$version" lt 1.2.28
+  then
+    # make sure that keys get updated to get rid of IDEA
+    #
+    # N.B. this only works because we've still got the old
+    # nonfree ssh-keygen at this point
+    #
+    # First, check if we need to bother
+    printf '\0\0' | 3<&0 sh -c \
+        'dd if=$key bs=1 skip=32 count=2 2>/dev/null | cmp -s - /dev/fd/3' || {
+      # this means that bytes 32&33 of the key were not both zero, in which
+      # case the key is encrypted, which we need to fix
+      chmod 600 $key
+      ssh-keygen -u -f $key >/dev/null
+      if which restorecon >/dev/null 2>&1; then
+        restorecon "$key.pub"
+      fi
+    }
+  fi
+
+  if dpkg --compare-versions "$version" lt 0; then
+    CONFFILES="$(dpkg-query -W -f '${Conffiles}\n' ssh 2>/dev/null | sed 's/^ *//')"
+    prepare_transfer_conffile /etc/default/ssh "$ETC_DEFAULT_SSH" 0644
+    prepare_transfer_conffile /etc/init.d/ssh "$ETC_INIT_D_SSH" 0755
+    prepare_transfer_conffile /etc/pam.d/ssh "$ETC_PAM_D_SSH" 0644
+  fi
+
+  if dpkg --compare-versions "$version" lt 1:4.7p1-4; then
+    prepare_mv_conffile /etc/pam.d/ssh
+  fi
+
+  if dpkg --compare-versions "$version" lt 1:5.5p1-6 && \
+     [ -d /var/run/sshd ]; then
+    # make sure /var/run/sshd is not removed on upgrades
+    touch /var/run/sshd/.placeholder
+  fi
+fi
+
+#DEBHELPER#
diff --git a/debian/openssh-server.prerm b/debian/openssh-server.prerm
new file mode 100644 (file)
index 0000000..9c3313a
--- /dev/null
@@ -0,0 +1,48 @@
+#! /bin/sh
+# prerm script for ssh
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <prerm> `remove'
+#        * <old-prerm> `upgrade' <new-version>
+#        * <new-prerm> `failed-upgrade' <old-version>
+#        * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+#        * <deconfigured's-prerm> `deconfigure' `in-favour'
+#          <package-being-installed> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see /usr/share/doc/packaging-manual/
+
+case "$1" in
+    remove|deconfigure)
+       if [ -x /etc/init.d/ssh ]; then
+               if [ -x /usr/sbin/invoke-rc.d ]; then
+                       invoke-rc.d ssh stop
+               else
+                       /etc/init.d/ssh stop
+               fi
+       fi
+       ;;
+    upgrade)
+       # remove symlink on downgrade to when it was a directory
+       if [ -L /usr/share/doc/openssh-server ] && \
+          dpkg --compare-versions "$2" lt-nl 1:4.1p1-5; then
+               rm -f /usr/share/doc/openssh-server
+       fi
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 0
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/openssh-server.ssh.default b/debian/openssh-server.ssh.default
new file mode 100644 (file)
index 0000000..3040422
--- /dev/null
@@ -0,0 +1,5 @@
+# Default settings for openssh-server. This file is sourced by /bin/sh from
+# /etc/init.d/ssh.
+
+# Options to pass to sshd
+SSHD_OPTS=
diff --git a/debian/openssh-server.ssh.init b/debian/openssh-server.ssh.init
new file mode 100644 (file)
index 0000000..62bcc21
--- /dev/null
@@ -0,0 +1,164 @@
+#! /bin/sh
+
+### BEGIN INIT INFO
+# Provides:            sshd
+# Required-Start:      $remote_fs $syslog
+# Required-Stop:       $remote_fs $syslog
+# Default-Start:       2 3 4 5
+# Default-Stop:                
+# Short-Description:   OpenBSD Secure Shell server
+### END INIT INFO
+
+set -e
+
+# /etc/init.d/ssh: start and stop the OpenBSD "secure shell(tm)" daemon
+
+test -x /usr/sbin/sshd || exit 0
+( /usr/sbin/sshd -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0
+
+umask 022
+
+if test -f /etc/default/ssh; then
+    . /etc/default/ssh
+fi
+
+. /lib/lsb/init-functions
+
+if [ -n "$2" ]; then
+    SSHD_OPTS="$SSHD_OPTS $2"
+fi
+
+# Are we running from init?
+run_by_init() {
+    ([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ]
+}
+
+check_for_no_start() {
+    # forget it if we're trying to start, and /etc/ssh/sshd_not_to_be_run exists
+    if [ -e /etc/ssh/sshd_not_to_be_run ]; then 
+       if [ "$1" = log_end_msg ]; then
+           log_end_msg 0
+       fi
+       if ! run_by_init; then
+           log_action_msg "OpenBSD Secure Shell server not in use (/etc/ssh/sshd_not_to_be_run)"
+       fi
+       exit 0
+    fi
+}
+
+check_dev_null() {
+    if [ ! -c /dev/null ]; then
+       if [ "$1" = log_end_msg ]; then
+           log_end_msg 1 || true
+       fi
+       if ! run_by_init; then
+           log_action_msg "/dev/null is not a character device!"
+       fi
+       exit 1
+    fi
+}
+
+check_privsep_dir() {
+    # Create the PrivSep empty dir if necessary
+    if [ ! -d /var/run/sshd ]; then
+       mkdir /var/run/sshd
+       chmod 0755 /var/run/sshd
+    fi
+}
+
+check_config() {
+    if [ ! -e /etc/ssh/sshd_not_to_be_run ]; then
+       /usr/sbin/sshd $SSHD_OPTS -t || exit 1
+    fi
+}
+
+export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
+
+case "$1" in
+  start)
+       check_privsep_dir
+       check_for_no_start
+       check_dev_null
+       log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd"
+       if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
+           log_end_msg 0
+       else
+           log_end_msg 1
+       fi
+       ;;
+  stop)
+       log_daemon_msg "Stopping OpenBSD Secure Shell server" "sshd"
+       if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid; then
+           log_end_msg 0
+       else
+           log_end_msg 1
+       fi
+       ;;
+
+  reload|force-reload)
+       check_for_no_start
+       check_config
+       log_daemon_msg "Reloading OpenBSD Secure Shell server's configuration" "sshd"
+       if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd; then
+           log_end_msg 0
+       else
+           log_end_msg 1
+       fi
+       ;;
+
+  restart)
+       check_privsep_dir
+       check_config
+       log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"
+       start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sshd.pid
+       check_for_no_start log_end_msg
+       check_dev_null log_end_msg
+       if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
+           log_end_msg 0
+       else
+           log_end_msg 1
+       fi
+       ;;
+
+  try-restart)
+       check_privsep_dir
+       check_config
+       log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"
+       set +e
+       start-stop-daemon --stop --quiet --retry 30 --pidfile /var/run/sshd.pid
+       RET="$?"
+       set -e
+       case $RET in
+           0)
+               # old daemon stopped
+               check_for_no_start log_end_msg
+               check_dev_null log_end_msg
+               if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
+                   log_end_msg 0
+               else
+                   log_end_msg 1
+               fi
+               ;;
+           1)
+               # daemon not running
+               log_progress_msg "(not running)"
+               log_end_msg 0
+               ;;
+           *)
+               # failed to stop
+               log_progress_msg "(failed to stop)"
+               log_end_msg 1
+               ;;
+       esac
+       ;;
+
+  status)
+       status_of_proc -p /var/run/sshd.pid /usr/sbin/sshd sshd && exit 0 || exit $?
+       ;;
+
+  *)
+       log_action_msg "Usage: /etc/init.d/ssh {start|stop|reload|force-reload|restart|try-restart|status}"
+       exit 1
+esac
+
+exit 0
diff --git a/debian/openssh-server.sshd.pam b/debian/openssh-server.sshd.pam
new file mode 100644 (file)
index 0000000..9b76951
--- /dev/null
@@ -0,0 +1,39 @@
+# PAM configuration for the Secure Shell service
+
+# Read environment variables from /etc/environment and
+# /etc/security/pam_env.conf.
+auth       required     pam_env.so # [1]
+# In Debian 4.0 (etch), locale-related environment variables were moved to
+# /etc/default/locale, so read that as well.
+auth       required     pam_env.so envfile=/etc/default/locale
+
+# Standard Un*x authentication.
+@include common-auth
+
+# Disallow non-root logins when /etc/nologin exists.
+account    required     pam_nologin.so
+
+# Uncomment and edit /etc/security/access.conf if you need to set complex
+# access limits that are hard to express in sshd_config.
+# account  required     pam_access.so
+
+# Standard Un*x authorization.
+@include common-account
+
+# Standard Un*x session setup and teardown.
+@include common-session
+
+# Print the message of the day upon successful login.
+session    optional     pam_motd.so # [1]
+
+# Print the status of the user's mailbox upon successful login.
+session    optional     pam_mail.so standard noenv # [1]
+
+# Set up user limits from /etc/security/limits.conf.
+session    required     pam_limits.so
+
+# Set up SELinux capabilities (need modified pam)
+# session  required     pam_selinux.so multiple
+
+# Standard Un*x password updating.
+@include common-password
diff --git a/debian/openssh-server.templates b/debian/openssh-server.templates
new file mode 100644 (file)
index 0000000..6c7d399
--- /dev/null
@@ -0,0 +1,68 @@
+# These templates have been reviewed by the debian-l10n-english
+# team
+#
+# If modifications/additions/rewording are needed, please ask
+# for an advice to debian-l10n-english@lists.debian.org
+#
+# Even minor modifications require translation updates and such
+# changes should be coordinated with translators and reviewers.
+#
+Template: ssh/use_old_init_script
+Type: boolean
+Default: false
+_Description: Do you want to risk killing active SSH sessions?
+ The currently installed version of /etc/init.d/ssh is likely to kill
+ all running sshd instances. If you are doing this upgrade via an SSH
+ session, you're likely to be disconnected and leave the upgrade
+ procedure unfinished.
+ .
+ This can be fixed by manually adding "--pidfile /var/run/sshd.pid" to
+ the start-stop-daemon line in the stop section of the file.
+
+Template: ssh/encrypted_host_key_but_no_keygen
+Type: note
+_Description: New host key mandatory
+ The current host key, in /etc/ssh/ssh_host_key, is encrypted with the
+ IDEA algorithm. OpenSSH can not handle this host key file, and the
+ ssh-keygen utility from the old (non-free) SSH installation does not
+ appear to be available.
+ .
+ You need to manually generate a new host key.
+
+Template: ssh/disable_cr_auth
+Type: boolean
+Default: false
+_Description: Disable challenge-response authentication?
+ Password authentication appears to be disabled in the current OpenSSH
+ server configuration. In order to prevent users from logging in using
+ passwords (perhaps using only public key authentication instead) with
+ recent versions of OpenSSH, you must disable challenge-response
+ authentication, or else ensure that your PAM configuration does not allow
+ Unix password file authentication.
+ .
+ If you disable challenge-response authentication, then users will not be
+ able to log in using passwords. If you leave it enabled (the default
+ answer), then the 'PasswordAuthentication no' option will have no useful
+ effect unless you also adjust your PAM configuration in /etc/pam.d/ssh.
+
+Template: ssh/vulnerable_host_keys
+Type: note
+#flag:translate!:5
+_Description: Vulnerable host keys will be regenerated
+ Some of the OpenSSH server host keys on this system were generated with a
+ version of OpenSSL that had a broken random number generator. As a result,
+ these host keys are from a well-known set, are subject to brute-force
+ attacks, and must be regenerated.
+ .
+ Users of this system should be informed of this change, as they will be
+ prompted about the host key change the next time they log in. Use
+ 'ssh-keygen -l -f HOST_KEY_FILE' after the upgrade to print the
+ fingerprints of the new host keys.
+ .
+ The affected host keys are:
+ .
+ ${HOST_KEYS}
+ .
+ User keys may also be affected by this problem. The 'ssh-vulnkey' command
+ may be used as a partial test for this. See
+ /usr/share/doc/openssh-server/README.compromised-keys.gz for more details.
diff --git a/debian/openssh-server.ufw.profile b/debian/openssh-server.ufw.profile
new file mode 100644 (file)
index 0000000..9bbe906
--- /dev/null
@@ -0,0 +1,4 @@
+[OpenSSH]
+title=Secure shell server, an rshd replacement
+description=OpenSSH is a free implementation of the Secure Shell protocol.
+ports=22/tcp
diff --git a/debian/patches/auth-log-verbosity.patch b/debian/patches/auth-log-verbosity.patch
new file mode 100644 (file)
index 0000000..da940d9
--- /dev/null
@@ -0,0 +1,123 @@
+Description: Quieten logs when multiple from= restrictions are used
+Author: Colin Watson <cjwatson@debian.org>
+Bug-Debian: http://bugs.debian.org/630606
+Forwarded: no
+Last-Update: 2011-07-28
+
+Index: b/auth-options.c
+===================================================================
+--- a/auth-options.c
++++ b/auth-options.c
+@@ -58,9 +58,20 @@
+ /* "principals=" option. */
+ char *authorized_principals = NULL;
++/* Throttle log messages. */
++int logged_from_hostip = 0;
++int logged_cert_hostip = 0;
++
+ extern ServerOptions options;
+ void
++auth_start_parse_options(void)
++{
++      logged_from_hostip = 0;
++      logged_cert_hostip = 0;
++}
++
++void
+ auth_clear_options(void)
+ {
+       no_agent_forwarding_flag = 0;
+@@ -288,10 +299,13 @@
+                               /* FALLTHROUGH */
+                       case 0:
+                               xfree(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);
++                              if (!logged_from_hostip) {
++                                      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);
++                                      logged_from_hostip = 1;
++                              }
+                               auth_debug_add("Your host '%.200s' is not "
+                                   "permitted to use this key for login.",
+                                   remote_host);
+@@ -526,11 +540,14 @@
+                                       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);
++                                      if (!logged_cert_hostip) {
++                                              logit("Authentication tried for %.100s "
++                                                  "with valid certificate but not "
++                                                  "from a permitted host "
++                                                  "(ip=%.200s).", pw->pw_name,
++                                                  remote_ip);
++                                              logged_cert_hostip = 1;
++                                      }
+                                       auth_debug_add("Your address '%.200s' "
+                                           "is not permitted to use this "
+                                           "certificate for login.",
+Index: b/auth-options.h
+===================================================================
+--- a/auth-options.h
++++ b/auth-options.h
+@@ -33,6 +33,7 @@
+ extern int key_is_cert_authority;
+ extern char *authorized_principals;
++void  auth_start_parse_options(void);
+ int   auth_parse_options(struct passwd *, char *, char *, u_long);
+ void  auth_clear_options(void);
+ int   auth_cert_options(Key *, struct passwd *);
+Index: b/auth-rsa.c
+===================================================================
+--- a/auth-rsa.c
++++ b/auth-rsa.c
+@@ -175,6 +175,8 @@
+       if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
+               return 0;
++      auth_start_parse_options();
++
+       /*
+        * Go though the accepted keys, looking for the current key.  If
+        * found, perform a challenge-response dialog to verify that the
+Index: b/auth2-pubkey.c
+===================================================================
+--- a/auth2-pubkey.c
++++ b/auth2-pubkey.c
+@@ -211,6 +211,7 @@
+               restore_uid();
+               return 0;
+       }
++      auth_start_parse_options();
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               /* Skip leading whitespace. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+@@ -280,6 +281,8 @@
+       found_key = 0;
+       found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
++      auth_start_parse_options();
++
+       while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
+               char *cp, *key_options = NULL;
+@@ -416,6 +419,7 @@
+       if (key_cert_check_authority(key, 0, 1,
+           principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
+               goto fail_reason;
++      auth_start_parse_options();
+       if (auth_cert_options(key, pw) != 0)
+               goto out;
diff --git a/debian/patches/authorized-keys-man-symlink.patch b/debian/patches/authorized-keys-man-symlink.patch
new file mode 100644 (file)
index 0000000..a9ca854
--- /dev/null
@@ -0,0 +1,18 @@
+Description: Install authorized_keys(5) as a symlink to sshd(8)
+Author: Tomas Pospisek <tpo_deb@sourcepole.ch>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1720
+Bug-Debian: http://bugs.debian.org/441817
+Last-Update: 2010-03-01
+
+Index: b/Makefile.in
+===================================================================
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -275,6 +275,7 @@
+       $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
+       $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
+       $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
++      ln -s ../$(mansubdir)8/sshd.8 $(DESTDIR)$(mandir)/$(mansubdir)5/authorized_keys.5
+       $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
diff --git a/debian/patches/debian-banner.patch b/debian/patches/debian-banner.patch
new file mode 100644 (file)
index 0000000..57ca35e
--- /dev/null
@@ -0,0 +1,99 @@
+Description: Add DebianBanner server configuration option
+ Setting this to "no" causes sshd to omit the Debian revision from its
+ initial protocol handshake, for those scared by package-versioning.patch.
+Author: Kees Cook <kees@debian.org>
+Bug-Debian: http://bugs.debian.org/562048
+Forwarded: not-needed
+Last-Update: 2010-02-28
+
+Index: b/servconf.c
+===================================================================
+--- a/servconf.c
++++ b/servconf.c
+@@ -142,6 +142,7 @@
+       options->authorized_principals_file = NULL;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
++      options->debian_banner = -1;
+ }
+ void
+@@ -289,6 +290,8 @@
+               options->ip_qos_interactive = IPTOS_LOWDELAY;
+       if (options->ip_qos_bulk == -1)
+               options->ip_qos_bulk = IPTOS_THROUGHPUT;
++      if (options->debian_banner == -1)
++              options->debian_banner = 1;
+       /* Turn privilege separation on by default */
+       if (use_privsep == -1)
+@@ -338,6 +341,7 @@
+       sZeroKnowledgePasswordAuthentication, sHostCertificate,
+       sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+       sKexAlgorithms, sIPQoS,
++      sDebianBanner,
+       sDeprecated, sUnsupported
+ } ServerOpCodes;
+@@ -473,6 +477,7 @@
+       { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
+       { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+       { "ipqos", sIPQoS, SSHCFG_ALL },
++      { "debianbanner", sDebianBanner, SSHCFG_GLOBAL },
+       { NULL, sBadOption, 0 }
+ };
+@@ -1436,6 +1441,10 @@
+               }
+               break;
++      case sDebianBanner:
++              intptr = &options->debian_banner;
++              goto parse_int;
++
+       case sDeprecated:
+               logit("%s line %d: Deprecated option %s",
+                   filename, linenum, arg);
+Index: b/servconf.h
+===================================================================
+--- a/servconf.h
++++ b/servconf.h
+@@ -166,6 +166,8 @@
+       int     num_permitted_opens;
++      int     debian_banner;
++
+       char   *chroot_directory;
+       char   *revoked_keys_file;
+       char   *trusted_user_ca_keys;
+Index: b/sshd.c
+===================================================================
+--- a/sshd.c
++++ b/sshd.c
+@@ -423,7 +423,8 @@
+               minor = PROTOCOL_MINOR_1;
+       }
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+-          SSH_RELEASE, newline);
++          options.debian_banner ? SSH_RELEASE : SSH_RELEASE_MINIMUM,
++          newline);
+       server_version_string = xstrdup(buf);
+       /* Send our protocol version identification. */
+Index: b/sshd_config.5
+===================================================================
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -340,6 +340,11 @@
+ .Dq no .
+ The default is
+ .Dq delayed .
++.It Cm DebianBanner
++Specifies whether the distribution-specified extra version suffix is
++included during initial protocol handshake.
++The default is
++.Dq yes .
+ .It Cm DenyGroups
+ This keyword can be followed by a list of group name patterns, separated
+ by spaces.
diff --git a/debian/patches/debian-config.patch b/debian/patches/debian-config.patch
new file mode 100644 (file)
index 0000000..74aa53e
--- /dev/null
@@ -0,0 +1,146 @@
+Description: Various Debian-specific configuration changes
+ ssh: Enable ForwardX11Trusted, returning to earlier semantics which cause
+ fewer problems with existing setups (http://bugs.debian.org/237021).
+ .
+ ssh: Set 'SendEnv LANG LC_*' by default (http://bugs.debian.org/264024).
+ .
+ ssh: Enable HashKnownHosts by default to try to limit the spread of ssh
+ worms.
+ .
+ ssh: Enable GSSAPIAuthentication and disable GSSAPIDelegateCredentials by
+ default.
+ .
+ sshd: Refer to /usr/share/doc/openssh-server/README.Debian.gz alongside
+ PermitRootLogin default.
+ .
+ Document all of this, along with several sshd defaults set in
+ debian/openssh-server.postinst.
+Author: Colin Watson <cjwatson@debian.org>
+Author: Russ Allbery <rra@debian.org>
+Forwarded: not-needed
+Last-Update: 2010-02-28
+
+Index: b/readconf.c
+===================================================================
+--- a/readconf.c
++++ b/readconf.c
+@@ -1268,7 +1268,7 @@
+       if (options->forward_x11 == -1)
+               options->forward_x11 = 0;
+       if (options->forward_x11_trusted == -1)
+-              options->forward_x11_trusted = 0;
++              options->forward_x11_trusted = 1;
+       if (options->forward_x11_timeout == -1)
+               options->forward_x11_timeout = 1200;
+       if (options->exit_on_forward_failure == -1)
+Index: b/ssh_config
+===================================================================
+--- a/ssh_config
++++ b/ssh_config
+@@ -17,9 +17,10 @@
+ # list of available options, their meanings and defaults, please see the
+ # ssh_config(5) man page.
+-# Host *
++Host *
+ #   ForwardAgent no
+ #   ForwardX11 no
++#   ForwardX11Trusted yes
+ #   RhostsRSAAuthentication no
+ #   RSAAuthentication yes
+ #   PasswordAuthentication yes
+@@ -47,3 +48,7 @@
+ #   PermitLocalCommand no
+ #   VisualHostKey no
+ #   ProxyCommand ssh -q -W %h:%p gateway.example.com
++    SendEnv LANG LC_*
++    HashKnownHosts yes
++    GSSAPIAuthentication yes
++    GSSAPIDelegateCredentials no
+Index: b/ssh_config.5
+===================================================================
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -71,6 +71,22 @@
+ host-specific declarations should be given near the beginning of the
+ file, and general defaults at the end.
+ .Pp
++Note that the Debian
++.Ic openssh-client
++package sets several options as standard in
++.Pa /etc/ssh/ssh_config
++which are not the default in
++.Xr ssh 1 :
++.Pp
++.Bl -bullet -offset indent -compact
++.It
++.Cm SendEnv No LANG LC_*
++.It
++.Cm HashKnownHosts No yes
++.It
++.Cm GSSAPIAuthentication No yes
++.El
++.Pp
+ The configuration file has the following format:
+ .Pp
+ Empty lines and lines starting with
+@@ -499,7 +515,8 @@
+ Remote clients will be refused access after this time.
+ .Pp
+ The default is
+-.Dq no .
++.Dq yes
++(Debian-specific).
+ .Pp
+ See the X11 SECURITY extension specification for full details on
+ the restrictions imposed on untrusted clients.
+Index: b/sshd_config
+===================================================================
+--- a/sshd_config
++++ b/sshd_config
+@@ -37,6 +37,7 @@
+ # Authentication:
+ #LoginGraceTime 2m
++# See /usr/share/doc/openssh-server/README.Debian.gz.
+ #PermitRootLogin yes
+ #StrictModes yes
+ #MaxAuthTries 6
+Index: b/sshd_config.5
+===================================================================
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -57,6 +57,33 @@
+ .Pq \&"
+ in order to represent arguments containing spaces.
+ .Pp
++Note that the Debian
++.Ic openssh-server
++package sets several options as standard in
++.Pa /etc/ssh/sshd_config
++which are not the default in
++.Xr sshd 8 .
++The exact list depends on whether the package was installed fresh or
++upgraded from various possible previous versions, but includes at least the
++following:
++.Pp
++.Bl -bullet -offset indent -compact
++.It
++.Cm Protocol No 2
++.It
++.Cm ChallengeResponseAuthentication No no
++.It
++.Cm X11Forwarding No yes
++.It
++.Cm PrintMotd No no
++.It
++.Cm AcceptEnv No LANG LC_*
++.It
++.Cm Subsystem No sftp /usr/lib/openssh/sftp-server
++.It
++.Cm UsePAM No yes
++.El
++.Pp
+ The possible
+ keywords and their meanings are as follows (note that
+ keywords are case-insensitive and arguments are case-sensitive):
diff --git a/debian/patches/dnssec-sshfp.patch b/debian/patches/dnssec-sshfp.patch
new file mode 100644 (file)
index 0000000..8e8285a
--- /dev/null
@@ -0,0 +1,82 @@
+Description: Force use of DNSSEC even if "options edns0" isn't in resolv.conf
+ This allows SSHFP DNS records to be verified if glibc 2.11 is installed.
+Origin: vendor, https://cvs.fedoraproject.org/viewvc/F-12/openssh/openssh-5.2p1-edns.patch?revision=1.1&view=markup
+Bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572049
+Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=572049
+Last-Update: 2010-04-06
+
+Index: b/dns.c
+===================================================================
+--- a/dns.c
++++ b/dns.c
+@@ -177,6 +177,7 @@
+ {
+       u_int counter;
+       int result;
++      unsigned int rrset_flags = 0;
+       struct rrsetinfo *fingerprints = NULL;
+       u_int8_t hostkey_algorithm;
+@@ -200,8 +201,19 @@
+               return -1;
+       }
++      /*
++       * Original getrrsetbyname function, found on OpenBSD for example,
++       * doesn't accept any flag and prerequisite for obtaining AD bit in
++       * DNS response is set by "options edns0" in resolv.conf.
++       *
++       * Our version is more clever and use RRSET_FORCE_EDNS0 flag.
++       */
++#ifndef HAVE_GETRRSETBYNAME
++      rrset_flags |= RRSET_FORCE_EDNS0;
++#endif
+       result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
+-          DNS_RDATATYPE_SSHFP, 0, &fingerprints);
++          DNS_RDATATYPE_SSHFP, rrset_flags, &fingerprints);
++
+       if (result) {
+               verbose("DNS lookup error: %s", dns_result_totext(result));
+               return -1;
+Index: b/openbsd-compat/getrrsetbyname.c
+===================================================================
+--- a/openbsd-compat/getrrsetbyname.c
++++ b/openbsd-compat/getrrsetbyname.c
+@@ -209,8 +209,8 @@
+               goto fail;
+       }
+-      /* don't allow flags yet, unimplemented */
+-      if (flags) {
++      /* Allow RRSET_FORCE_EDNS0 flag only. */
++      if ((flags & !RRSET_FORCE_EDNS0) != 0) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+@@ -226,9 +226,9 @@
+ #endif /* DEBUG */
+ #ifdef RES_USE_DNSSEC
+-      /* turn on DNSSEC if EDNS0 is configured */
+-      if (_resp->options & RES_USE_EDNS0)
+-              _resp->options |= RES_USE_DNSSEC;
++      /* turn on DNSSEC if required  */
++      if (flags & RRSET_FORCE_EDNS0)
++              _resp->options |= (RES_USE_EDNS0|RES_USE_DNSSEC);
+ #endif /* RES_USE_DNSEC */
+       /* make query */
+Index: b/openbsd-compat/getrrsetbyname.h
+===================================================================
+--- a/openbsd-compat/getrrsetbyname.h
++++ b/openbsd-compat/getrrsetbyname.h
+@@ -72,6 +72,9 @@
+ #ifndef RRSET_VALIDATED
+ # define RRSET_VALIDATED      1
+ #endif
++#ifndef RRSET_FORCE_EDNS0
++# define RRSET_FORCE_EDNS0    0x0001
++#endif
+ /*
+  * Return codes for getrrsetbyname()
diff --git a/debian/patches/doc-hash-tab-completion.patch b/debian/patches/doc-hash-tab-completion.patch
new file mode 100644 (file)
index 0000000..cec6f66
--- /dev/null
@@ -0,0 +1,20 @@
+Description: Document that HashKnownHosts may break tab-completion
+Author: Colin Watson <cjwatson@debian.org>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1727
+Bug-Debian: http://bugs.debian.org/430154
+Last-Update: 2010-03-01
+
+Index: b/ssh_config.5
+===================================================================
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -585,6 +585,9 @@
+ will not be converted automatically,
+ but may be manually hashed using
+ .Xr ssh-keygen 1 .
++Use of this option may break facilities such as tab-completion that rely
++on being able to read unhashed host names from
++.Pa ~/.ssh/known_hosts .
+ .It Cm HostbasedAuthentication
+ Specifies whether to try rhosts based authentication with public key
+ authentication.
diff --git a/debian/patches/gnome-ssh-askpass2-icon.patch b/debian/patches/gnome-ssh-askpass2-icon.patch
new file mode 100644 (file)
index 0000000..96bbf3a
--- /dev/null
@@ -0,0 +1,18 @@
+Description: Give the ssh-askpass-gnome window a default icon
+Author: Vincent Untz <vuntz@ubuntu.com>
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/27152
+Last-Update: 2010-02-28
+
+Index: b/contrib/gnome-ssh-askpass2.c
+===================================================================
+--- a/contrib/gnome-ssh-askpass2.c
++++ b/contrib/gnome-ssh-askpass2.c
+@@ -209,6 +209,8 @@
+       gtk_init(&argc, &argv);
++      gtk_window_set_default_icon_from_file ("/usr/share/pixmaps/ssh-askpass-gnome.png", NULL);
++
+       if (argc > 1) {
+               message = g_strjoinv(" ", argv + 1);
+       } else {
diff --git a/debian/patches/gssapi.patch b/debian/patches/gssapi.patch
new file mode 100644 (file)
index 0000000..dc29368
--- /dev/null
@@ -0,0 +1,3091 @@
+Description: GSSAPI key exchange support
+ This patch has been rejected upstream: "None of the OpenSSH developers are
+ in favour of adding this, and this situation has not changed for several
+ years.  This is not a slight on Simon's patch, which is of fine quality,
+ but just that a) we don't trust GSSAPI implementations that much and b) we
+ don't like adding new KEX since they are pre-auth attack surface.  This one
+ is particularly scary, since it requires hooks out to typically root-owned
+ system resources."
+ .
+ However, quite a lot of people rely on this in Debian, and it's better to
+ have it merged into the main openssh package rather than having separate
+ -krb5 packages (as we used to have).  It seems to have a generally good
+ security history.
+Author: Simon Wilkinson <simon@sxw.org.uk>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
+Last-Updated: 2010-02-27
+
+Index: b/ChangeLog.gssapi
+===================================================================
+--- /dev/null
++++ b/ChangeLog.gssapi
+@@ -0,0 +1,113 @@
++20110101
++  - Finally update for OpenSSH 5.6p1
++  - Add GSSAPIServerIdentity option from Jim Basney
++ 
++20100308
++  - [ Makefile.in, key.c, key.h ]
++    Updates for OpenSSH 5.4p1
++  - [ servconf.c ]
++    Include GSSAPI options in the sshd -T configuration dump, and flag
++    some older configuration options as being unsupported. Thanks to Colin 
++    Watson.
++  -
++
++20100124
++  - [ sshconnect2.c ]
++    Adapt to deal with additional element in Authmethod structure. Thanks to
++    Colin Watson
++
++20090615
++  - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
++      sshd.c ]
++    Fix issues identified by Greg Hudson following a code review
++      Check return value of gss_indicate_mechs
++      Protect GSSAPI calls in monitor, so they can only be used if enabled
++      Check return values of bignum functions in key exchange
++      Use BN_clear_free to clear other side's DH value
++      Make ssh_gssapi_id_kex more robust
++      Only configure kex table pointers if GSSAPI is enabled
++      Don't leak mechanism list, or gss mechanism list
++      Cast data.length before printing
++      If serverkey isn't provided, use an empty string, rather than NULL
++
++20090201
++  - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
++      ssh_config.5 sshconnet2.c ]
++    Add support for the GSSAPIClientIdentity option, which allows the user
++    to specify which GSSAPI identity to use to contact a given server
++
++20080404
++  - [ gss-serv.c ]
++    Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
++    been omitted from a previous version of this patch. Reported by Borislav
++    Stoichkov
++
++20070317
++  - [ gss-serv-krb5.c ]
++    Remove C99ism, where new_ccname was being declared in the middle of a 
++    function
++
++20061220
++  - [ servconf.c ]
++    Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and 
++    documented, behaviour. Reported by Dan Watson.
++
++20060910
++  - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
++      ssh-gss.h ]
++    add support for gss-group14-sha1 key exchange mechanisms
++  - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
++    Add GSSAPIStrictAcceptorCheck option to allow the disabling of
++    acceptor principal checking on multi-homed machines.
++    <Bugzilla #928>
++  - [ sshd_config ssh_config ]
++    Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
++    configuration files
++  - [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
++    Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
++    Limit length of error messages displayed by client
++
++20060909
++  - [ gss-genr.c gss-serv.c ]
++    move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
++    only, where they belong 
++    <Bugzilla #1225>
++
++20060829
++  - [ gss-serv-krb5.c ]
++    Fix CCAPI credentials cache name when creating KRB5CCNAME environment 
++    variable
++
++20060828
++  - [ gss-genr.c ]
++    Avoid Heimdal context freeing problem
++    <Fixed upstream 20060829>
++
++20060818
++  - [ gss-genr.c ssh-gss.h sshconnect2.c ]
++    Make sure that SPENGO is disabled 
++    <Bugzilla #1218 - Fixed upstream 20060818>
++
++20060421
++  - [ gssgenr.c, sshconnect2.c ]
++    a few type changes (signed versus unsigned, int versus size_t) to
++    fix compiler errors/warnings 
++    (from jbasney AT ncsa.uiuc.edu)
++  - [ kexgssc.c, sshconnect2.c ]
++    fix uninitialized variable warnings
++    (from jbasney AT ncsa.uiuc.edu)
++  - [ gssgenr.c ]
++    pass oid to gss_display_status (helpful when using GSSAPI mechglue)
++    (from jbasney AT ncsa.uiuc.edu)
++    <Bugzilla #1220 >
++  - [ gss-serv-krb5.c ]
++    #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
++    (from jbasney AT ncsa.uiuc.edu)
++    <Fixed upstream 20060304>
++  - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c 
++    add client-side GssapiKeyExchange option
++    (from jbasney AT ncsa.uiuc.edu)
++  - [ sshconnect2.c ]
++    add support for GssapiTrustDns option for gssapi-with-mic
++    (from jbasney AT ncsa.uiuc.edu)
++    <gssapi-with-mic support is Bugzilla #1008>
+Index: b/Makefile.in
+===================================================================
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -70,6 +70,7 @@
+       atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
+       monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
+       kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
++      kexgssc.o \
+       msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
+       schnorr.o ssh-pkcs11.o
+@@ -86,7 +87,7 @@
+       auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
+       monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
+       auth-krb5.o \
+-      auth2-gss.o gss-serv.o gss-serv-krb5.o \
++      auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
+       loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
+       sftp-server.o sftp-common.o \
+       roaming_common.o roaming_serv.o \
+Index: b/auth-krb5.c
+===================================================================
+--- a/auth-krb5.c
++++ b/auth-krb5.c
+@@ -170,8 +170,13 @@
+       len = strlen(authctxt->krb5_ticket_file) + 6;
+       authctxt->krb5_ccname = xmalloc(len);
++#ifdef USE_CCAPI
++      snprintf(authctxt->krb5_ccname, len, "API:%s",
++          authctxt->krb5_ticket_file);
++#else
+       snprintf(authctxt->krb5_ccname, len, "FILE:%s",
+           authctxt->krb5_ticket_file);
++#endif
+ #ifdef USE_PAM
+       if (options.use_pam)
+@@ -226,15 +231,22 @@
+ #ifndef HEIMDAL
+ krb5_error_code
+ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
+-      int tmpfd, ret;
++      int ret;
+       char ccname[40];
+       mode_t old_umask;
++#ifdef USE_CCAPI
++      char cctemplate[] = "API:krb5cc_%d";
++#else
++      char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
++      int tmpfd;
++#endif
+       ret = snprintf(ccname, sizeof(ccname),
+-          "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
++          cctemplate, geteuid());
+       if (ret < 0 || (size_t)ret >= sizeof(ccname))
+               return ENOMEM;
++#ifndef USE_CCAPI
+       old_umask = umask(0177);
+       tmpfd = mkstemp(ccname + strlen("FILE:"));
+       umask(old_umask);
+@@ -249,6 +261,7 @@
+               return errno;
+       }
+       close(tmpfd);
++#endif
+       return (krb5_cc_resolve(ctx, ccname, ccache));
+ }
+Index: b/auth2-gss.c
+===================================================================
+--- a/auth2-gss.c
++++ b/auth2-gss.c
+@@ -1,7 +1,7 @@
+ /* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
+ /*
+- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -52,6 +52,40 @@
+ static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
+ static void input_gssapi_errtok(int, u_int32_t, void *);
++/* 
++ * The 'gssapi_keyex' userauth mechanism.
++ */
++static int
++userauth_gsskeyex(Authctxt *authctxt)
++{
++      int authenticated = 0;
++      Buffer b;
++      gss_buffer_desc mic, gssbuf;
++      u_int len;
++
++      mic.value = packet_get_string(&len);
++      mic.length = len;
++
++      packet_check_eom();
++
++      ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
++          "gssapi-keyex");
++
++      gssbuf.value = buffer_ptr(&b);
++      gssbuf.length = buffer_len(&b);
++
++      /* gss_kex_context is NULL with privsep, so we can't check it here */
++      if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
++          &gssbuf, &mic))))
++              authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
++                  authctxt->pw));
++      
++      buffer_free(&b);
++      xfree(mic.value);
++
++      return (authenticated);
++}
++
+ /*
+  * We only support those mechanisms that we know about (ie ones that we know
+  * how to check local user kuserok and the like)
+@@ -244,7 +278,8 @@
+       packet_check_eom();
+-      authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
++      authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
++          authctxt->pw));
+       authctxt->postponed = 0;
+       dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+@@ -279,7 +314,8 @@
+       gssbuf.length = buffer_len(&b);
+       if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
+-              authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
++              authenticated = 
++                  PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
+       else
+               logit("GSSAPI MIC check failed");
+@@ -294,6 +330,12 @@
+       userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+ }
++Authmethod method_gsskeyex = {
++      "gssapi-keyex",
++      userauth_gsskeyex,
++      &options.gss_authentication
++};
++
+ Authmethod method_gssapi = {
+       "gssapi-with-mic",
+       userauth_gssapi,
+Index: b/auth2.c
+===================================================================
+--- a/auth2.c
++++ b/auth2.c
+@@ -69,6 +69,7 @@
+ extern Authmethod method_kbdint;
+ extern Authmethod method_hostbased;
+ #ifdef GSSAPI
++extern Authmethod method_gsskeyex;
+ extern Authmethod method_gssapi;
+ #endif
+ #ifdef JPAKE
+@@ -79,6 +80,7 @@
+       &method_none,
+       &method_pubkey,
+ #ifdef GSSAPI
++      &method_gsskeyex,
+       &method_gssapi,
+ #endif
+ #ifdef JPAKE
+Index: b/clientloop.c
+===================================================================
+--- a/clientloop.c
++++ b/clientloop.c
+@@ -111,6 +111,10 @@
+ #include "msg.h"
+ #include "roaming.h"
++#ifdef GSSAPI
++#include "ssh-gss.h"
++#endif
++
+ /* import options */
+ extern Options options;
+@@ -1508,6 +1512,15 @@
+               /* Do channel operations unless rekeying in progress. */
+               if (!rekeying) {
+                       channel_after_select(readset, writeset);
++
++#ifdef GSSAPI
++                      if (options.gss_renewal_rekey &&
++                          ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) {
++                              debug("credentials updated - forcing rekey");
++                              need_rekeying = 1;
++                      }
++#endif
++
+                       if (need_rekeying || packet_need_rekeying()) {
+                               debug("need rekeying");
+                               xxx_kex->done = 0;
+Index: b/config.h.in
+===================================================================
+--- a/config.h.in
++++ b/config.h.in
+@@ -1441,6 +1441,9 @@
+ /* Use btmp to log bad logins */
+ #undef USE_BTMP
++/* platform uses an in-memory credentials cache */
++#undef USE_CCAPI
++
+ /* Use libedit for sftp */
+ #undef USE_LIBEDIT
+@@ -1456,6 +1459,9 @@
+ /* Use PIPES instead of a socketpair() */
+ #undef USE_PIPES
++/* platform has the Security Authorization Session API */
++#undef USE_SECURITY_SESSION_API
++
+ /* Define if you have Solaris process contracts */
+ #undef USE_SOLARIS_PROCESS_CONTRACTS
+Index: b/configure
+===================================================================
+--- a/configure
++++ b/configure
+@@ -6521,6 +6521,63 @@
+ $as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
++      { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have the Security Authorization Session API" >&5
++$as_echo_n "checking if we have the Security Authorization Session API... " >&6; }
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include <Security/AuthSession.h>
++int
++main ()
++{
++SessionCreate(0, 0);
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_cv_use_security_session_api="yes"
++
++$as_echo "#define USE_SECURITY_SESSION_API 1" >>confdefs.h
++
++               LIBS="$LIBS -framework Security"
++               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
++else
++  ac_cv_use_security_session_api="no"
++               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++      { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have an in-memory credentials cache" >&5
++$as_echo_n "checking if we have an in-memory credentials cache... " >&6; }
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include <Kerberos/Kerberos.h>
++int
++main ()
++{
++cc_context_t c;
++               (void) cc_initialize (&c, 0, NULL, NULL);
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++
++$as_echo "#define USE_CCAPI 1" >>confdefs.h
++
++               LIBS="$LIBS -framework Security"
++               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
++               if test "x$ac_cv_use_security_session_api" = "xno"; then
++                      as_fn_error $? "*** Need a security framework to use the credentials cache API ***" "$LINENO" 5
++              fi
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default"
+ if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then :
+Index: b/configure.ac
+===================================================================
+--- a/configure.ac
++++ b/configure.ac
+@@ -515,6 +515,30 @@
+           [Use tunnel device compatibility to OpenBSD])
+       AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
+           [Prepend the address family to IP tunnel traffic])
++      AC_MSG_CHECKING([if we have the Security Authorization Session API])
++      AC_TRY_COMPILE([#include <Security/AuthSession.h>],
++              [SessionCreate(0, 0);],
++              [ac_cv_use_security_session_api="yes"
++               AC_DEFINE([USE_SECURITY_SESSION_API], [1], 
++                      [platform has the Security Authorization Session API])
++               LIBS="$LIBS -framework Security"
++               AC_MSG_RESULT([yes])],
++              [ac_cv_use_security_session_api="no"
++               AC_MSG_RESULT([no])])
++      AC_MSG_CHECKING([if we have an in-memory credentials cache])
++      AC_TRY_COMPILE(
++              [#include <Kerberos/Kerberos.h>],
++              [cc_context_t c;
++               (void) cc_initialize (&c, 0, NULL, NULL);],
++              [AC_DEFINE([USE_CCAPI], [1], 
++                      [platform uses an in-memory credentials cache])
++               LIBS="$LIBS -framework Security"
++               AC_MSG_RESULT([yes])
++               if test "x$ac_cv_use_security_session_api" = "xno"; then
++                      AC_MSG_ERROR([*** Need a security framework to use the credentials cache API ***])
++              fi],
++              [AC_MSG_RESULT([no])]
++      )
+       m4_pattern_allow([AU_IPv])
+       AC_CHECK_DECL([AU_IPv4], [], 
+           AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
+Index: b/gss-genr.c
+===================================================================
+--- a/gss-genr.c
++++ b/gss-genr.c
+@@ -1,7 +1,7 @@
+ /* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */
+ /*
+- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -39,12 +39,167 @@
+ #include "buffer.h"
+ #include "log.h"
+ #include "ssh2.h"
++#include "cipher.h"
++#include "key.h"
++#include "kex.h"
++#include <openssl/evp.h>
+ #include "ssh-gss.h"
+ extern u_char *session_id2;
+ extern u_int session_id2_len;
++typedef struct {
++      char *encoded;
++      gss_OID oid;
++} ssh_gss_kex_mapping;
++
++/*
++ * XXX - It would be nice to find a more elegant way of handling the
++ * XXX   passing of the key exchange context to the userauth routines
++ */
++
++Gssctxt *gss_kex_context = NULL;
++
++static ssh_gss_kex_mapping *gss_enc2oid = NULL;
++
++int 
++ssh_gssapi_oid_table_ok() {
++      return (gss_enc2oid != NULL);
++}
++
++/*
++ * Return a list of the gss-group1-sha1 mechanisms supported by this program
++ *
++ * We test mechanisms to ensure that we can use them, to avoid starting
++ * a key exchange with a bad mechanism
++ */
++
++char *
++ssh_gssapi_client_mechanisms(const char *host, const char *client) {
++      gss_OID_set gss_supported;
++      OM_uint32 min_status;
++
++      if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
++              return NULL;
++
++      return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
++          host, client));
++}
++
++char *
++ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
++    const char *host, const char *client) {
++      Buffer buf;
++      size_t i;
++      int oidpos, enclen;
++      char *mechs, *encoded;
++      u_char digest[EVP_MAX_MD_SIZE];
++      char deroid[2];
++      const EVP_MD *evp_md = EVP_md5();
++      EVP_MD_CTX md;
++
++      if (gss_enc2oid != NULL) {
++              for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
++                      xfree(gss_enc2oid[i].encoded);
++              xfree(gss_enc2oid);
++      }
++
++      gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
++          (gss_supported->count + 1));
++
++      buffer_init(&buf);
++
++      oidpos = 0;
++      for (i = 0; i < gss_supported->count; i++) {
++              if (gss_supported->elements[i].length < 128 &&
++                  (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
++
++                      deroid[0] = SSH_GSS_OIDTYPE;
++                      deroid[1] = gss_supported->elements[i].length;
++
++                      EVP_DigestInit(&md, evp_md);
++                      EVP_DigestUpdate(&md, deroid, 2);
++                      EVP_DigestUpdate(&md,
++                          gss_supported->elements[i].elements,
++                          gss_supported->elements[i].length);
++                      EVP_DigestFinal(&md, digest, NULL);
++
++                      encoded = xmalloc(EVP_MD_size(evp_md) * 2);
++                      enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
++                          encoded, EVP_MD_size(evp_md) * 2);
++
++                      if (oidpos != 0)
++                              buffer_put_char(&buf, ',');
++
++                      buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
++                          sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
++                      buffer_append(&buf, encoded, enclen);
++                      buffer_put_char(&buf, ',');
++                      buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
++                          sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
++                      buffer_append(&buf, encoded, enclen);
++                      buffer_put_char(&buf, ',');
++                      buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
++                          sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
++                      buffer_append(&buf, encoded, enclen);
++
++                      gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
++                      gss_enc2oid[oidpos].encoded = encoded;
++                      oidpos++;
++              }
++      }
++      gss_enc2oid[oidpos].oid = NULL;
++      gss_enc2oid[oidpos].encoded = NULL;
++
++      buffer_put_char(&buf, '\0');
++
++      mechs = xmalloc(buffer_len(&buf));
++      buffer_get(&buf, mechs, buffer_len(&buf));
++      buffer_free(&buf);
++
++      if (strlen(mechs) == 0) {
++              xfree(mechs);
++              mechs = NULL;
++      }
++      
++      return (mechs);
++}
++
++gss_OID
++ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
++      int i = 0;
++      
++      switch (kex_type) {
++      case KEX_GSS_GRP1_SHA1:
++              if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
++                      return GSS_C_NO_OID;
++              name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
++              break;
++      case KEX_GSS_GRP14_SHA1:
++              if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
++                      return GSS_C_NO_OID;
++              name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
++              break;
++      case KEX_GSS_GEX_SHA1:
++              if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
++                      return GSS_C_NO_OID;
++              name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
++              break;
++      default:
++              return GSS_C_NO_OID;
++      }
++
++      while (gss_enc2oid[i].encoded != NULL &&
++          strcmp(name, gss_enc2oid[i].encoded) != 0)
++              i++;
++
++      if (gss_enc2oid[i].oid != NULL && ctx != NULL)
++              ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
++
++      return gss_enc2oid[i].oid;
++}
++
+ /* Check that the OID in a data stream matches that in the context */
+ int
+ ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
+@@ -197,7 +352,7 @@
+       }
+       ctx->major = gss_init_sec_context(&ctx->minor,
+-          GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
++          ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
+           GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
+           0, NULL, recv_tok, NULL, send_tok, flags, NULL);
+@@ -227,8 +382,42 @@
+ }
+ OM_uint32
++ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
++{
++      gss_buffer_desc gssbuf;
++      gss_name_t gssname;
++      OM_uint32 status;
++      gss_OID_set oidset;
++
++      gssbuf.value = (void *) name;
++      gssbuf.length = strlen(gssbuf.value);
++
++      gss_create_empty_oid_set(&status, &oidset);
++      gss_add_oid_set_member(&status, ctx->oid, &oidset);
++
++      ctx->major = gss_import_name(&ctx->minor, &gssbuf,
++          GSS_C_NT_USER_NAME, &gssname);
++
++      if (!ctx->major)
++              ctx->major = gss_acquire_cred(&ctx->minor, 
++                  gssname, 0, oidset, GSS_C_INITIATE, 
++                  &ctx->client_creds, NULL, NULL);
++
++      gss_release_name(&status, &gssname);
++      gss_release_oid_set(&status, &oidset);
++
++      if (ctx->major)
++              ssh_gssapi_error(ctx);
++
++      return(ctx->major);
++}
++
++OM_uint32
+ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
+ {
++      if (ctx == NULL) 
++              return -1;
++
+       if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
+           GSS_C_QOP_DEFAULT, buffer, hash)))
+               ssh_gssapi_error(ctx);
+@@ -236,6 +425,19 @@
+       return (ctx->major);
+ }
++/* Priviledged when used by server */
++OM_uint32
++ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
++{
++      if (ctx == NULL)
++              return -1;
++
++      ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
++          gssbuf, gssmic, NULL);
++
++      return (ctx->major);
++}
++
+ void
+ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
+     const char *context)
+@@ -249,11 +451,16 @@
+ }
+ int
+-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
++ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 
++    const char *client)
+ {
+       gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
++      Gssctxt *intctx = NULL;
++
++      if (ctx == NULL)
++              ctx = &intctx;
+       /* RFC 4462 says we MUST NOT do SPNEGO */
+       if (oid->length == spnego_oid.length && 
+@@ -263,6 +470,10 @@
+       ssh_gssapi_build_ctx(ctx);
+       ssh_gssapi_set_oid(*ctx, oid);
+       major = ssh_gssapi_import_name(*ctx, host);
++
++      if (!GSS_ERROR(major) && client)
++              major = ssh_gssapi_client_identity(*ctx, client);
++
+       if (!GSS_ERROR(major)) {
+               major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
+                   NULL);
+@@ -272,10 +483,67 @@
+                           GSS_C_NO_BUFFER);
+       }
+-      if (GSS_ERROR(major)) 
++      if (GSS_ERROR(major) || intctx != NULL) 
+               ssh_gssapi_delete_ctx(ctx);
+       return (!GSS_ERROR(major));
+ }
++int
++ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
++      static gss_name_t saved_name = GSS_C_NO_NAME;
++      static OM_uint32 saved_lifetime = 0;
++      static gss_OID saved_mech = GSS_C_NO_OID;
++      static gss_name_t name;
++      static OM_uint32 last_call = 0;
++      OM_uint32 lifetime, now, major, minor;
++      int equal;
++      gss_cred_usage_t usage = GSS_C_INITIATE;
++      
++      now = time(NULL);
++
++      if (ctxt) {
++              debug("Rekey has happened - updating saved versions");
++
++              if (saved_name != GSS_C_NO_NAME)
++                      gss_release_name(&minor, &saved_name);
++
++              major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
++                  &saved_name, &saved_lifetime, NULL, NULL);
++
++              if (!GSS_ERROR(major)) {
++                      saved_mech = ctxt->oid;
++                      saved_lifetime+= now;
++              } else {
++                      /* Handle the error */
++              }
++              return 0;
++      }
++
++      if (now - last_call < 10)
++              return 0;
++
++      last_call = now;
++
++      if (saved_mech == GSS_C_NO_OID)
++              return 0;
++      
++      major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 
++          &name, &lifetime, NULL, NULL);
++      if (major == GSS_S_CREDENTIALS_EXPIRED)
++              return 0;
++      else if (GSS_ERROR(major))
++              return 0;
++
++      major = gss_compare_name(&minor, saved_name, name, &equal);
++      gss_release_name(&minor, &name);
++      if (GSS_ERROR(major))
++              return 0;
++
++      if (equal && (saved_lifetime < lifetime + now - 10))
++              return 1;
++
++      return 0;
++}
++
+ #endif /* GSSAPI */
+Index: b/gss-serv-krb5.c
+===================================================================
+--- a/gss-serv-krb5.c
++++ b/gss-serv-krb5.c
+@@ -1,7 +1,7 @@
+ /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
+ /*
+- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -120,6 +120,7 @@
+       krb5_principal princ;
+       OM_uint32 maj_status, min_status;
+       int len;
++      const char *new_ccname;
+       if (client->creds == NULL) {
+               debug("No credentials stored");
+@@ -168,11 +169,16 @@
+               return;
+       }
+-      client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
++      new_ccname = krb5_cc_get_name(krb_context, ccache);
++
+       client->store.envvar = "KRB5CCNAME";
+-      len = strlen(client->store.filename) + 6;
+-      client->store.envval = xmalloc(len);
+-      snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
++#ifdef USE_CCAPI
++      xasprintf(&client->store.envval, "API:%s", new_ccname);
++      client->store.filename = NULL;
++#else
++      xasprintf(&client->store.envval, "FILE:%s", new_ccname);
++      client->store.filename = xstrdup(new_ccname);
++#endif
+ #ifdef USE_PAM
+       if (options.use_pam)
+@@ -184,6 +190,71 @@
+       return;
+ }
++int
++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 
++    ssh_gssapi_client *client)
++{
++      krb5_ccache ccache = NULL;
++      krb5_principal principal = NULL;
++      char *name = NULL;
++      krb5_error_code problem;
++      OM_uint32 maj_status, min_status;
++
++      if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
++                logit("krb5_cc_resolve(): %.100s",
++                    krb5_get_err_text(krb_context, problem));
++                return 0;
++              }
++      
++      /* Find out who the principal in this cache is */
++      if ((problem = krb5_cc_get_principal(krb_context, ccache, 
++          &principal))) {
++              logit("krb5_cc_get_principal(): %.100s",
++                  krb5_get_err_text(krb_context, problem));
++              krb5_cc_close(krb_context, ccache);
++              return 0;
++      }
++
++      if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
++              logit("krb5_unparse_name(): %.100s",
++                  krb5_get_err_text(krb_context, problem));
++              krb5_free_principal(krb_context, principal);
++              krb5_cc_close(krb_context, ccache);
++              return 0;
++      }
++
++
++      if (strcmp(name,client->exportedname.value)!=0) {
++              debug("Name in local credentials cache differs. Not storing");
++              krb5_free_principal(krb_context, principal);
++              krb5_cc_close(krb_context, ccache);
++              krb5_free_unparsed_name(krb_context, name);
++              return 0;
++      }
++      krb5_free_unparsed_name(krb_context, name);
++
++      /* Name matches, so lets get on with it! */
++
++      if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
++              logit("krb5_cc_initialize(): %.100s",
++                  krb5_get_err_text(krb_context, problem));
++              krb5_free_principal(krb_context, principal);
++              krb5_cc_close(krb_context, ccache);
++              return 0;
++      }
++
++      krb5_free_principal(krb_context, principal);
++
++      if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
++          ccache))) {
++              logit("gss_krb5_copy_ccache() failed. Sorry!");
++              krb5_cc_close(krb_context, ccache);
++              return 0;
++      }
++
++      return 1;
++}
++
+ ssh_gssapi_mech gssapi_kerberos_mech = {
+       "toWM5Slw5Ew8Mqkay+al2g==",
+       "Kerberos",
+@@ -191,7 +262,8 @@
+       NULL,
+       &ssh_gssapi_krb5_userok,
+       NULL,
+-      &ssh_gssapi_krb5_storecreds
++      &ssh_gssapi_krb5_storecreds,
++      &ssh_gssapi_krb5_updatecreds
+ };
+ #endif /* KRB5 */
+Index: b/gss-serv.c
+===================================================================
+--- a/gss-serv.c
++++ b/gss-serv.c
+@@ -1,7 +1,7 @@
+ /* $OpenBSD: gss-serv.c,v 1.23 2011/08/01 19:18:15 markus Exp $ */
+ /*
+- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -45,15 +45,20 @@
+ #include "channels.h"
+ #include "session.h"
+ #include "misc.h"
++#include "servconf.h"
++#include "uidswap.h"
+ #include "ssh-gss.h"
++#include "monitor_wrap.h"
++
++extern ServerOptions options;
+ static ssh_gssapi_client gssapi_client =
+     { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
+-    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
++    GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,  NULL, {NULL, NULL, NULL}, 0, 0};
+ ssh_gssapi_mech gssapi_null_mech =
+-    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
++    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
+ #ifdef KRB5
+ extern ssh_gssapi_mech gssapi_kerberos_mech;
+@@ -81,25 +86,32 @@
+       char lname[MAXHOSTNAMELEN];
+       gss_OID_set oidset;
+-      gss_create_empty_oid_set(&status, &oidset);
+-      gss_add_oid_set_member(&status, ctx->oid, &oidset);
++      if (options.gss_strict_acceptor) {
++              gss_create_empty_oid_set(&status, &oidset);
++              gss_add_oid_set_member(&status, ctx->oid, &oidset);
++
++              if (gethostname(lname, MAXHOSTNAMELEN)) {
++                      gss_release_oid_set(&status, &oidset);
++                      return (-1);
++              }
+-      if (gethostname(lname, MAXHOSTNAMELEN)) {
+-              gss_release_oid_set(&status, &oidset);
+-              return (-1);
+-      }
++              if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
++                      gss_release_oid_set(&status, &oidset);
++                      return (ctx->major);
++              }
++
++              if ((ctx->major = gss_acquire_cred(&ctx->minor,
++                  ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, 
++                  NULL, NULL)))
++                      ssh_gssapi_error(ctx);
+-      if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
+               gss_release_oid_set(&status, &oidset);
+               return (ctx->major);
++      } else {
++              ctx->name = GSS_C_NO_NAME;
++              ctx->creds = GSS_C_NO_CREDENTIAL;
+       }
+-
+-      if ((ctx->major = gss_acquire_cred(&ctx->minor,
+-          ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL)))
+-              ssh_gssapi_error(ctx);
+-
+-      gss_release_oid_set(&status, &oidset);
+-      return (ctx->major);
++      return GSS_S_COMPLETE;
+ }
+ /* Privileged */
+@@ -114,6 +126,29 @@
+ }
+ /* Unprivileged */
++char *
++ssh_gssapi_server_mechanisms() {
++      gss_OID_set     supported;
++
++      ssh_gssapi_supported_oids(&supported);
++      return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
++          NULL, NULL));
++}
++
++/* Unprivileged */
++int
++ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
++    const char *dummy) {
++      Gssctxt *ctx = NULL;
++      int res;
++ 
++      res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
++      ssh_gssapi_delete_ctx(&ctx);
++
++      return (res);
++}
++
++/* Unprivileged */
+ void
+ ssh_gssapi_supported_oids(gss_OID_set *oidset)
+ {
+@@ -123,7 +158,9 @@
+       gss_OID_set supported;
+       gss_create_empty_oid_set(&min_status, oidset);
+-      gss_indicate_mechs(&min_status, &supported);
++
++      if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
++              return;
+       while (supported_mechs[i]->name != NULL) {
+               if (GSS_ERROR(gss_test_oid_set_member(&min_status,
+@@ -249,8 +286,48 @@
+ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
+ {
+       int i = 0;
++      int equal = 0;
++      gss_name_t new_name = GSS_C_NO_NAME;
++      gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
++
++      if (options.gss_store_rekey && client->used && ctx->client_creds) {
++              if (client->mech->oid.length != ctx->oid->length ||
++                  (memcmp(client->mech->oid.elements,
++                   ctx->oid->elements, ctx->oid->length) !=0)) {
++                      debug("Rekeyed credentials have different mechanism");
++                      return GSS_S_COMPLETE;
++              }
++
++              if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 
++                  ctx->client_creds, ctx->oid, &new_name, 
++                  NULL, NULL, NULL))) {
++                      ssh_gssapi_error(ctx);
++                      return (ctx->major);
++              }
++
++              ctx->major = gss_compare_name(&ctx->minor, client->name, 
++                  new_name, &equal);
+-      gss_buffer_desc ename;
++              if (GSS_ERROR(ctx->major)) {
++                      ssh_gssapi_error(ctx);
++                      return (ctx->major);
++              }
++ 
++              if (!equal) {
++                      debug("Rekeyed credentials have different name");
++                      return GSS_S_COMPLETE;
++              }
++
++              debug("Marking rekeyed credentials for export");
++
++              gss_release_name(&ctx->minor, &client->name);
++              gss_release_cred(&ctx->minor, &client->creds);
++              client->name = new_name;
++              client->creds = ctx->client_creds;
++              ctx->client_creds = GSS_C_NO_CREDENTIAL;
++              client->updated = 1;
++              return GSS_S_COMPLETE;
++      }
+       client->mech = NULL;
+@@ -265,6 +342,13 @@
+       if (client->mech == NULL)
+               return GSS_S_FAILURE;
++      if (ctx->client_creds &&
++          (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
++           ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
++              ssh_gssapi_error(ctx);
++              return (ctx->major);
++      }
++
+       if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
+           &client->displayname, NULL))) {
+               ssh_gssapi_error(ctx);
+@@ -282,6 +366,8 @@
+               return (ctx->major);
+       }
++      gss_release_buffer(&ctx->minor, &ename);
++
+       /* We can't copy this structure, so we just move the pointer to it */
+       client->creds = ctx->client_creds;
+       ctx->client_creds = GSS_C_NO_CREDENTIAL;
+@@ -329,7 +415,7 @@
+ /* Privileged */
+ int
+-ssh_gssapi_userok(char *user)
++ssh_gssapi_userok(char *user, struct passwd *pw)
+ {
+       OM_uint32 lmin;
+@@ -339,9 +425,11 @@
+               return 0;
+       }
+       if (gssapi_client.mech && gssapi_client.mech->userok)
+-              if ((*gssapi_client.mech->userok)(&gssapi_client, user))
++              if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
++                      gssapi_client.used = 1;
++                      gssapi_client.store.owner = pw;
+                       return 1;
+-              else {
++              } else {
+                       /* Destroy delegated credentials if userok fails */
+                       gss_release_buffer(&lmin, &gssapi_client.displayname);
+                       gss_release_buffer(&lmin, &gssapi_client.exportedname);
+@@ -354,14 +442,90 @@
+       return (0);
+ }
+-/* Privileged */
+-OM_uint32
+-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
++/* These bits are only used for rekeying. The unpriviledged child is running 
++ * as the user, the monitor is root.
++ *
++ * In the child, we want to :
++ *    *) Ask the monitor to store our credentials into the store we specify
++ *    *) If it succeeds, maybe do a PAM update
++ */
++
++/* Stuff for PAM */
++
++#ifdef USE_PAM
++static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 
++    struct pam_response **resp, void *data)
+ {
+-      ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+-          gssbuf, gssmic, NULL);
++      return (PAM_CONV_ERR);
++}
++#endif
+-      return (ctx->major);
++void
++ssh_gssapi_rekey_creds() {
++      int ok;
++      int ret;
++#ifdef USE_PAM
++      pam_handle_t *pamh = NULL;
++      struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
++      char *envstr;
++#endif
++
++      if (gssapi_client.store.filename == NULL && 
++          gssapi_client.store.envval == NULL &&
++          gssapi_client.store.envvar == NULL)
++              return;
++ 
++      ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
++
++      if (!ok)
++              return;
++
++      debug("Rekeyed credentials stored successfully");
++
++      /* Actually managing to play with the ssh pam stack from here will
++       * be next to impossible. In any case, we may want different options
++       * for rekeying. So, use our own :)
++       */
++#ifdef USE_PAM        
++      if (!use_privsep) {
++              debug("Not even going to try and do PAM with privsep disabled");
++              return;
++      }
++
++      ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
++          &pamconv, &pamh);
++      if (ret)
++              return;
++
++      xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 
++          gssapi_client.store.envval);
++
++      ret = pam_putenv(pamh, envstr);
++      if (!ret)
++              pam_setcred(pamh, PAM_REINITIALIZE_CRED);
++      pam_end(pamh, PAM_SUCCESS);
++#endif
++}
++
++int 
++ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
++      int ok = 0;
++
++      /* Check we've got credentials to store */
++      if (!gssapi_client.updated)
++              return 0;
++
++      gssapi_client.updated = 0;
++
++      temporarily_use_uid(gssapi_client.store.owner);
++      if (gssapi_client.mech && gssapi_client.mech->updatecreds)
++              ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
++      else
++              debug("No update function for this mechanism");
++
++      restore_uid();
++
++      return ok;
+ }
+ #endif
+Index: b/kex.c
+===================================================================
+--- a/kex.c
++++ b/kex.c
+@@ -50,6 +50,10 @@
+ #include "monitor.h"
+ #include "roaming.h"
++#ifdef GSSAPI
++#include "ssh-gss.h"
++#endif
++
+ #if OPENSSL_VERSION_NUMBER >= 0x00907000L
+ # if defined(HAVE_EVP_SHA256)
+ # define evp_ssh_sha256 EVP_sha256
+@@ -358,6 +362,20 @@
+               k->kex_type = KEX_ECDH_SHA2;
+               k->evp_md = kex_ecdh_name_to_evpmd(k->name);
+ #endif
++#ifdef GSSAPI
++      } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
++          sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
++              k->kex_type = KEX_GSS_GEX_SHA1;
++              k->evp_md = EVP_sha1();
++      } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
++          sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
++              k->kex_type = KEX_GSS_GRP1_SHA1;
++              k->evp_md = EVP_sha1();
++      } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
++          sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
++              k->kex_type = KEX_GSS_GRP14_SHA1;
++              k->evp_md = EVP_sha1();
++#endif
+       } else
+               fatal("bad kex alg %s", k->name);
+ }
+Index: b/kex.h
+===================================================================
+--- a/kex.h
++++ b/kex.h
+@@ -73,6 +73,9 @@
+       KEX_DH_GEX_SHA1,
+       KEX_DH_GEX_SHA256,
+       KEX_ECDH_SHA2,
++      KEX_GSS_GRP1_SHA1,
++      KEX_GSS_GRP14_SHA1,
++      KEX_GSS_GEX_SHA1,
+       KEX_MAX
+ };
+@@ -129,6 +132,12 @@
+       sig_atomic_t done;
+       int     flags;
+       const EVP_MD *evp_md;
++#ifdef GSSAPI
++      int     gss_deleg_creds;
++      int     gss_trust_dns;
++      char    *gss_host;
++      char    *gss_client;
++#endif
+       char    *client_version_string;
+       char    *server_version_string;
+       int     (*verify_host_key)(Key *);
+@@ -156,6 +165,11 @@
+ void   kexecdh_client(Kex *);
+ void   kexecdh_server(Kex *);
++#ifdef GSSAPI
++void  kexgss_client(Kex *);
++void  kexgss_server(Kex *);
++#endif
++
+ void
+ kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
+     BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
+Index: b/kexgssc.c
+===================================================================
+--- /dev/null
++++ b/kexgssc.c
+@@ -0,0 +1,334 @@
++/*
++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "includes.h"
++
++#ifdef GSSAPI
++
++#include "includes.h"
++
++#include <openssl/crypto.h>
++#include <openssl/bn.h>
++
++#include <string.h>
++
++#include "xmalloc.h"
++#include "buffer.h"
++#include "ssh2.h"
++#include "key.h"
++#include "cipher.h"
++#include "kex.h"
++#include "log.h"
++#include "packet.h"
++#include "dh.h"
++
++#include "ssh-gss.h"
++
++void
++kexgss_client(Kex *kex) {
++      gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
++      gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
++      Gssctxt *ctxt;
++      OM_uint32 maj_status, min_status, ret_flags;
++      u_int klen, kout, slen = 0, hashlen, strlen;
++      DH *dh; 
++      BIGNUM *dh_server_pub = NULL;
++      BIGNUM *shared_secret = NULL;
++      BIGNUM *p = NULL;
++      BIGNUM *g = NULL;       
++      u_char *kbuf, *hash;
++      u_char *serverhostkey = NULL;
++      u_char *empty = "";
++      char *msg;
++      char *lang;
++      int type = 0;
++      int first = 1;
++      int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
++
++      /* Initialise our GSSAPI world */       
++      ssh_gssapi_build_ctx(&ctxt);
++      if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) 
++          == GSS_C_NO_OID)
++              fatal("Couldn't identify host exchange");
++
++      if (ssh_gssapi_import_name(ctxt, kex->gss_host))
++              fatal("Couldn't import hostname");
++
++      if (kex->gss_client && 
++          ssh_gssapi_client_identity(ctxt, kex->gss_client))
++              fatal("Couldn't acquire client credentials");
++
++      switch (kex->kex_type) {
++      case KEX_GSS_GRP1_SHA1:
++              dh = dh_new_group1();
++              break;
++      case KEX_GSS_GRP14_SHA1:
++              dh = dh_new_group14();
++              break;
++      case KEX_GSS_GEX_SHA1:
++              debug("Doing group exchange\n");
++              nbits = dh_estimate(kex->we_need * 8);
++              packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
++              packet_put_int(min);
++              packet_put_int(nbits);
++              packet_put_int(max);
++
++              packet_send();
++
++              packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
++
++              if ((p = BN_new()) == NULL)
++                      fatal("BN_new() failed");
++              packet_get_bignum2(p);
++              if ((g = BN_new()) == NULL)
++                      fatal("BN_new() failed");
++              packet_get_bignum2(g);
++              packet_check_eom();
++
++              if (BN_num_bits(p) < min || BN_num_bits(p) > max)
++                      fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
++                          min, BN_num_bits(p), max);
++
++              dh = dh_new_group(g, p);
++              break;
++      default:
++              fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
++      }
++      
++      /* Step 1 - e is dh->pub_key */
++      dh_gen_key(dh, kex->we_need * 8);
++
++      /* This is f, we initialise it now to make life easier */
++      dh_server_pub = BN_new();
++      if (dh_server_pub == NULL)
++              fatal("dh_server_pub == NULL");
++
++      token_ptr = GSS_C_NO_BUFFER;
++                       
++      do {
++              debug("Calling gss_init_sec_context");
++              
++              maj_status = ssh_gssapi_init_ctx(ctxt,
++                  kex->gss_deleg_creds, token_ptr, &send_tok,
++                  &ret_flags);
++
++              if (GSS_ERROR(maj_status)) {
++                      if (send_tok.length != 0) {
++                              packet_start(SSH2_MSG_KEXGSS_CONTINUE);
++                              packet_put_string(send_tok.value,
++                                  send_tok.length);
++                      }
++                      fatal("gss_init_context failed");
++              }
++
++              /* If we've got an old receive buffer get rid of it */
++              if (token_ptr != GSS_C_NO_BUFFER)
++                      xfree(recv_tok.value);
++
++              if (maj_status == GSS_S_COMPLETE) {
++                      /* If mutual state flag is not true, kex fails */
++                      if (!(ret_flags & GSS_C_MUTUAL_FLAG))
++                              fatal("Mutual authentication failed");
++
++                      /* If integ avail flag is not true kex fails */
++                      if (!(ret_flags & GSS_C_INTEG_FLAG))
++                              fatal("Integrity check failed");
++              }
++
++              /* 
++               * If we have data to send, then the last message that we
++               * received cannot have been a 'complete'. 
++               */
++              if (send_tok.length != 0) {
++                      if (first) {
++                              packet_start(SSH2_MSG_KEXGSS_INIT);
++                              packet_put_string(send_tok.value,
++                                  send_tok.length);
++                              packet_put_bignum2(dh->pub_key);
++                              first = 0;
++                      } else {
++                              packet_start(SSH2_MSG_KEXGSS_CONTINUE);
++                              packet_put_string(send_tok.value,
++                                  send_tok.length);
++                      }
++                      packet_send();
++                      gss_release_buffer(&min_status, &send_tok);
++
++                      /* If we've sent them data, they should reply */
++                      do {    
++                              type = packet_read();
++                              if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
++                                      debug("Received KEXGSS_HOSTKEY");
++                                      if (serverhostkey)
++                                              fatal("Server host key received more than once");
++                                      serverhostkey = 
++                                          packet_get_string(&slen);
++                              }
++                      } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
++
++                      switch (type) {
++                      case SSH2_MSG_KEXGSS_CONTINUE:
++                              debug("Received GSSAPI_CONTINUE");
++                              if (maj_status == GSS_S_COMPLETE) 
++                                      fatal("GSSAPI Continue received from server when complete");
++                              recv_tok.value = packet_get_string(&strlen);
++                              recv_tok.length = strlen; 
++                              break;
++                      case SSH2_MSG_KEXGSS_COMPLETE:
++                              debug("Received GSSAPI_COMPLETE");
++                              packet_get_bignum2(dh_server_pub);
++                              msg_tok.value =  packet_get_string(&strlen);
++                              msg_tok.length = strlen; 
++
++                              /* Is there a token included? */
++                              if (packet_get_char()) {
++                                      recv_tok.value=
++                                          packet_get_string(&strlen);
++                                      recv_tok.length = strlen;
++                                      /* If we're already complete - protocol error */
++                                      if (maj_status == GSS_S_COMPLETE)
++                                              packet_disconnect("Protocol error: received token when complete");
++                                      } else {
++                                              /* No token included */
++                                              if (maj_status != GSS_S_COMPLETE)
++                                                      packet_disconnect("Protocol error: did not receive final token");
++                              }
++                              break;
++                      case SSH2_MSG_KEXGSS_ERROR:
++                              debug("Received Error");
++                              maj_status = packet_get_int();
++                              min_status = packet_get_int();
++                              msg = packet_get_string(NULL);
++                              lang = packet_get_string(NULL);
++                              fatal("GSSAPI Error: \n%.400s",msg);
++                      default:
++                              packet_disconnect("Protocol error: didn't expect packet type %d",
++                              type);
++                      }
++                      token_ptr = &recv_tok;
++              } else {
++                      /* No data, and not complete */
++                      if (maj_status != GSS_S_COMPLETE)
++                              fatal("Not complete, and no token output");
++              }
++      } while (maj_status & GSS_S_CONTINUE_NEEDED);
++
++      /* 
++       * We _must_ have received a COMPLETE message in reply from the 
++       * server, which will have set dh_server_pub and msg_tok 
++       */
++
++      if (type != SSH2_MSG_KEXGSS_COMPLETE)
++              fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
++
++      /* Check f in range [1, p-1] */
++      if (!dh_pub_is_valid(dh, dh_server_pub))
++              packet_disconnect("bad server public DH value");
++
++      /* compute K=f^x mod p */
++      klen = DH_size(dh);
++      kbuf = xmalloc(klen);
++      kout = DH_compute_key(kbuf, dh_server_pub, dh);
++      if (kout < 0)
++              fatal("DH_compute_key: failed");
++
++      shared_secret = BN_new();
++      if (shared_secret == NULL)
++              fatal("kexgss_client: BN_new failed");
++
++      if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
++              fatal("kexdh_client: BN_bin2bn failed");
++
++      memset(kbuf, 0, klen);
++      xfree(kbuf);
++
++      switch (kex->kex_type) {
++      case KEX_GSS_GRP1_SHA1:
++      case KEX_GSS_GRP14_SHA1:
++              kex_dh_hash( kex->client_version_string, 
++                  kex->server_version_string,
++                  buffer_ptr(&kex->my), buffer_len(&kex->my),
++                  buffer_ptr(&kex->peer), buffer_len(&kex->peer),
++                  (serverhostkey ? serverhostkey : empty), slen,
++                  dh->pub_key,        /* e */
++                  dh_server_pub,      /* f */
++                  shared_secret,      /* K */
++                  &hash, &hashlen
++              );
++              break;
++      case KEX_GSS_GEX_SHA1:
++              kexgex_hash(
++                  kex->evp_md,
++                  kex->client_version_string,
++                  kex->server_version_string,
++                  buffer_ptr(&kex->my), buffer_len(&kex->my),
++                  buffer_ptr(&kex->peer), buffer_len(&kex->peer),
++                  (serverhostkey ? serverhostkey : empty), slen,
++                  min, nbits, max,
++                  dh->p, dh->g,
++                  dh->pub_key,
++                  dh_server_pub,
++                  shared_secret,
++                  &hash, &hashlen
++              );
++              break;
++      default:
++              fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
++      }
++
++      gssbuf.value = hash;
++      gssbuf.length = hashlen;
++
++      /* Verify that the hash matches the MIC we just got. */
++      if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
++              packet_disconnect("Hash's MIC didn't verify");
++
++      xfree(msg_tok.value);
++
++      DH_free(dh);
++      if (serverhostkey)
++              xfree(serverhostkey);
++      BN_clear_free(dh_server_pub);
++
++      /* save session id */
++      if (kex->session_id == NULL) {
++              kex->session_id_len = hashlen;
++              kex->session_id = xmalloc(kex->session_id_len);
++              memcpy(kex->session_id, hash, kex->session_id_len);
++      }
++
++      if (kex->gss_deleg_creds)
++              ssh_gssapi_credentials_updated(ctxt);
++
++      if (gss_kex_context == NULL)
++              gss_kex_context = ctxt;
++      else
++              ssh_gssapi_delete_ctx(&ctxt);
++
++      kex_derive_keys(kex, hash, hashlen, shared_secret);
++      BN_clear_free(shared_secret);
++      kex_finish(kex);
++}
++
++#endif /* GSSAPI */
+Index: b/kexgsss.c
+===================================================================
+--- /dev/null
++++ b/kexgsss.c
+@@ -0,0 +1,288 @@
++/*
++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "includes.h"
++
++#ifdef GSSAPI
++
++#include <string.h>
++
++#include <openssl/crypto.h>
++#include <openssl/bn.h>
++
++#include "xmalloc.h"
++#include "buffer.h"
++#include "ssh2.h"
++#include "key.h"
++#include "cipher.h"
++#include "kex.h"
++#include "log.h"
++#include "packet.h"
++#include "dh.h"
++#include "ssh-gss.h"
++#include "monitor_wrap.h"
++#include "servconf.h"
++
++extern ServerOptions options;
++
++void
++kexgss_server(Kex *kex)
++{
++      OM_uint32 maj_status, min_status;
++      
++      /* 
++       * Some GSSAPI implementations use the input value of ret_flags (an
++       * output variable) as a means of triggering mechanism specific 
++       * features. Initializing it to zero avoids inadvertently 
++       * activating this non-standard behaviour.
++       */
++
++      OM_uint32 ret_flags = 0;
++      gss_buffer_desc gssbuf, recv_tok, msg_tok;
++      gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
++      Gssctxt *ctxt = NULL;
++      u_int slen, klen, kout, hashlen;
++      u_char *kbuf, *hash;
++      DH *dh;
++      int min = -1, max = -1, nbits = -1;
++      BIGNUM *shared_secret = NULL;
++      BIGNUM *dh_client_pub = NULL;
++      int type = 0;
++      gss_OID oid;
++      char *mechs;
++
++      /* Initialise GSSAPI */
++
++      /* If we're rekeying, privsep means that some of the private structures
++       * in the GSSAPI code are no longer available. This kludges them back
++       * into life
++       */
++      if (!ssh_gssapi_oid_table_ok()) 
++              if ((mechs = ssh_gssapi_server_mechanisms()))
++                      xfree(mechs);
++
++      debug2("%s: Identifying %s", __func__, kex->name);
++      oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
++      if (oid == GSS_C_NO_OID)
++         fatal("Unknown gssapi mechanism");
++
++      debug2("%s: Acquiring credentials", __func__);
++
++      if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
++              fatal("Unable to acquire credentials for the server");
++
++      switch (kex->kex_type) {
++      case KEX_GSS_GRP1_SHA1:
++              dh = dh_new_group1();
++              break;
++      case KEX_GSS_GRP14_SHA1:
++              dh = dh_new_group14();
++              break;
++      case KEX_GSS_GEX_SHA1:
++              debug("Doing group exchange");
++              packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
++              min = packet_get_int();
++              nbits = packet_get_int();
++              max = packet_get_int();
++              min = MAX(DH_GRP_MIN, min);
++              max = MIN(DH_GRP_MAX, max);
++              packet_check_eom();
++              if (max < min || nbits < min || max < nbits)
++                      fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
++                          min, nbits, max);
++              dh = PRIVSEP(choose_dh(min, nbits, max));
++              if (dh == NULL)
++                      packet_disconnect("Protocol error: no matching group found");
++
++              packet_start(SSH2_MSG_KEXGSS_GROUP);
++              packet_put_bignum2(dh->p);
++              packet_put_bignum2(dh->g);
++              packet_send();
++
++              packet_write_wait();
++              break;
++      default:
++              fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
++      }
++
++      dh_gen_key(dh, kex->we_need * 8);
++
++      do {
++              debug("Wait SSH2_MSG_GSSAPI_INIT");
++              type = packet_read();
++              switch(type) {
++              case SSH2_MSG_KEXGSS_INIT:
++                      if (dh_client_pub != NULL) 
++                              fatal("Received KEXGSS_INIT after initialising");
++                      recv_tok.value = packet_get_string(&slen);
++                      recv_tok.length = slen; 
++
++                      if ((dh_client_pub = BN_new()) == NULL)
++                              fatal("dh_client_pub == NULL");
++
++                      packet_get_bignum2(dh_client_pub);
++
++                      /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
++                      break;
++              case SSH2_MSG_KEXGSS_CONTINUE:
++                      recv_tok.value = packet_get_string(&slen);
++                      recv_tok.length = slen; 
++                      break;
++              default:
++                      packet_disconnect(
++                          "Protocol error: didn't expect packet type %d",
++                          type);
++              }
++
++              maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
++                  &send_tok, &ret_flags));
++
++              xfree(recv_tok.value);
++
++              if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
++                      fatal("Zero length token output when incomplete");
++
++              if (dh_client_pub == NULL)
++                      fatal("No client public key");
++              
++              if (maj_status & GSS_S_CONTINUE_NEEDED) {
++                      debug("Sending GSSAPI_CONTINUE");
++                      packet_start(SSH2_MSG_KEXGSS_CONTINUE);
++                      packet_put_string(send_tok.value, send_tok.length);
++                      packet_send();
++                      gss_release_buffer(&min_status, &send_tok);
++              }
++      } while (maj_status & GSS_S_CONTINUE_NEEDED);
++
++      if (GSS_ERROR(maj_status)) {
++              if (send_tok.length > 0) {
++                      packet_start(SSH2_MSG_KEXGSS_CONTINUE);
++                      packet_put_string(send_tok.value, send_tok.length);
++                      packet_send();
++              }
++              fatal("accept_ctx died");
++      }
++
++      if (!(ret_flags & GSS_C_MUTUAL_FLAG))
++              fatal("Mutual Authentication flag wasn't set");
++
++      if (!(ret_flags & GSS_C_INTEG_FLAG))
++              fatal("Integrity flag wasn't set");
++      
++      if (!dh_pub_is_valid(dh, dh_client_pub))
++              packet_disconnect("bad client public DH value");
++
++      klen = DH_size(dh);
++      kbuf = xmalloc(klen); 
++      kout = DH_compute_key(kbuf, dh_client_pub, dh);
++      if (kout < 0)
++              fatal("DH_compute_key: failed");
++
++      shared_secret = BN_new();
++      if (shared_secret == NULL)
++              fatal("kexgss_server: BN_new failed");
++
++      if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
++              fatal("kexgss_server: BN_bin2bn failed");
++
++      memset(kbuf, 0, klen);
++      xfree(kbuf);
++
++      switch (kex->kex_type) {
++      case KEX_GSS_GRP1_SHA1:
++      case KEX_GSS_GRP14_SHA1:
++              kex_dh_hash(
++                  kex->client_version_string, kex->server_version_string,
++                  buffer_ptr(&kex->peer), buffer_len(&kex->peer),
++                  buffer_ptr(&kex->my), buffer_len(&kex->my),
++                  NULL, 0, /* Change this if we start sending host keys */
++                  dh_client_pub, dh->pub_key, shared_secret,
++                  &hash, &hashlen
++              );
++              break;
++      case KEX_GSS_GEX_SHA1:
++              kexgex_hash(
++                  kex->evp_md,
++                  kex->client_version_string, kex->server_version_string,
++                  buffer_ptr(&kex->peer), buffer_len(&kex->peer),
++                  buffer_ptr(&kex->my), buffer_len(&kex->my),
++                  NULL, 0,
++                  min, nbits, max,
++                  dh->p, dh->g,
++                  dh_client_pub,
++                  dh->pub_key,
++                  shared_secret,
++                  &hash, &hashlen
++              );
++              break;
++      default:
++              fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
++      }
++
++      BN_clear_free(dh_client_pub);
++
++      if (kex->session_id == NULL) {
++              kex->session_id_len = hashlen;
++              kex->session_id = xmalloc(kex->session_id_len);
++              memcpy(kex->session_id, hash, kex->session_id_len);
++      }
++
++      gssbuf.value = hash;
++      gssbuf.length = hashlen;
++
++      if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
++              fatal("Couldn't get MIC");
++
++      packet_start(SSH2_MSG_KEXGSS_COMPLETE);
++      packet_put_bignum2(dh->pub_key);
++      packet_put_string(msg_tok.value,msg_tok.length);
++
++      if (send_tok.length != 0) {
++              packet_put_char(1); /* true */
++              packet_put_string(send_tok.value, send_tok.length);
++      } else {
++              packet_put_char(0); /* false */
++      }
++      packet_send();
++
++      gss_release_buffer(&min_status, &send_tok);
++      gss_release_buffer(&min_status, &msg_tok);
++
++      if (gss_kex_context == NULL)
++              gss_kex_context = ctxt;
++      else 
++              ssh_gssapi_delete_ctx(&ctxt);
++
++      DH_free(dh);
++
++      kex_derive_keys(kex, hash, hashlen, shared_secret);
++      BN_clear_free(shared_secret);
++      kex_finish(kex);
++
++      /* If this was a rekey, then save out any delegated credentials we
++       * just exchanged.  */
++      if (options.gss_store_rekey)
++              ssh_gssapi_rekey_creds();
++}
++#endif /* GSSAPI */
+Index: b/key.c
+===================================================================
+--- a/key.c
++++ b/key.c
+@@ -971,6 +971,8 @@
+               }
+               break;
+ #endif /* OPENSSL_HAS_ECC */
++      case KEY_NULL:
++              return "null";
+       }
+       return "ssh-unknown";
+ }
+@@ -1276,6 +1278,8 @@
+           strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
+               return KEY_ECDSA_CERT;
+ #endif
++      } else if (strcmp(name, "null") == 0) {
++              return KEY_NULL;
+       }
+       debug2("key_type_from_name: unknown key type '%s'", name);
+Index: b/key.h
+===================================================================
+--- a/key.h
++++ b/key.h
+@@ -44,6 +44,7 @@
+       KEY_ECDSA_CERT,
+       KEY_RSA_CERT_V00,
+       KEY_DSA_CERT_V00,
++      KEY_NULL,
+       KEY_UNSPEC
+ };
+ enum fp_type {
+Index: b/monitor.c
+===================================================================
+--- a/monitor.c
++++ b/monitor.c
+@@ -180,6 +180,8 @@
+ int mm_answer_gss_accept_ctx(int, Buffer *);
+ int mm_answer_gss_userok(int, Buffer *);
+ int mm_answer_gss_checkmic(int, Buffer *);
++int mm_answer_gss_sign(int, Buffer *);
++int mm_answer_gss_updatecreds(int, Buffer *);
+ #endif
+ #ifdef SSH_AUDIT_EVENTS
+@@ -251,6 +253,7 @@
+     {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
+     {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+     {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
++    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+ #endif
+ #ifdef JPAKE
+     {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
+@@ -263,6 +266,12 @@
+ };
+ struct mon_table mon_dispatch_postauth20[] = {
++#ifdef GSSAPI
++    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
++    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
++    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
++    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
++#endif
+     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
+     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
+     {MONITOR_REQ_PTY, 0, mm_answer_pty},
+@@ -371,6 +380,10 @@
+               /* Permit requests for moduli and signatures */
+               monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
++#ifdef GSSAPI
++              /* and for the GSSAPI key exchange */
++              monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
++#endif
+       } else {
+               mon_dispatch = mon_dispatch_proto15;
+@@ -468,6 +481,10 @@
+               monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
++#ifdef GSSAPI
++              /* and for the GSSAPI key exchange */
++              monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
++#endif                
+       } else {
+               mon_dispatch = mon_dispatch_postauth15;
+               monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+@@ -1802,6 +1819,13 @@
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
++#ifdef GSSAPI
++      if (options.gss_keyex) {
++              kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
++              kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
++              kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
++      }
++#endif
+       kex->server = 1;
+       kex->hostkey_type = buffer_get_int(m);
+       kex->kex_type = buffer_get_int(m);
+@@ -2008,6 +2032,9 @@
+       OM_uint32 major;
+       u_int len;
++      if (!options.gss_authentication && !options.gss_keyex)
++              fatal("In GSSAPI monitor when GSSAPI is disabled");
++
+       goid.elements = buffer_get_string(m, &len);
+       goid.length = len;
+@@ -2035,6 +2062,9 @@
+       OM_uint32 flags = 0; /* GSI needs this */
+       u_int len;
++      if (!options.gss_authentication && !options.gss_keyex)
++              fatal("In GSSAPI monitor when GSSAPI is disabled");
++
+       in.value = buffer_get_string(m, &len);
+       in.length = len;
+       major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
+@@ -2052,6 +2082,7 @@
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
++              monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
+       }
+       return (0);
+ }
+@@ -2063,6 +2094,9 @@
+       OM_uint32 ret;
+       u_int len;
++      if (!options.gss_authentication && !options.gss_keyex)
++              fatal("In GSSAPI monitor when GSSAPI is disabled");
++
+       gssbuf.value = buffer_get_string(m, &len);
+       gssbuf.length = len;
+       mic.value = buffer_get_string(m, &len);
+@@ -2089,7 +2123,11 @@
+ {
+       int authenticated;
+-      authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
++      if (!options.gss_authentication && !options.gss_keyex)
++              fatal("In GSSAPI monitor when GSSAPI is disabled");
++
++      authenticated = authctxt->valid && 
++          ssh_gssapi_userok(authctxt->user, authctxt->pw);
+       buffer_clear(m);
+       buffer_put_int(m, authenticated);
+@@ -2102,6 +2140,74 @@
+       /* Monitor loop will terminate if authenticated */
+       return (authenticated);
+ }
++
++int 
++mm_answer_gss_sign(int socket, Buffer *m)
++{
++      gss_buffer_desc data;
++      gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
++      OM_uint32 major, minor;
++      u_int len;
++
++      if (!options.gss_authentication && !options.gss_keyex)
++              fatal("In GSSAPI monitor when GSSAPI is disabled");
++
++      data.value = buffer_get_string(m, &len);
++      data.length = len;
++      if (data.length != 20) 
++              fatal("%s: data length incorrect: %d", __func__, 
++                  (int) data.length);
++
++      /* Save the session ID on the first time around */
++      if (session_id2_len == 0) {
++              session_id2_len = data.length;
++              session_id2 = xmalloc(session_id2_len);
++              memcpy(session_id2, data.value, session_id2_len);
++      }
++      major = ssh_gssapi_sign(gsscontext, &data, &hash);
++
++      xfree(data.value);
++
++      buffer_clear(m);
++      buffer_put_int(m, major);
++      buffer_put_string(m, hash.value, hash.length);
++
++      mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
++
++      gss_release_buffer(&minor, &hash);
++
++      /* Turn on getpwnam permissions */
++      monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
++      
++      /* And credential updating, for when rekeying */
++      monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
++
++      return (0);
++}
++
++int
++mm_answer_gss_updatecreds(int socket, Buffer *m) {
++      ssh_gssapi_ccache store;
++      int ok;
++
++      store.filename = buffer_get_string(m, NULL);
++      store.envvar   = buffer_get_string(m, NULL);
++      store.envval   = buffer_get_string(m, NULL);
++
++      ok = ssh_gssapi_update_creds(&store);
++
++      xfree(store.filename);
++      xfree(store.envvar);
++      xfree(store.envval);
++
++      buffer_clear(m);
++      buffer_put_int(m, ok);
++
++      mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
++
++      return(0);
++}
++
+ #endif /* GSSAPI */
+ #ifdef JPAKE
+Index: b/monitor.h
+===================================================================
+--- a/monitor.h
++++ b/monitor.h
+@@ -53,6 +53,8 @@
+       MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
+       MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
+       MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
++      MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
++      MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS,
+       MONITOR_REQ_PAM_START,
+       MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
+       MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
+Index: b/monitor_wrap.c
+===================================================================
+--- a/monitor_wrap.c
++++ b/monitor_wrap.c
+@@ -1270,7 +1270,7 @@
+ }
+ int
+-mm_ssh_gssapi_userok(char *user)
++mm_ssh_gssapi_userok(char *user, struct passwd *pw)
+ {
+       Buffer m;
+       int authenticated = 0;
+@@ -1287,6 +1287,51 @@
+       debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
+       return (authenticated);
+ }
++
++OM_uint32
++mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
++{
++      Buffer m;
++      OM_uint32 major;
++      u_int len;
++
++      buffer_init(&m);
++      buffer_put_string(&m, data->value, data->length);
++
++      mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
++      mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
++
++      major = buffer_get_int(&m);
++      hash->value = buffer_get_string(&m, &len);
++      hash->length = len;
++
++      buffer_free(&m);
++
++      return(major);
++}
++
++int
++mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
++{
++      Buffer m;
++      int ok;
++
++      buffer_init(&m);
++
++      buffer_put_cstring(&m, store->filename ? store->filename : "");
++      buffer_put_cstring(&m, store->envvar ? store->envvar : "");
++      buffer_put_cstring(&m, store->envval ? store->envval : "");
++      
++      mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
++      mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
++
++      ok = buffer_get_int(&m);
++
++      buffer_free(&m);
++      
++      return (ok);
++}
++
+ #endif /* GSSAPI */
+ #ifdef JPAKE
+Index: b/monitor_wrap.h
+===================================================================
+--- a/monitor_wrap.h
++++ b/monitor_wrap.h
+@@ -58,8 +58,10 @@
+ OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
+ OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
+    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
+-int mm_ssh_gssapi_userok(char *user);
++int mm_ssh_gssapi_userok(char *user, struct passwd *);
+ OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
++OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
++int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
+ #endif
+ #ifdef USE_PAM
+Index: b/readconf.c
+===================================================================
+--- a/readconf.c
++++ b/readconf.c
+@@ -129,6 +129,8 @@
+       oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+       oAddressFamily, oGssAuthentication, oGssDelegateCreds,
++      oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
++      oGssServerIdentity, 
+       oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
+       oSendEnv, oControlPath, oControlMaster, oControlPersist,
+       oHashKnownHosts,
+@@ -169,10 +171,19 @@
+       { "afstokenpassing", oUnsupported },
+ #if defined(GSSAPI)
+       { "gssapiauthentication", oGssAuthentication },
++      { "gssapikeyexchange", oGssKeyEx },
+       { "gssapidelegatecredentials", oGssDelegateCreds },
++      { "gssapitrustdns", oGssTrustDns },
++      { "gssapiclientidentity", oGssClientIdentity },
++      { "gssapiserveridentity", oGssServerIdentity },
++      { "gssapirenewalforcesrekey", oGssRenewalRekey },
+ #else
+       { "gssapiauthentication", oUnsupported },
++      { "gssapikeyexchange", oUnsupported },
+       { "gssapidelegatecredentials", oUnsupported },
++      { "gssapitrustdns", oUnsupported },
++      { "gssapiclientidentity", oUnsupported },
++      { "gssapirenewalforcesrekey", oUnsupported },
+ #endif
+       { "fallbacktorsh", oDeprecated },
+       { "usersh", oDeprecated },
+@@ -482,10 +493,30 @@
+               intptr = &options->gss_authentication;
+               goto parse_flag;
++      case oGssKeyEx:
++              intptr = &options->gss_keyex;
++              goto parse_flag;
++
+       case oGssDelegateCreds:
+               intptr = &options->gss_deleg_creds;
+               goto parse_flag;
++      case oGssTrustDns:
++              intptr = &options->gss_trust_dns;
++              goto parse_flag;
++
++      case oGssClientIdentity:
++              charptr = &options->gss_client_identity;
++              goto parse_string;
++
++      case oGssServerIdentity:
++              charptr = &options->gss_server_identity;
++              goto parse_string;
++
++      case oGssRenewalRekey:
++              intptr = &options->gss_renewal_rekey;
++              goto parse_flag;
++
+       case oBatchMode:
+               intptr = &options->batch_mode;
+               goto parse_flag;
+@@ -1138,7 +1169,12 @@
+       options->pubkey_authentication = -1;
+       options->challenge_response_authentication = -1;
+       options->gss_authentication = -1;
++      options->gss_keyex = -1;
+       options->gss_deleg_creds = -1;
++      options->gss_trust_dns = -1;
++      options->gss_renewal_rekey = -1;
++      options->gss_client_identity = NULL;
++      options->gss_server_identity = NULL;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->kbd_interactive_devices = NULL;
+@@ -1238,8 +1274,14 @@
+               options->challenge_response_authentication = 1;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
++      if (options->gss_keyex == -1)
++              options->gss_keyex = 0;
+       if (options->gss_deleg_creds == -1)
+               options->gss_deleg_creds = 0;
++      if (options->gss_trust_dns == -1)
++              options->gss_trust_dns = 0;
++      if (options->gss_renewal_rekey == -1)
++              options->gss_renewal_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+Index: b/readconf.h
+===================================================================
+--- a/readconf.h
++++ b/readconf.h
+@@ -47,7 +47,12 @@
+       int     challenge_response_authentication;
+                                       /* Try S/Key or TIS, authentication. */
+       int     gss_authentication;     /* Try GSS authentication */
++      int     gss_keyex;              /* Try GSS key exchange */
+       int     gss_deleg_creds;        /* Delegate GSS credentials */
++      int     gss_trust_dns;          /* Trust DNS for GSS canonicalization */
++      int     gss_renewal_rekey;      /* Credential renewal forces rekey */
++      char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
++      char    *gss_server_identity;   /* GSSAPI target principal */
+       int     password_authentication;        /* Try password
+                                                * authentication. */
+       int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
+Index: b/servconf.c
+===================================================================
+--- a/servconf.c
++++ b/servconf.c
+@@ -97,7 +97,10 @@
+       options->kerberos_ticket_cleanup = -1;
+       options->kerberos_get_afs_token = -1;
+       options->gss_authentication=-1;
++      options->gss_keyex = -1;
+       options->gss_cleanup_creds = -1;
++      options->gss_strict_acceptor = -1;
++      options->gss_store_rekey = -1;
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->challenge_response_authentication = -1;
+@@ -225,8 +228,14 @@
+               options->kerberos_get_afs_token = 0;
+       if (options->gss_authentication == -1)
+               options->gss_authentication = 0;
++      if (options->gss_keyex == -1)
++              options->gss_keyex = 0;
+       if (options->gss_cleanup_creds == -1)
+               options->gss_cleanup_creds = 1;
++      if (options->gss_strict_acceptor == -1)
++              options->gss_strict_acceptor = 1;
++      if (options->gss_store_rekey == -1)
++              options->gss_store_rekey = 0;
+       if (options->password_authentication == -1)
+               options->password_authentication = 1;
+       if (options->kbd_interactive_authentication == -1)
+@@ -318,7 +327,9 @@
+       sBanner, sUseDNS, sHostbasedAuthentication,
+       sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
+       sClientAliveCountMax, sAuthorizedKeysFile,
+-      sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
++      sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
++      sGssKeyEx, sGssStoreRekey,
++      sAcceptEnv, sPermitTunnel,
+       sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
+       sUsePrivilegeSeparation, sAllowAgentForwarding,
+       sZeroKnowledgePasswordAuthentication, sHostCertificate,
+@@ -382,10 +393,20 @@
+ #ifdef GSSAPI
+       { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
++      { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL },
++      { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
++      { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
++      { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
+ #else
+       { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+       { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
++      { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
++      { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
++      { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
++      { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
+ #endif
++      { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
++      { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
+       { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
+       { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
+       { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
+@@ -962,10 +983,22 @@
+               intptr = &options->gss_authentication;
+               goto parse_flag;
++      case sGssKeyEx:
++              intptr = &options->gss_keyex;
++              goto parse_flag;
++
+       case sGssCleanupCreds:
+               intptr = &options->gss_cleanup_creds;
+               goto parse_flag;
++      case sGssStrictAcceptor:
++              intptr = &options->gss_strict_acceptor;
++              goto parse_flag;
++
++      case sGssStoreRekey:
++              intptr = &options->gss_store_rekey;
++              goto parse_flag;
++
+       case sPasswordAuthentication:
+               intptr = &options->password_authentication;
+               goto parse_flag;
+@@ -1720,7 +1753,10 @@
+ #endif
+ #ifdef GSSAPI
+       dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
++      dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
+       dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
++      dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
++      dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
+ #endif
+ #ifdef JPAKE
+       dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
+Index: b/servconf.h
+===================================================================
+--- a/servconf.h
++++ b/servconf.h
+@@ -103,7 +103,10 @@
+       int     kerberos_get_afs_token;         /* If true, try to get AFS token if
+                                                * authenticated with Kerberos. */
+       int     gss_authentication;     /* If true, permit GSSAPI authentication */
++      int     gss_keyex;              /* If true, permit GSSAPI key exchange */
+       int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
++      int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
++      int     gss_store_rekey;
+       int     password_authentication;        /* If true, permit password
+                                                * authentication. */
+       int     kbd_interactive_authentication; /* If true, permit */
+Index: b/ssh-gss.h
+===================================================================
+--- a/ssh-gss.h
++++ b/ssh-gss.h
+@@ -1,6 +1,6 @@
+ /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
+ /*
+- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+@@ -60,10 +60,22 @@
+ #define SSH_GSS_OIDTYPE 0x06
++#define SSH2_MSG_KEXGSS_INIT                            30
++#define SSH2_MSG_KEXGSS_CONTINUE                        31
++#define SSH2_MSG_KEXGSS_COMPLETE                        32
++#define SSH2_MSG_KEXGSS_HOSTKEY                         33
++#define SSH2_MSG_KEXGSS_ERROR                           34
++#define SSH2_MSG_KEXGSS_GROUPREQ                      40
++#define SSH2_MSG_KEXGSS_GROUP                         41
++#define KEX_GSS_GRP1_SHA1_ID                          "gss-group1-sha1-"
++#define KEX_GSS_GRP14_SHA1_ID                         "gss-group14-sha1-"
++#define KEX_GSS_GEX_SHA1_ID                           "gss-gex-sha1-"
++
+ typedef struct {
+       char *filename;
+       char *envvar;
+       char *envval;
++      struct passwd *owner;
+       void *data;
+ } ssh_gssapi_ccache;
+@@ -71,8 +83,11 @@
+       gss_buffer_desc displayname;
+       gss_buffer_desc exportedname;
+       gss_cred_id_t creds;
++      gss_name_t name;
+       struct ssh_gssapi_mech_struct *mech;
+       ssh_gssapi_ccache store;
++      int used;
++      int updated;
+ } ssh_gssapi_client;
+ typedef struct ssh_gssapi_mech_struct {
+@@ -83,6 +98,7 @@
+       int (*userok) (ssh_gssapi_client *, char *);
+       int (*localname) (ssh_gssapi_client *, char **);
+       void (*storecreds) (ssh_gssapi_client *);
++      int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
+ } ssh_gssapi_mech;
+ typedef struct {
+@@ -93,10 +109,11 @@
+       gss_OID         oid; /* client */
+       gss_cred_id_t   creds; /* server */
+       gss_name_t      client; /* server */
+-      gss_cred_id_t   client_creds; /* server */
++      gss_cred_id_t   client_creds; /* both */
+ } Gssctxt;
+ extern ssh_gssapi_mech *supported_mechs[];
++extern Gssctxt *gss_kex_context;
+ int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
+ void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
+@@ -116,16 +133,30 @@
+ void ssh_gssapi_delete_ctx(Gssctxt **);
+ OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
+ void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
+-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
++int ssh_gssapi_credentials_updated(Gssctxt *);
+ /* In the server */
++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 
++    const char *);
++char *ssh_gssapi_client_mechanisms(const char *, const char *);
++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
++    const char *);
++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 
++    const char *);
+ OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
+-int ssh_gssapi_userok(char *name);
++int ssh_gssapi_userok(char *name, struct passwd *);
+ OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+ void ssh_gssapi_do_child(char ***, u_int *);
+ void ssh_gssapi_cleanup_creds(void);
+ void ssh_gssapi_storecreds(void);
++char *ssh_gssapi_server_mechanisms(void);
++int ssh_gssapi_oid_table_ok();
++
++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
+ #endif /* GSSAPI */
+ #endif /* _SSH_GSS_H */
+Index: b/ssh_config
+===================================================================
+--- a/ssh_config
++++ b/ssh_config
+@@ -26,6 +26,8 @@
+ #   HostbasedAuthentication no
+ #   GSSAPIAuthentication no
+ #   GSSAPIDelegateCredentials no
++#   GSSAPIKeyExchange no
++#   GSSAPITrustDNS no
+ #   BatchMode no
+ #   CheckHostIP yes
+ #   AddressFamily any
+Index: b/ssh_config.5
+===================================================================
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -527,11 +527,43 @@
+ The default is
+ .Dq no .
+ Note that this option applies to protocol version 2 only.
++.It Cm GSSAPIKeyExchange
++Specifies whether key exchange based on GSSAPI may be used. When using
++GSSAPI key exchange the server need not have a host key.
++The default is
++.Dq no .
++Note that this option applies to protocol version 2 only.
++.It Cm GSSAPIClientIdentity
++If set, specifies the GSSAPI client identity that ssh should use when 
++connecting to the server. The default is unset, which means that the default 
++identity will be used.
++.It Cm GSSAPIServerIdentity
++If set, specifies the GSSAPI server identity that ssh should expect when 
++connecting to the server. The default is unset, which means that the
++expected GSSAPI server identity will be determined from the target
++hostname.
+ .It Cm GSSAPIDelegateCredentials
+ Forward (delegate) credentials to the server.
+ The default is
+ .Dq no .
+-Note that this option applies to protocol version 2 only.
++Note that this option applies to protocol version 2 connections using GSSAPI.
++.It Cm GSSAPIRenewalForcesRekey
++If set to 
++.Dq yes
++then renewal of the client's GSSAPI credentials will force the rekeying of the
++ssh connection. With a compatible server, this can delegate the renewed 
++credentials to a session on the server.
++The default is
++.Dq no .
++.It Cm GSSAPITrustDns
++Set to 
++.Dq yes to indicate that the DNS is trusted to securely canonicalize
++the name of the host being connected to. If 
++.Dq no, the hostname entered on the
++command line will be passed untouched to the GSSAPI library.
++The default is
++.Dq no .
++This option only applies to protocol version 2 connections using GSSAPI.
+ .It Cm HashKnownHosts
+ Indicates that
+ .Xr ssh 1
+Index: b/sshconnect2.c
+===================================================================
+--- a/sshconnect2.c
++++ b/sshconnect2.c
+@@ -160,9 +160,34 @@
+ {
+       Kex *kex;
++#ifdef GSSAPI
++      char *orig = NULL, *gss = NULL;
++      char *gss_host = NULL;
++#endif
++
+       xxx_host = host;
+       xxx_hostaddr = hostaddr;
++#ifdef GSSAPI
++      if (options.gss_keyex) {
++              /* Add the GSSAPI mechanisms currently supported on this 
++               * client to the key exchange algorithm proposal */
++              orig = myproposal[PROPOSAL_KEX_ALGS];
++
++              if (options.gss_trust_dns)
++                      gss_host = (char *)get_canonical_hostname(1);
++              else
++                      gss_host = host;
++
++              gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
++              if (gss) {
++                      debug("Offering GSSAPI proposal: %s", gss);
++                      xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
++                          "%s,%s", gss, orig);
++              }
++      }
++#endif
++
+       if (options.ciphers == (char *)-1) {
+               logit("No valid ciphers for protocol version 2 given, using defaults.");
+               options.ciphers = NULL;
+@@ -197,6 +222,17 @@
+       if (options.kex_algorithms != NULL)
+               myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
++#ifdef GSSAPI
++      /* If we've got GSSAPI algorithms, then we also support the
++       * 'null' hostkey, as a last resort */
++      if (options.gss_keyex && gss) {
++              orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
++              xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 
++                  "%s,null", orig);
++              xfree(gss);
++      }
++#endif
++
+       if (options.rekey_limit)
+               packet_set_rekey_limit((u_int32_t)options.rekey_limit);
+@@ -207,10 +243,30 @@
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
++#ifdef GSSAPI
++      if (options.gss_keyex) {
++              kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
++              kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
++              kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
++      }
++#endif
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+       kex->verify_host_key=&verify_host_key_callback;
++#ifdef GSSAPI
++      if (options.gss_keyex) {
++              kex->gss_deleg_creds = options.gss_deleg_creds;
++              kex->gss_trust_dns = options.gss_trust_dns;
++              kex->gss_client = options.gss_client_identity;
++              if (options.gss_server_identity) {
++                      kex->gss_host = options.gss_server_identity;
++              } else {
++                      kex->gss_host = gss_host;
++        }
++      }
++#endif
++
+       xxx_kex = kex;
+       dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
+@@ -305,6 +361,7 @@
+ void  input_gssapi_hash(int type, u_int32_t, void *);
+ void  input_gssapi_error(int, u_int32_t, void *);
+ void  input_gssapi_errtok(int, u_int32_t, void *);
++int   userauth_gsskeyex(Authctxt *authctxt);
+ #endif
+ void  userauth(Authctxt *, char *);
+@@ -320,6 +377,11 @@
+ Authmethod authmethods[] = {
+ #ifdef GSSAPI
++      {"gssapi-keyex",
++              userauth_gsskeyex,
++              NULL,
++              &options.gss_authentication,
++              NULL},
+       {"gssapi-with-mic",
+               userauth_gssapi,
+               NULL,
+@@ -626,19 +688,31 @@
+       static u_int mech = 0;
+       OM_uint32 min;
+       int ok = 0;
++      const char *gss_host;
++
++      if (options.gss_server_identity)
++              gss_host = options.gss_server_identity;
++      else if (options.gss_trust_dns)
++              gss_host = get_canonical_hostname(1);
++      else
++              gss_host = authctxt->host;
+       /* Try one GSSAPI method at a time, rather than sending them all at
+        * once. */
+       if (gss_supported == NULL)
+-              gss_indicate_mechs(&min, &gss_supported);
++              if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
++                      gss_supported = NULL;
++                      return 0;
++              }
+       /* Check to see if the mechanism is usable before we offer it */
+       while (mech < gss_supported->count && !ok) {
+               /* My DER encoding requires length<128 */
+               if (gss_supported->elements[mech].length < 128 &&
+                   ssh_gssapi_check_mechanism(&gssctxt, 
+-                  &gss_supported->elements[mech], authctxt->host)) {
++                  &gss_supported->elements[mech], gss_host, 
++                    options.gss_client_identity)) {
+                       ok = 1; /* Mechanism works */
+               } else {
+                       mech++;
+@@ -735,8 +809,8 @@
+ {
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+-      int oidlen;
+-      char *oidv;
++      u_int oidlen;
++      u_char *oidv;
+       if (authctxt == NULL)
+               fatal("input_gssapi_response: no authentication context");
+@@ -846,6 +920,48 @@
+       xfree(msg);
+       xfree(lang);
+ }
++
++int
++userauth_gsskeyex(Authctxt *authctxt)
++{
++      Buffer b;
++      gss_buffer_desc gssbuf;
++      gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
++      OM_uint32 ms;
++
++      static int attempt = 0;
++      if (attempt++ >= 1)
++              return (0);
++
++      if (gss_kex_context == NULL) {
++              debug("No valid Key exchange context"); 
++              return (0);
++      }
++
++      ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
++          "gssapi-keyex");
++
++      gssbuf.value = buffer_ptr(&b);
++      gssbuf.length = buffer_len(&b);
++
++      if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
++              buffer_free(&b);
++              return (0);
++      }
++
++      packet_start(SSH2_MSG_USERAUTH_REQUEST);
++      packet_put_cstring(authctxt->server_user);
++      packet_put_cstring(authctxt->service);
++      packet_put_cstring(authctxt->method->name);
++      packet_put_string(mic.value, mic.length);
++      packet_send();
++
++      buffer_free(&b);
++      gss_release_buffer(&ms, &mic);
++
++      return (1);
++}
++
+ #endif /* GSSAPI */
+ int
+Index: b/sshd.c
+===================================================================
+--- a/sshd.c
++++ b/sshd.c
+@@ -121,6 +121,10 @@
+ #include "ssh-sandbox.h"
+ #include "version.h"
++#ifdef USE_SECURITY_SESSION_API
++#include <Security/AuthSession.h>
++#endif
++
+ #ifdef LIBWRAP
+ #include <tcpd.h>
+ #include <syslog.h>
+@@ -1612,10 +1616,13 @@
+               logit("Disabling protocol version 1. Could not load host key");
+               options.protocol &= ~SSH_PROTO_1;
+       }
++#ifndef GSSAPI
++      /* The GSSAPI key exchange can run without a host key */
+       if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
+               logit("Disabling protocol version 2. Could not load host key");
+               options.protocol &= ~SSH_PROTO_2;
+       }
++#endif
+       if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
+               logit("sshd: no hostkeys available -- exiting.");
+               exit(1);
+@@ -1944,6 +1951,60 @@
+       /* Log the connection. */
+       verbose("Connection from %.500s port %d", remote_ip, remote_port);
++#ifdef USE_SECURITY_SESSION_API
++      /*
++       * Create a new security session for use by the new user login if
++       * the current session is the root session or we are not launched
++       * by inetd (eg: debugging mode or server mode).  We do not
++       * necessarily need to create a session if we are launched from
++       * inetd because Panther xinetd will create a session for us.
++       *
++       * The only case where this logic will fail is if there is an
++       * inetd running in a non-root session which is not creating
++       * new sessions for us.  Then all the users will end up in the
++       * same session (bad).
++       *
++       * When the client exits, the session will be destroyed for us
++       * automatically.
++       *
++       * We must create the session before any credentials are stored
++       * (including AFS pags, which happens a few lines below).
++       */
++      {
++              OSStatus err = 0;
++              SecuritySessionId sid = 0;
++              SessionAttributeBits sattrs = 0;
++
++              err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
++              if (err)
++                      error("SessionGetInfo() failed with error %.8X",
++                          (unsigned) err);
++              else
++                      debug("Current Session ID is %.8X / Session Attributes are %.8X",
++                          (unsigned) sid, (unsigned) sattrs);
++
++              if (inetd_flag && !(sattrs & sessionIsRoot))
++                      debug("Running in inetd mode in a non-root session... "
++                          "assuming inetd created the session for us.");
++              else {
++                      debug("Creating new security session...");
++                      err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
++                      if (err)
++                              error("SessionCreate() failed with error %.8X",
++                                  (unsigned) err);
++
++                      err = SessionGetInfo(callerSecuritySession, &sid, 
++                          &sattrs);
++                      if (err)
++                              error("SessionGetInfo() failed with error %.8X",
++                                  (unsigned) err);
++                      else
++                              debug("New Session ID is %.8X / Session Attributes are %.8X",
++                                  (unsigned) sid, (unsigned) sattrs);
++              }
++      }
++#endif
++
+       /*
+        * We don't want to listen forever unless the other side
+        * successfully authenticates itself.  So we set up an alarm which is
+@@ -2325,6 +2386,48 @@
+       myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
++#ifdef GSSAPI
++      {
++      char *orig;
++      char *gss = NULL;
++      char *newstr = NULL;
++      orig = myproposal[PROPOSAL_KEX_ALGS];
++
++      /* 
++       * If we don't have a host key, then there's no point advertising
++       * the other key exchange algorithms
++       */
++
++      if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
++              orig = NULL;
++
++      if (options.gss_keyex)
++              gss = ssh_gssapi_server_mechanisms();
++      else
++              gss = NULL;
++
++      if (gss && orig)
++              xasprintf(&newstr, "%s,%s", gss, orig);
++      else if (gss)
++              newstr = gss;
++      else if (orig)
++              newstr = orig;
++
++      /* 
++       * If we've got GSSAPI mechanisms, then we've got the 'null' host
++       * key alg, but we can't tell people about it unless its the only
++       * host key algorithm we support
++       */
++      if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
++              myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
++
++      if (newstr)
++              myproposal[PROPOSAL_KEX_ALGS] = newstr;
++      else
++              fatal("No supported key exchange algorithms");
++      }
++#endif
++
+       /* start key exchange */
+       kex = kex_setup(myproposal);
+       kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+@@ -2332,6 +2435,13 @@
+       kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+       kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+       kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
++#ifdef GSSAPI
++      if (options.gss_keyex) {
++              kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
++              kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
++              kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
++      }
++#endif
+       kex->server = 1;
+       kex->client_version_string=client_version_string;
+       kex->server_version_string=server_version_string;
+Index: b/sshd_config
+===================================================================
+--- a/sshd_config
++++ b/sshd_config
+@@ -75,6 +75,8 @@
+ # GSSAPI options
+ #GSSAPIAuthentication no
+ #GSSAPICleanupCredentials yes
++#GSSAPIStrictAcceptorCheck yes
++#GSSAPIKeyExchange no
+ # Set this to 'yes' to enable PAM authentication, account processing, 
+ # and session processing. If this is enabled, PAM authentication will 
+Index: b/sshd_config.5
+===================================================================
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -424,12 +424,40 @@
+ The default is
+ .Dq no .
+ Note that this option applies to protocol version 2 only.
++.It Cm GSSAPIKeyExchange
++Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
++doesn't rely on ssh keys to verify host identity.
++The default is
++.Dq no .
++Note that this option applies to protocol version 2 only.
+ .It Cm GSSAPICleanupCredentials
+ Specifies whether to automatically destroy the user's credentials cache
+ on logout.
+ The default is
+ .Dq yes .
+ Note that this option applies to protocol version 2 only.
++.It Cm GSSAPIStrictAcceptorCheck
++Determines whether to be strict about the identity of the GSSAPI acceptor 
++a client authenticates against. If
++.Dq yes
++then the client must authenticate against the
++.Pa host
++service on the current hostname. If 
++.Dq no
++then the client may authenticate against any service key stored in the 
++machine's default store. This facility is provided to assist with operation 
++on multi homed machines. 
++The default is
++.Dq yes .
++Note that this option applies only to protocol version 2 GSSAPI connections,
++and setting it to 
++.Dq no
++may only work with recent Kerberos GSSAPI libraries.
++.It Cm GSSAPIStoreCredentialsOnRekey
++Controls whether the user's GSSAPI credentials should be updated following a 
++successful connection rekeying. This option can be used to accepted renewed 
++or updated credentials from a compatible client. The default is
++.Dq no .
+ .It Cm HostbasedAuthentication
+ Specifies whether rhosts or /etc/hosts.equiv authentication together
+ with successful public key client host authentication is allowed
diff --git a/debian/patches/helpful-wait-terminate.patch b/debian/patches/helpful-wait-terminate.patch
new file mode 100644 (file)
index 0000000..857f864
--- /dev/null
@@ -0,0 +1,18 @@
+Description: Mention ~& when waiting for forwarded connections to terminate
+Author: Matthew Vernon <matthew@debian.org>
+Bug-Debian: http://bugs.debian.org/50308
+Last-Update: 2010-02-27
+
+Index: b/serverloop.c
+===================================================================
+--- a/serverloop.c
++++ b/serverloop.c
+@@ -680,7 +680,7 @@
+                       if (!channel_still_open())
+                               break;
+                       if (!waiting_termination) {
+-                              const char *s = "Waiting for forwarded connections to terminate...\r\n";
++                              const char *s = "Waiting for forwarded connections to terminate... (press ~& to background)\r\n";
+                               char *cp;
+                               waiting_termination = 1;
+                               buffer_append(&stderr_buffer, s, strlen(s));
diff --git a/debian/patches/keepalive-extensions.patch b/debian/patches/keepalive-extensions.patch
new file mode 100644 (file)
index 0000000..d8362de
--- /dev/null
@@ -0,0 +1,124 @@
+Description: Various keepalive extensions
+ Add compatibility aliases for ProtocolKeepAlives and SetupTimeOut,
+ supported in previous versions of Debian's OpenSSH package but since
+ superseded by ServerAliveInterval.  (We're probably stuck with this bit for
+ compatibility.)
+ .
+ In batch mode, default ServerAliveInterval to five minutes.
+ .
+ Adjust documentation to match and to give some more advice on use of
+ keepalives.
+Author: Richard Kettlewell <rjk@greenend.org.uk>
+Author: Ian Jackson <ian@chiark.greenend.org.uk>
+Author: Matthew Vernon <matthew@debian.org>
+Author: Colin Watson <cjwatson@debian.org>
+Last-Update: 2010-02-27
+
+Index: b/readconf.c
+===================================================================
+--- a/readconf.c
++++ b/readconf.c
+@@ -138,6 +138,7 @@
+       oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+       oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
+       oKexAlgorithms, oIPQoS, oRequestTTY,
++      oProtocolKeepAlives, oSetupTimeOut,
+       oDeprecated, oUnsupported
+ } OpCodes;
+@@ -259,6 +260,8 @@
+       { "kexalgorithms", oKexAlgorithms },
+       { "ipqos", oIPQoS },
+       { "requesttty", oRequestTTY },
++      { "protocolkeepalives", oProtocolKeepAlives },
++      { "setuptimeout", oSetupTimeOut },
+       { NULL, oBadOption }
+ };
+@@ -914,6 +917,8 @@
+               goto parse_flag;
+       case oServerAliveInterval:
++      case oProtocolKeepAlives: /* Debian-specific compatibility alias */
++      case oSetupTimeOut:       /* Debian-specific compatibility alias */
+               intptr = &options->server_alive_interval;
+               goto parse_time;
+@@ -1385,8 +1390,13 @@
+               options->rekey_limit = 0;
+       if (options->verify_host_key_dns == -1)
+               options->verify_host_key_dns = 0;
+-      if (options->server_alive_interval == -1)
+-              options->server_alive_interval = 0;
++      if (options->server_alive_interval == -1) {
++              /* in batch mode, default is 5mins */
++              if (options->batch_mode == 1)
++                      options->server_alive_interval = 300;
++              else
++                      options->server_alive_interval = 0;
++      }
+       if (options->server_alive_count_max == -1)
+               options->server_alive_count_max = 3;
+       if (options->control_master == -1)
+Index: b/ssh_config.5
+===================================================================
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -136,8 +136,12 @@
+ If set to
+ .Dq yes ,
+ passphrase/password querying will be disabled.
++In addition, the
++.Cm ServerAliveInterval
++option will be set to 300 seconds by default.
+ This option is useful in scripts and other batch jobs where no user
+-is present to supply the password.
++is present to supply the password,
++and where it is desirable to detect a broken network swiftly.
+ The argument must be
+ .Dq yes
+ or
+@@ -1100,8 +1104,15 @@
+ will send a message through the encrypted
+ channel to request a response from the server.
+ The default
+-is 0, indicating that these messages will not be sent to the server.
++is 0, indicating that these messages will not be sent to the server,
++or 300 if the
++.Cm BatchMode
++option is set.
+ This option applies to protocol version 2 only.
++.Cm ProtocolKeepAlives
++and
++.Cm SetupTimeOut
++are Debian-specific compatibility aliases for this option.
+ .It Cm StrictHostKeyChecking
+ If this flag is set to
+ .Dq yes ,
+@@ -1140,6 +1151,12 @@
+ other side.
+ If they are sent, death of the connection or crash of one
+ of the machines will be properly noticed.
++This option only uses TCP keepalives (as opposed to using ssh level
++keepalives), so takes a long time to notice when the connection dies.
++As such, you probably want
++the
++.Cm ServerAliveInterval
++option as well.
+ However, this means that
+ connections will die if the route is down temporarily, and some people
+ find it annoying.
+Index: b/sshd_config.5
+===================================================================
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -1037,6 +1037,9 @@
+ .Pp
+ To disable TCP keepalive messages, the value should be set to
+ .Dq no .
++.Pp
++This option was formerly called
++.Cm KeepAlive .
+ .It Cm TrustedUserCAKeys
+ Specifies a file containing public keys of certificate authorities that are
+ trusted to sign user certificates for authentication.
diff --git a/debian/patches/lintian-symlink-pickiness.patch b/debian/patches/lintian-symlink-pickiness.patch
new file mode 100644 (file)
index 0000000..7ee91cc
--- /dev/null
@@ -0,0 +1,23 @@
+Description: Fix picky lintian errors about slogin symlinks
+ Apparently this breaks some SVR4 packaging systems, so upstream can't win
+ either way and opted to keep the status quo.  We need this patch anyway.
+Author: Colin Watson <cjwatson@debian.org>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1728
+Last-Update: 2010-04-10
+
+Index: b/Makefile.in
+===================================================================
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -282,9 +282,9 @@
+       $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+       $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+       -rm -f $(DESTDIR)$(bindir)/slogin
+-      ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
++      ln -s ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+-      ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
++      ln -s ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+ install-sysconf:
+       if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
diff --git a/debian/patches/openbsd-docs.patch b/debian/patches/openbsd-docs.patch
new file mode 100644 (file)
index 0000000..bda5f0c
--- /dev/null
@@ -0,0 +1,135 @@
+Description: Adjust various OpenBSD-specific references in manual pages
+ No single bug reference for this patch, but history includes:
+  http://bugs.debian.org/154434 (login.conf(5))
+  http://bugs.debian.org/513417 (/etc/rc)
+  http://bugs.debian.org/530692 (ssl(8))
+  https://bugs.launchpad.net/bugs/456660 (ssl(8))
+Author: Colin Watson <cjwatson@debian.org>
+Forwarded: not-needed
+Last-Update: 2010-02-28
+
+Index: b/moduli.5
+===================================================================
+--- a/moduli.5
++++ b/moduli.5
+@@ -21,7 +21,7 @@
+ .Nd Diffie-Hellman moduli
+ .Sh DESCRIPTION
+ The
+-.Pa /etc/moduli
++.Pa /etc/ssh/moduli
+ file contains prime numbers and generators for use by
+ .Xr sshd 8
+ in the Diffie-Hellman Group Exchange key exchange method.
+@@ -110,7 +110,7 @@
+ Diffie-Hellman output to sufficiently key the selected symmetric cipher.
+ .Xr sshd 8
+ then randomly selects a modulus from
+-.Fa /etc/moduli
++.Fa /etc/ssh/moduli
+ that best meets the size requirement.
+ .Sh SEE ALSO
+ .Xr ssh-keygen 1 ,
+Index: b/ssh-keygen.1
+===================================================================
+--- a/ssh-keygen.1
++++ b/ssh-keygen.1
+@@ -149,9 +149,7 @@
+ .Pa ~/.ssh/id_dsa
+ or
+ .Pa ~/.ssh/id_rsa .
+-Additionally, the system administrator may use this to generate host keys,
+-as seen in
+-.Pa /etc/rc .
++Additionally, the system administrator may use this to generate host keys.
+ .Pp
+ Normally this program generates the key and asks for a file in which
+ to store the private key.
+@@ -197,9 +195,7 @@
+ For each of the key types (rsa1, rsa, dsa and ecdsa) for which host keys
+ do not exist, generate the host keys with the default key file path,
+ an empty passphrase, default bits for the key type, and default comment.
+-This is used by
+-.Pa /etc/rc
+-to generate new host keys.
++This is used by system administration scripts to generate new host keys.
+ .It Fl a Ar trials
+ Specifies the number of primality tests to perform when screening DH-GEX
+ candidates using the
+@@ -535,7 +531,7 @@
+ Valid generator values are 2, 3, and 5.
+ .Pp
+ Screened DH groups may be installed in
+-.Pa /etc/moduli .
++.Pa /etc/ssh/moduli .
+ It is important that this file contains moduli of a range of bit lengths and
+ that both ends of a connection share common moduli.
+ .Sh CERTIFICATES
+@@ -661,7 +657,7 @@
+ where the user wishes to log in using public key authentication.
+ There is no need to keep the contents of this file secret.
+ .Pp
+-.It Pa /etc/moduli
++.It Pa /etc/ssh/moduli
+ Contains Diffie-Hellman groups used for DH-GEX.
+ The file format is described in
+ .Xr moduli 5 .
+Index: b/ssh.1
+===================================================================
+--- a/ssh.1
++++ b/ssh.1
+@@ -731,6 +731,10 @@
+ .Sx HISTORY
+ section of
+ .Xr ssl 8
++(on non-OpenBSD systems, see
++.nh
++http://www.openbsd.org/cgi\-bin/man.cgi?query=ssl&sektion=8#HISTORY)
++.hy
+ contains a brief discussion of the DSA and RSA algorithms.
+ .Pp
+ The file
+Index: b/sshd.8
+===================================================================
+--- a/sshd.8
++++ b/sshd.8
+@@ -69,7 +69,7 @@
+ .Nm
+ listens for connections from clients.
+ It is normally started at boot from
+-.Pa /etc/rc .
++.Pa /etc/init.d/ssh .
+ It forks a new
+ daemon for each incoming connection.
+ The forked daemons handle
+@@ -853,7 +853,7 @@
+ .Xr ssh 1 ) .
+ It should only be writable by root.
+ .Pp
+-.It Pa /etc/moduli
++.It Pa /etc/ssh/moduli
+ Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange".
+ The file format is described in
+ .Xr moduli 5 .
+@@ -951,7 +951,6 @@
+ .Xr ssh-vulnkey 1 ,
+ .Xr chroot 2 ,
+ .Xr hosts_access 5 ,
+-.Xr login.conf 5 ,
+ .Xr moduli 5 ,
+ .Xr sshd_config 5 ,
+ .Xr inetd 8 ,
+Index: b/sshd_config.5
+===================================================================
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -222,8 +222,7 @@
+ By default, no banner is displayed.
+ .It Cm ChallengeResponseAuthentication
+ Specifies whether challenge-response authentication is allowed (e.g. via
+-PAM or though authentication styles supported in
+-.Xr login.conf 5 )
++PAM).
+ The default is
+ .Dq yes .
+ .It Cm ChrootDirectory
diff --git a/debian/patches/package-versioning.patch b/debian/patches/package-versioning.patch
new file mode 100644 (file)
index 0000000..95444cb
--- /dev/null
@@ -0,0 +1,50 @@
+Description: Include the Debian version in our identification
+ This makes it easier to audit networks for versions patched against
+ security vulnerabilities.  It has little detrimental effect, as attackers
+ will generally just try attacks rather than bothering to scan for
+ vulnerable-looking version strings.  (However, see debian-banner.patch.)
+Author: Matthew Vernon <matthew@debian.org>
+Forwarded: not-needed
+Last-Update: 2010-02-28
+
+Index: b/sshconnect.c
+===================================================================
+--- a/sshconnect.c
++++ b/sshconnect.c
+@@ -556,7 +556,7 @@
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
+           compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
+           compat20 ? PROTOCOL_MINOR_2 : minor1,
+-          SSH_VERSION, compat20 ? "\r\n" : "\n");
++          SSH_RELEASE, compat20 ? "\r\n" : "\n");
+       if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
+           != strlen(buf))
+               fatal("write: %.100s", strerror(errno));
+Index: b/sshd.c
+===================================================================
+--- a/sshd.c
++++ b/sshd.c
+@@ -423,7 +423,7 @@
+               minor = PROTOCOL_MINOR_1;
+       }
+       snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
+-          SSH_VERSION, newline);
++          SSH_RELEASE, newline);
+       server_version_string = xstrdup(buf);
+       /* Send our protocol version identification. */
+Index: b/version.h
+===================================================================
+--- a/version.h
++++ b/version.h
+@@ -3,4 +3,9 @@
+ #define SSH_VERSION   "OpenSSH_5.9"
+ #define SSH_PORTABLE  "p1"
+-#define SSH_RELEASE   SSH_VERSION SSH_PORTABLE
++#define SSH_RELEASE_MINIMUM   SSH_VERSION SSH_PORTABLE
++#ifdef SSH_EXTRAVERSION
++#define SSH_RELEASE   SSH_RELEASE_MINIMUM " " SSH_EXTRAVERSION
++#else
++#define SSH_RELEASE   SSH_RELEASE_MINIMUM
++#endif
diff --git a/debian/patches/quieter-signals.patch b/debian/patches/quieter-signals.patch
new file mode 100644 (file)
index 0000000..ff41f09
--- /dev/null
@@ -0,0 +1,31 @@
+Description: Reduce severity of "Killed by signal %d"
+ This produces irritating messages when using ProxyCommand or other programs
+ that use ssh under the covers (e.g. Subversion).  These messages are more
+ normally printed by the calling program, such as the shell.
+ .
+ According to the upstream bug, the right way to avoid this is to use the -q
+ option, so we may drop this patch after further investigation into whether
+ any software in Debian is still relying on it.
+Author: Peter Samuelson <peter@p12n.org>
+Author: Colin Watson <cjwatson@debian.org>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1118
+Bug-Debian: http://bugs.debian.org/313371
+Last-Update: 2010-02-27
+
+Index: b/clientloop.c
+===================================================================
+--- a/clientloop.c
++++ b/clientloop.c
+@@ -1619,8 +1619,10 @@
+               exit_status = 0;
+       }
+-      if (received_signal)
+-              fatal("Killed by signal %d.", (int) received_signal);
++      if (received_signal) {
++              debug("Killed by signal %d.", (int) received_signal);
++              cleanup_exit((int) received_signal + 128);
++      }
+       /*
+        * In interactive mode (with pseudo tty) display a message indicating
diff --git a/debian/patches/scp-quoting.patch b/debian/patches/scp-quoting.patch
new file mode 100644 (file)
index 0000000..239c1b5
--- /dev/null
@@ -0,0 +1,32 @@
+Description: Adjust scp quoting in verbose mode
+ Tweak scp's reporting of filenames in verbose mode to be a bit less
+ confusing with spaces.
+ .
+ This should be revised to mimic real shell quoting.
+Author: Nicolas Valcárcel <nvalcarcel@ubuntu.com>
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/89945
+Last-Update: 2010-02-27
+
+Index: b/scp.c
+===================================================================
+--- a/scp.c
++++ b/scp.c
+@@ -189,8 +189,16 @@
+       if (verbose_mode) {
+               fprintf(stderr, "Executing:");
+-              for (i = 0; i < a->num; i++)
+-                      fprintf(stderr, " %s", a->list[i]);
++              for (i = 0; i < a->num; i++) {
++                      if (i == 0)
++                              fprintf(stderr, " %s", a->list[i]);
++                      else
++                              /*
++                               * TODO: misbehaves if a->list[i] contains a
++                               * single quote
++                               */
++                              fprintf(stderr, " '%s'", a->list[i]);
++              }
+               fprintf(stderr, "\n");
+       }
+       if ((pid = fork()) == -1)
diff --git a/debian/patches/selinux-role.patch b/debian/patches/selinux-role.patch
new file mode 100644 (file)
index 0000000..b144021
--- /dev/null
@@ -0,0 +1,482 @@
+Description: Handle SELinux authorisation roles
+ Rejected upstream due to discomfort with magic usernames; a better approach
+ will need an SSH protocol change.  In the meantime, this came from Debian's
+ SELinux maintainer, so we'll keep it until we have something better.
+Author: Manoj Srivastava <srivasta@debian.org>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1641
+Bug-Debian: http://bugs.debian.org/394795
+Last-Update: 2010-02-27
+
+Index: b/auth.h
+===================================================================
+--- a/auth.h
++++ b/auth.h
+@@ -59,6 +59,7 @@
+       char            *service;
+       struct passwd   *pw;            /* set if 'valid' */
+       char            *style;
++      char            *role;
+       void            *kbdintctxt;
+       void            *jpake_ctx;
+ #ifdef BSD_AUTH
+Index: b/auth1.c
+===================================================================
+--- a/auth1.c
++++ b/auth1.c
+@@ -383,7 +383,7 @@
+ do_authentication(Authctxt *authctxt)
+ {
+       u_int ulen;
+-      char *user, *style = NULL;
++      char *user, *style = NULL, *role = NULL;
+       /* Get the name of the user that we wish to log in as. */
+       packet_read_expect(SSH_CMSG_USER);
+@@ -392,11 +392,17 @@
+       user = packet_get_cstring(&ulen);
+       packet_check_eom();
++      if ((role = strchr(user, '/')) != NULL)
++              *role++ = '\0';
++
+       if ((style = strchr(user, ':')) != NULL)
+               *style++ = '\0';
++      else if (role && (style = strchr(role, ':')) != NULL)
++              *style++ = '\0';
+       authctxt->user = user;
+       authctxt->style = style;
++      authctxt->role = role;
+       /* Verify that the user is a valid user. */
+       if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
+Index: b/auth2.c
+===================================================================
+--- a/auth2.c
++++ b/auth2.c
+@@ -217,7 +217,7 @@
+ {
+       Authctxt *authctxt = ctxt;
+       Authmethod *m = NULL;
+-      char *user, *service, *method, *style = NULL;
++      char *user, *service, *method, *style = NULL, *role = NULL;
+       int authenticated = 0;
+       if (authctxt == NULL)
+@@ -229,8 +229,13 @@
+       debug("userauth-request for user %s service %s method %s", user, service, method);
+       debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
++      if ((role = strchr(user, '/')) != NULL)
++              *role++ = 0;
++
+       if ((style = strchr(user, ':')) != NULL)
+               *style++ = 0;
++      else if (role && (style = strchr(role, ':')) != NULL)
++              *style++ = '\0';
+       if (authctxt->attempt++ == 0) {
+               /* setup auth context */
+@@ -254,8 +259,9 @@
+                   use_privsep ? " [net]" : "");
+               authctxt->service = xstrdup(service);
+               authctxt->style = style ? xstrdup(style) : NULL;
++              authctxt->role = role ? xstrdup(role) : NULL;
+               if (use_privsep)
+-                      mm_inform_authserv(service, style);
++                      mm_inform_authserv(service, style, role);
+               userauth_banner();
+       } else if (strcmp(user, authctxt->user) != 0 ||
+           strcmp(service, authctxt->service) != 0) {
+Index: b/monitor.c
+===================================================================
+--- a/monitor.c
++++ b/monitor.c
+@@ -145,6 +145,7 @@
+ int mm_answer_pwnamallow(int, Buffer *);
+ int mm_answer_auth2_read_banner(int, Buffer *);
+ int mm_answer_authserv(int, Buffer *);
++int mm_answer_authrole(int, Buffer *);
+ int mm_answer_authpassword(int, Buffer *);
+ int mm_answer_bsdauthquery(int, Buffer *);
+ int mm_answer_bsdauthrespond(int, Buffer *);
+@@ -225,6 +226,7 @@
+     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
+     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
++    {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
+     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
+     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+ #ifdef USE_PAM
+@@ -810,6 +812,7 @@
+       else {
+               /* Allow service/style information on the auth context */
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
++              monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
+       }
+ #ifdef USE_PAM
+@@ -842,14 +845,37 @@
+       authctxt->service = buffer_get_string(m, NULL);
+       authctxt->style = buffer_get_string(m, NULL);
+-      debug3("%s: service=%s, style=%s",
+-          __func__, authctxt->service, authctxt->style);
++      authctxt->role = buffer_get_string(m, NULL);
++      debug3("%s: service=%s, style=%s, role=%s",
++          __func__, authctxt->service, authctxt->style, authctxt->role);
+       if (strlen(authctxt->style) == 0) {
+               xfree(authctxt->style);
+               authctxt->style = NULL;
+       }
++      if (strlen(authctxt->role) == 0) {
++              xfree(authctxt->role);
++              authctxt->role = NULL;
++      }
++
++      return (0);
++}
++
++int
++mm_answer_authrole(int sock, Buffer *m)
++{
++      monitor_permit_authentications(1);
++
++      authctxt->role = buffer_get_string(m, NULL);
++      debug3("%s: role=%s",
++          __func__, authctxt->role);
++
++      if (strlen(authctxt->role) == 0) {
++              xfree(authctxt->role);
++              authctxt->role = NULL;
++      }
++
+       return (0);
+ }
+@@ -1437,7 +1463,7 @@
+       res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
+       if (res == 0)
+               goto error;
+-      pty_setowner(authctxt->pw, s->tty);
++      pty_setowner(authctxt->pw, s->tty, authctxt->role);
+       buffer_put_int(m, 1);
+       buffer_put_cstring(m, s->tty);
+Index: b/monitor.h
+===================================================================
+--- a/monitor.h
++++ b/monitor.h
+@@ -30,7 +30,7 @@
+ enum monitor_reqtype {
+       MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
+-      MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
++      MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, MONITOR_REQ_AUTHROLE,
+       MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
+       MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
+       MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
+Index: b/monitor_wrap.c
+===================================================================
+--- a/monitor_wrap.c
++++ b/monitor_wrap.c
+@@ -318,10 +318,10 @@
+       return (banner);
+ }
+-/* Inform the privileged process about service and style */
++/* Inform the privileged process about service, style, and role */
+ void
+-mm_inform_authserv(char *service, char *style)
++mm_inform_authserv(char *service, char *style, char *role)
+ {
+       Buffer m;
+@@ -330,11 +330,29 @@
+       buffer_init(&m);
+       buffer_put_cstring(&m, service);
+       buffer_put_cstring(&m, style ? style : "");
++      buffer_put_cstring(&m, role ? role : "");
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
+       buffer_free(&m);
+ }
++
++/* Inform the privileged process about role */
++
++void
++mm_inform_authrole(char *role)
++{
++      Buffer m;
++
++      debug3("%s entering", __func__);
++
++      buffer_init(&m);
++      buffer_put_cstring(&m, role ? role : "");
++
++      mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
++
++      buffer_free(&m);
++}
+ /* Do the password authentication */
+ int
+Index: b/monitor_wrap.h
+===================================================================
+--- a/monitor_wrap.h
++++ b/monitor_wrap.h
+@@ -41,7 +41,8 @@
+ int mm_is_monitor(void);
+ DH *mm_choose_dh(int, int, int);
+ int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
+-void mm_inform_authserv(char *, char *);
++void mm_inform_authserv(char *, char *, char *);
++void mm_inform_authrole(char *);
+ struct passwd *mm_getpwnamallow(const char *);
+ char *mm_auth2_read_banner(void);
+ int mm_auth_password(struct Authctxt *, char *);
+Index: b/openbsd-compat/port-linux.c
+===================================================================
+--- a/openbsd-compat/port-linux.c
++++ b/openbsd-compat/port-linux.c
+@@ -29,6 +29,12 @@
+ #include <string.h>
+ #include <stdio.h>
++#ifdef WITH_SELINUX
++#include "key.h"
++#include "hostfile.h"
++#include "auth.h"
++#endif
++
+ #include "log.h"
+ #include "xmalloc.h"
+ #include "port-linux.h"
+@@ -58,9 +64,9 @@
+ /* Return the default security context for the given username */
+ static security_context_t
+-ssh_selinux_getctxbyname(char *pwname)
++ssh_selinux_getctxbyname(char *pwname, const char *role)
+ {
+-      security_context_t sc;
++      security_context_t sc = NULL;
+       char *sename = NULL, *lvl = NULL;
+       int r;
+@@ -73,9 +79,16 @@
+ #endif
+ #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+-      r = get_default_context_with_level(sename, lvl, NULL, &sc);
++      if (role != NULL && role[0])
++              r = get_default_context_with_rolelevel(sename, role, lvl, NULL,
++                                                     &sc);
++      else
++              r = get_default_context_with_level(sename, lvl, NULL, &sc);
+ #else
+-      r = get_default_context(sename, NULL, &sc);
++      if (role != NULL && role[0])
++              r = get_default_context_with_role(sename, role, NULL, &sc);
++      else
++              r = get_default_context(sename, NULL, &sc);
+ #endif
+       if (r != 0) {
+@@ -106,7 +119,7 @@
+ /* Set the execution context to the default for the specified user */
+ void
+-ssh_selinux_setup_exec_context(char *pwname)
++ssh_selinux_setup_exec_context(char *pwname, const char *role)
+ {
+       security_context_t user_ctx = NULL;
+@@ -115,7 +128,7 @@
+       debug3("%s: setting execution context", __func__);
+-      user_ctx = ssh_selinux_getctxbyname(pwname);
++      user_ctx = ssh_selinux_getctxbyname(pwname, role);
+       if (setexeccon(user_ctx) != 0) {
+               switch (security_getenforce()) {
+               case -1:
+@@ -137,7 +150,7 @@
+ /* Set the TTY context for the specified user */
+ void
+-ssh_selinux_setup_pty(char *pwname, const char *tty)
++ssh_selinux_setup_pty(char *pwname, const char *tty, const char *role)
+ {
+       security_context_t new_tty_ctx = NULL;
+       security_context_t user_ctx = NULL;
+@@ -148,7 +161,7 @@
+       debug3("%s: setting TTY context on %s", __func__, tty);
+-      user_ctx = ssh_selinux_getctxbyname(pwname);
++      user_ctx = ssh_selinux_getctxbyname(pwname, role);
+       /* XXX: should these calls fatal() upon failure in enforcing mode? */
+Index: b/openbsd-compat/port-linux.h
+===================================================================
+--- a/openbsd-compat/port-linux.h
++++ b/openbsd-compat/port-linux.h
+@@ -21,8 +21,8 @@
+ #ifdef WITH_SELINUX
+ int ssh_selinux_enabled(void);
+-void ssh_selinux_setup_pty(char *, const char *);
+-void ssh_selinux_setup_exec_context(char *);
++void ssh_selinux_setup_pty(char *, const char *, const char *);
++void ssh_selinux_setup_exec_context(char *, const char *);
+ void ssh_selinux_change_context(const char *);
+ void ssh_selinux_setfscreatecon(const char *);
+ #endif
+Index: b/platform.c
+===================================================================
+--- a/platform.c
++++ b/platform.c
+@@ -134,7 +134,7 @@
+  * called if sshd is running as root.
+  */
+ void
+-platform_setusercontext_post_groups(struct passwd *pw)
++platform_setusercontext_post_groups(struct passwd *pw, const char *role)
+ {
+ #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
+       /*
+@@ -181,7 +181,7 @@
+       }
+ #endif /* HAVE_SETPCRED */
+ #ifdef WITH_SELINUX
+-      ssh_selinux_setup_exec_context(pw->pw_name);
++      ssh_selinux_setup_exec_context(pw->pw_name, role);
+ #endif
+ }
+Index: b/platform.h
+===================================================================
+--- a/platform.h
++++ b/platform.h
+@@ -26,7 +26,7 @@
+ void platform_post_fork_child(void);
+ int  platform_privileged_uidswap(void);
+ void platform_setusercontext(struct passwd *);
+-void platform_setusercontext_post_groups(struct passwd *);
++void platform_setusercontext_post_groups(struct passwd *, const char *);
+ char *platform_get_krb5_client(const char *);
+ char *platform_krb5_get_principal_name(const char *);
+Index: b/session.c
+===================================================================
+--- a/session.c
++++ b/session.c
+@@ -1471,7 +1471,7 @@
+ /* Set login name, uid, gid, and groups. */
+ void
+-do_setusercontext(struct passwd *pw)
++do_setusercontext(struct passwd *pw, const char *role)
+ {
+       char *chroot_path, *tmp;
+@@ -1499,7 +1499,7 @@
+               endgrent();
+ #endif
+-              platform_setusercontext_post_groups(pw);
++              platform_setusercontext_post_groups(pw, role);
+               if (options.chroot_directory != NULL &&
+                   strcasecmp(options.chroot_directory, "none") != 0) {
+@@ -1625,7 +1625,7 @@
+       /* Force a password change */
+       if (s->authctxt->force_pwchange) {
+-              do_setusercontext(pw);
++              do_setusercontext(pw, s->authctxt->role);
+               child_close_fds();
+               do_pwchange(s);
+               exit(1);
+@@ -1652,7 +1652,7 @@
+               /* When PAM is enabled we rely on it to do the nologin check */
+               if (!options.use_pam)
+                       do_nologin(pw);
+-              do_setusercontext(pw);
++              do_setusercontext(pw, s->authctxt->role);
+               /*
+                * PAM session modules in do_setusercontext may have
+                * generated messages, so if this in an interactive
+@@ -2064,7 +2064,7 @@
+       tty_parse_modes(s->ttyfd, &n_bytes);
+       if (!use_privsep)
+-              pty_setowner(s->pw, s->tty);
++              pty_setowner(s->pw, s->tty, s->authctxt->role);
+       /* Set window size from the packet. */
+       pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
+Index: b/session.h
+===================================================================
+--- a/session.h
++++ b/session.h
+@@ -76,7 +76,7 @@
+ Session       *session_new(void);
+ Session       *session_by_tty(char *);
+ void   session_close(Session *);
+-void   do_setusercontext(struct passwd *);
++void   do_setusercontext(struct passwd *, const char *);
+ void   child_set_env(char ***envp, u_int *envsizep, const char *name,
+                      const char *value);
+Index: b/sshd.c
+===================================================================
+--- a/sshd.c
++++ b/sshd.c
+@@ -730,7 +730,7 @@
+       RAND_seed(rnd, sizeof(rnd));
+       /* Drop privileges */
+-      do_setusercontext(authctxt->pw);
++      do_setusercontext(authctxt->pw, authctxt->role);
+  skip:
+       /* It is safe now to apply the key state */
+Index: b/sshpty.c
+===================================================================
+--- a/sshpty.c
++++ b/sshpty.c
+@@ -200,7 +200,7 @@
+ }
+ void
+-pty_setowner(struct passwd *pw, const char *tty)
++pty_setowner(struct passwd *pw, const char *tty, const char *role)
+ {
+       struct group *grp;
+       gid_t gid;
+@@ -227,7 +227,7 @@
+                   strerror(errno));
+ #ifdef WITH_SELINUX
+-      ssh_selinux_setup_pty(pw->pw_name, tty);
++      ssh_selinux_setup_pty(pw->pw_name, tty, role);
+ #endif
+       if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
+Index: b/sshpty.h
+===================================================================
+--- a/sshpty.h
++++ b/sshpty.h
+@@ -24,4 +24,4 @@
+ void   pty_release(const char *);
+ void   pty_make_controlling_tty(int *, const char *);
+ void   pty_change_window_size(int, u_int, u_int, u_int, u_int);
+-void   pty_setowner(struct passwd *, const char *);
++void   pty_setowner(struct passwd *, const char *, const char *);
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644 (file)
index 0000000..2be7cf1
--- /dev/null
@@ -0,0 +1,43 @@
+# GSSAPI
+gssapi.patch
+
+# SELinux
+selinux-role.patch
+
+# Key blacklisting
+ssh-vulnkey.patch
+
+# Keepalive handling
+ssh1-keepalive.patch
+keepalive-extensions.patch
+
+# Message adjustments
+syslog-level-silent.patch
+quieter-signals.patch
+helpful-wait-terminate.patch
+
+# Miscellaneous bug fixes
+user-group-modes.patch
+scp-quoting.patch
+shell-path.patch
+dnssec-sshfp.patch
+
+# Versioning
+package-versioning.patch
+debian-banner.patch
+
+# File system layout
+authorized-keys-man-symlink.patch
+lintian-symlink-pickiness.patch
+
+# Documentation
+openbsd-docs.patch
+ssh-argv0.patch
+doc-hash-tab-completion.patch
+
+# Miscellaneous bug fixes
+auth-log-verbosity.patch
+
+# Debian-specific configuration
+gnome-ssh-askpass2-icon.patch
+debian-config.patch
diff --git a/debian/patches/shell-path.patch b/debian/patches/shell-path.patch
new file mode 100644 (file)
index 0000000..8c54912
--- /dev/null
@@ -0,0 +1,30 @@
+Description: Look for $SHELL on the path for ProxyCommand/LocalCommand
+ There's some debate on the upstream bug about whether POSIX requires this.
+ I (Colin Watson) agree with Vincent and think it does.
+Author: Colin Watson <cjwatson@debian.org>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1494
+Bug-Debian: http://bugs.debian.org/492728
+Last-Update: 2010-02-27
+
+Index: b/sshconnect.c
+===================================================================
+--- a/sshconnect.c
++++ b/sshconnect.c
+@@ -144,7 +144,7 @@
+               /* Execute the proxy command.  Note that we gave up any
+                  extra privileges above. */
+               signal(SIGPIPE, SIG_DFL);
+-              execv(argv[0], argv);
++              execvp(argv[0], argv);
+               perror(argv[0]);
+               exit(1);
+       }
+@@ -1273,7 +1273,7 @@
+       if (pid == 0) {
+               signal(SIGPIPE, SIG_DFL);
+               debug3("Executing %s -c \"%s\"", shell, args);
+-              execl(shell, shell, "-c", args, (char *)NULL);
++              execlp(shell, shell, "-c", args, (char *)NULL);
+               error("Couldn't execute %s -c \"%s\": %s",
+                   shell, args, strerror(errno));
+               _exit(1);
diff --git a/debian/patches/ssh-argv0.patch b/debian/patches/ssh-argv0.patch
new file mode 100644 (file)
index 0000000..a7750ed
--- /dev/null
@@ -0,0 +1,21 @@
+Description: ssh(1): Refer to ssh-argv0(1)
+ Old versions of OpenSSH (up to 2.5 or thereabouts) allowed creating
+ symlinks to ssh with the name of the host you want to connect to.  Debian
+ ships an ssh-argv0 script restoring this feature; this patch refers to its
+ manual page from ssh(1).
+Bug-Debian: http://bugs.debian.org/111341
+Forwarded: not-needed
+Last-Update: 2010-02-28
+
+Index: b/ssh.1
+===================================================================
+--- a/ssh.1
++++ b/ssh.1
+@@ -1411,6 +1411,7 @@
+ .Xr sftp 1 ,
+ .Xr ssh-add 1 ,
+ .Xr ssh-agent 1 ,
++.Xr ssh-argv0 1 ,
+ .Xr ssh-keygen 1 ,
+ .Xr ssh-keyscan 1 ,
+ .Xr ssh-vulnkey 1 ,
diff --git a/debian/patches/ssh-vulnkey.patch b/debian/patches/ssh-vulnkey.patch
new file mode 100644 (file)
index 0000000..4245319
--- /dev/null
@@ -0,0 +1,1382 @@
+Description: Reject vulnerable keys to mitigate Debian OpenSSL flaw
+ In 2008, Debian (and derived distributions such as Ubuntu) shipped an
+ OpenSSL package with a flawed random number generator, causing OpenSSH to
+ generate only a very limited set of keys which were subject to private half
+ precomputation.  To mitigate this, this patch checks key authentications
+ against a blacklist of known-vulnerable keys, and adds a new ssh-vulnkey
+ program which can be used to explicitly check keys against that blacklist.
+ See CVE-2008-0166.
+Author: Colin Watson <cjwatson@ubuntu.com>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1469
+Last-Update: 2010-02-27
+
+Index: b/Makefile.in
+===================================================================
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -26,6 +26,7 @@
+ SFTP_SERVER=$(libexecdir)/sftp-server
+ SSH_KEYSIGN=$(libexecdir)/ssh-keysign
+ SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
++SSH_DATADIR=$(datadir)/ssh
+ PRIVSEP_PATH=@PRIVSEP_PATH@
+ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
+ STRIP_OPT=@STRIP_OPT@
+@@ -38,6 +39,7 @@
+       -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
+       -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
+       -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
++      -D_PATH_SSH_DATADIR=\"$(SSH_DATADIR)\" \
+ CC=@CC@
+ LD=@LD@
+@@ -59,7 +61,7 @@
+ EXEEXT=@EXEEXT@
+ MANFMT=@MANFMT@
+-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-vulnkey$(EXEEXT)
+ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
+       canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
+@@ -93,8 +95,8 @@
+       roaming_common.o roaming_serv.o \
+       sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
+-MANPAGES      = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
+-MANPAGES_IN   = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
++MANPAGES      = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-vulnkey.1.out sshd_config.5.out ssh_config.5.out
++MANPAGES_IN   = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-vulnkey.1 sshd_config.5 ssh_config.5
+ MANTYPE               = @MANTYPE@
+ CONFIGFILES=sshd_config.out ssh_config.out moduli.out
+@@ -171,6 +173,9 @@
+ sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
+       $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
++ssh-vulnkey$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-vulnkey.o
++      $(LD) -o $@ ssh-vulnkey.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
++
+ # test driver for the loginrec code - not built by default
+ logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
+       $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
+@@ -259,6 +264,7 @@
+       $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
++      $(INSTALL) -m 0755 $(STRIP_OPT) ssh-vulnkey$(EXEEXT) $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
+       $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
+       $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+       $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
+@@ -273,6 +279,7 @@
+       $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+       $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
++      $(INSTALL) -m 644 ssh-vulnkey.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+       -rm -f $(DESTDIR)$(bindir)/slogin
+       ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+@@ -354,6 +361,7 @@
+       -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
++      -rm -f $(DESTDIR)$(bindir)/ssh-vulnkey$(EXEEXT)
+       -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
+       -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
+       -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+@@ -366,6 +374,7 @@
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
++      -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-vulnkey.1
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
+       -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
+Index: b/auth-rh-rsa.c
+===================================================================
+--- a/auth-rh-rsa.c
++++ b/auth-rh-rsa.c
+@@ -44,7 +44,7 @@
+ {
+       HostStatus host_status;
+-      if (auth_key_is_revoked(client_host_key))
++      if (auth_key_is_revoked(client_host_key, 0))
+               return 0;
+       /* Check if we would accept it using rhosts authentication. */
+Index: b/auth-rsa.c
+===================================================================
+--- a/auth-rsa.c
++++ b/auth-rsa.c
+@@ -233,7 +233,7 @@
+                           file, linenum, BN_num_bits(key->rsa->n), bits);
+               /* Never accept a revoked key */
+-              if (auth_key_is_revoked(key))
++              if (auth_key_is_revoked(key, 0))
+                       break;
+               /* We have found the desired key. */
+Index: b/auth.c
+===================================================================
+--- a/auth.c
++++ b/auth.c
+@@ -59,6 +59,7 @@
+ #include "servconf.h"
+ #include "key.h"
+ #include "hostfile.h"
++#include "authfile.h"
+ #include "auth.h"
+ #include "auth-options.h"
+ #include "canohost.h"
+@@ -606,10 +607,34 @@
+ /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
+ int
+-auth_key_is_revoked(Key *key)
++auth_key_is_revoked(Key *key, int hostkey)
+ {
+       char *key_fp;
++      if (blacklisted_key(key, &key_fp) == 1) {
++              if (options.permit_blacklisted_keys) {
++                      if (hostkey)
++                              error("Host key %s blacklisted (see "
++                                  "ssh-vulnkey(1)); continuing anyway",
++                                  key_fp);
++                      else
++                              logit("Public key %s from %s blacklisted (see "
++                                  "ssh-vulnkey(1)); continuing anyway",
++                                  key_fp, get_remote_ipaddr());
++                      xfree(key_fp);
++              } else {
++                      if (hostkey)
++                              error("Host key %s blacklisted (see "
++                                  "ssh-vulnkey(1))", key_fp);
++                      else
++                              logit("Public key %s from %s blacklisted (see "
++                                  "ssh-vulnkey(1))",
++                                  key_fp, get_remote_ipaddr());
++                      xfree(key_fp);
++                      return 1;
++              }
++      }
++
+       if (options.revoked_keys_file == NULL)
+               return 0;
+Index: b/auth.h
+===================================================================
+--- a/auth.h
++++ b/auth.h
+@@ -174,7 +174,7 @@
+ FILE  *auth_openkeyfile(const char *, struct passwd *, int);
+ FILE  *auth_openprincipals(const char *, struct passwd *, int);
+-int    auth_key_is_revoked(Key *);
++int    auth_key_is_revoked(Key *, int);
+ HostStatus
+ check_key_in_hostfiles(struct passwd *, Key *, const char *,
+Index: b/auth2-hostbased.c
+===================================================================
+--- a/auth2-hostbased.c
++++ b/auth2-hostbased.c
+@@ -146,7 +146,7 @@
+       int len;
+       char *fp;
+-      if (auth_key_is_revoked(key))
++      if (auth_key_is_revoked(key, 0))
+               return 0;
+       resolvedname = get_canonical_hostname(options.use_dns);
+Index: b/auth2-pubkey.c
+===================================================================
+--- a/auth2-pubkey.c
++++ b/auth2-pubkey.c
+@@ -439,9 +439,10 @@
+       u_int success, i;
+       char *file;
+-      if (auth_key_is_revoked(key))
++      if (auth_key_is_revoked(key, 0))
+               return 0;
+-      if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
++      if (key_is_cert(key) &&
++          auth_key_is_revoked(key->cert->signature_key, 0))
+               return 0;
+       success = user_cert_trusted_ca(pw, key);
+Index: b/authfile.c
+===================================================================
+--- a/authfile.c
++++ b/authfile.c
+@@ -68,6 +68,7 @@
+ #include "rsa.h"
+ #include "misc.h"
+ #include "atomicio.h"
++#include "pathnames.h"
+ #define MAX_KEY_FILE_SIZE     (1024 * 1024)
+@@ -944,3 +945,140 @@
+       return ret;
+ }
++/* Scan a blacklist of known-vulnerable keys in blacklist_file. */
++static int
++blacklisted_key_in_file(Key *key, const char *blacklist_file, char **fp)
++{
++      int fd = -1;
++      char *dgst_hex = NULL;
++      char *dgst_packed = NULL, *p;
++      int i;
++      size_t line_len;
++      struct stat st;
++      char buf[256];
++      off_t start, lower, upper;
++      int ret = 0;
++
++      debug("Checking blacklist file %s", blacklist_file);
++      fd = open(blacklist_file, O_RDONLY);
++      if (fd < 0) {
++              ret = -1;
++              goto out;
++      }
++
++      dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++      /* Remove all colons */
++      dgst_packed = xcalloc(1, strlen(dgst_hex) + 1);
++      for (i = 0, p = dgst_packed; dgst_hex[i]; i++)
++              if (dgst_hex[i] != ':')
++                      *p++ = dgst_hex[i];
++      /* Only compare least-significant 80 bits (to keep the blacklist
++       * size down)
++       */
++      line_len = strlen(dgst_packed + 12);
++      if (line_len > 32)
++              goto out;
++
++      /* Skip leading comments */
++      start = 0;
++      for (;;) {
++              ssize_t r;
++              char *newline;
++
++              r = atomicio(read, fd, buf, sizeof(buf));
++              if (r <= 0)
++                      goto out;
++              if (buf[0] != '#')
++                      break;
++
++              newline = memchr(buf, '\n', sizeof(buf));
++              if (!newline)
++                      goto out;
++              start += newline + 1 - buf;
++              if (lseek(fd, start, SEEK_SET) < 0)
++                      goto out;
++      }
++
++      /* Initialise binary search record numbers */
++      if (fstat(fd, &st) < 0)
++              goto out;
++      lower = 0;
++      upper = (st.st_size - start) / (line_len + 1);
++
++      while (lower != upper) {
++              off_t cur;
++              int cmp;
++
++              cur = lower + (upper - lower) / 2;
++
++              /* Read this line and compare to digest; this is
++               * overflow-safe since cur < max(off_t) / (line_len + 1) */
++              if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
++                      break;
++              if (atomicio(read, fd, buf, line_len) != line_len)
++                      break;
++              cmp = memcmp(buf, dgst_packed + 12, line_len);
++              if (cmp < 0) {
++                      if (cur == lower)
++                              break;
++                      lower = cur;
++              } else if (cmp > 0) {
++                      if (cur == upper)
++                              break;
++                      upper = cur;
++              } else {
++                      debug("Found %s in blacklist", dgst_hex);
++                      ret = 1;
++                      break;
++              }
++      }
++
++out:
++      if (dgst_packed)
++              xfree(dgst_packed);
++      if (ret != 1 && dgst_hex) {
++              xfree(dgst_hex);
++              dgst_hex = NULL;
++      }
++      if (fp)
++              *fp = dgst_hex;
++      if (fd >= 0)
++              close(fd);
++      return ret;
++}
++
++/*
++ * Scan blacklists of known-vulnerable keys. If a vulnerable key is found,
++ * its fingerprint is returned in *fp, unless fp is NULL.
++ */
++int
++blacklisted_key(Key *key, char **fp)
++{
++      Key *public;
++      char *blacklist_file;
++      int ret, ret2;
++
++      public = key_demote(key);
++      if (public->type == KEY_RSA1)
++              public->type = KEY_RSA;
++
++      xasprintf(&blacklist_file, "%s.%s-%u",
++          _PATH_BLACKLIST, key_type(public), key_size(public));
++      ret = blacklisted_key_in_file(public, blacklist_file, fp);
++      xfree(blacklist_file);
++      if (ret > 0) {
++              key_free(public);
++              return ret;
++      }
++
++      xasprintf(&blacklist_file, "%s.%s-%u",
++          _PATH_BLACKLIST_CONFIG, key_type(public), key_size(public));
++      ret2 = blacklisted_key_in_file(public, blacklist_file, fp);
++      xfree(blacklist_file);
++      if (ret2 > ret)
++              ret = ret2;
++
++      key_free(public);
++      return ret;
++}
++
+Index: b/authfile.h
+===================================================================
+--- a/authfile.h
++++ b/authfile.h
+@@ -28,4 +28,6 @@
+ int    key_perm_ok(int, const char *);
+ int    key_in_file(Key *, const char *, int);
++int    blacklisted_key(Key *key, char **fp);
++
+ #endif
+Index: b/pathnames.h
+===================================================================
+--- a/pathnames.h
++++ b/pathnames.h
+@@ -18,6 +18,10 @@
+ #define SSHDIR                                ETCDIR "/ssh"
+ #endif
++#ifndef _PATH_SSH_DATADIR
++#define _PATH_SSH_DATADIR             "/usr/share/ssh"
++#endif
++
+ #ifndef _PATH_SSH_PIDDIR
+ #define _PATH_SSH_PIDDIR              "/var/run"
+ #endif
+@@ -44,6 +48,9 @@
+ /* Backwards compatibility */
+ #define _PATH_DH_PRIMES                       SSHDIR "/primes"
++#define _PATH_BLACKLIST                       _PATH_SSH_DATADIR "/blacklist"
++#define _PATH_BLACKLIST_CONFIG                SSHDIR "/blacklist"
++
+ #ifndef _PATH_SSH_PROGRAM
+ #define _PATH_SSH_PROGRAM             "/usr/bin/ssh"
+ #endif
+Index: b/readconf.c
+===================================================================
+--- a/readconf.c
++++ b/readconf.c
+@@ -125,6 +125,7 @@
+       oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
+       oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
+       oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
++      oUseBlacklistedKeys,
+       oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
+       oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+       oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+@@ -158,6 +159,7 @@
+       { "passwordauthentication", oPasswordAuthentication },
+       { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
+       { "kbdinteractivedevices", oKbdInteractiveDevices },
++      { "useblacklistedkeys", oUseBlacklistedKeys },
+       { "rsaauthentication", oRSAAuthentication },
+       { "pubkeyauthentication", oPubkeyAuthentication },
+       { "dsaauthentication", oPubkeyAuthentication },             /* alias */
+@@ -489,6 +491,10 @@
+               intptr = &options->challenge_response_authentication;
+               goto parse_flag;
++      case oUseBlacklistedKeys:
++              intptr = &options->use_blacklisted_keys;
++              goto parse_flag;
++
+       case oGssAuthentication:
+               intptr = &options->gss_authentication;
+               goto parse_flag;
+@@ -1180,6 +1186,7 @@
+       options->kbd_interactive_devices = NULL;
+       options->rhosts_rsa_authentication = -1;
+       options->hostbased_authentication = -1;
++      options->use_blacklisted_keys = -1;
+       options->batch_mode = -1;
+       options->check_host_ip = -1;
+       options->strict_host_key_checking = -1;
+@@ -1290,6 +1297,8 @@
+               options->rhosts_rsa_authentication = 0;
+       if (options->hostbased_authentication == -1)
+               options->hostbased_authentication = 0;
++      if (options->use_blacklisted_keys == -1)
++              options->use_blacklisted_keys = 0;
+       if (options->batch_mode == -1)
+               options->batch_mode = 0;
+       if (options->check_host_ip == -1)
+Index: b/readconf.h
+===================================================================
+--- a/readconf.h
++++ b/readconf.h
+@@ -58,6 +58,7 @@
+       int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
+       char    *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
+       int     zero_knowledge_password_authentication; /* Try jpake */
++      int     use_blacklisted_keys;   /* If true, send */
+       int     batch_mode;     /* Batch mode: do not ask for passwords. */
+       int     check_host_ip;  /* Also keep track of keys for IP address */
+       int     strict_host_key_checking;       /* Strict host key checking. */
+Index: b/servconf.c
+===================================================================
+--- a/servconf.c
++++ b/servconf.c
+@@ -104,6 +104,7 @@
+       options->password_authentication = -1;
+       options->kbd_interactive_authentication = -1;
+       options->challenge_response_authentication = -1;
++      options->permit_blacklisted_keys = -1;
+       options->permit_empty_passwd = -1;
+       options->permit_user_env = -1;
+       options->use_login = -1;
+@@ -242,6 +243,8 @@
+               options->kbd_interactive_authentication = 0;
+       if (options->challenge_response_authentication == -1)
+               options->challenge_response_authentication = 1;
++      if (options->permit_blacklisted_keys == -1)
++              options->permit_blacklisted_keys = 0;
+       if (options->permit_empty_passwd == -1)
+               options->permit_empty_passwd = 0;
+       if (options->permit_user_env == -1)
+@@ -318,7 +321,7 @@
+       sListenAddress, sAddressFamily,
+       sPrintMotd, sPrintLastLog, sIgnoreRhosts,
+       sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+-      sStrictModes, sEmptyPasswd, sTCPKeepAlive,
++      sStrictModes, sPermitBlacklistedKeys, sEmptyPasswd, sTCPKeepAlive,
+       sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
+       sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+       sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
+@@ -428,6 +431,7 @@
+       { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
+       { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
+       { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
++      { "permitblacklistedkeys", sPermitBlacklistedKeys, SSHCFG_GLOBAL },
+       { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
+       { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
+       { "uselogin", sUseLogin, SSHCFG_GLOBAL },
+@@ -1047,6 +1051,10 @@
+               intptr = &options->tcp_keep_alive;
+               goto parse_flag;
++      case sPermitBlacklistedKeys:
++              intptr = &options->permit_blacklisted_keys;
++              goto parse_flag;
++
+       case sEmptyPasswd:
+               intptr = &options->permit_empty_passwd;
+               goto parse_flag;
+@@ -1773,6 +1781,7 @@
+       dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
+       dump_cfg_fmtint(sStrictModes, o->strict_modes);
+       dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
++      dump_cfg_fmtint(sPermitBlacklistedKeys, o->permit_blacklisted_keys);
+       dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
+       dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
+       dump_cfg_fmtint(sUseLogin, o->use_login);
+Index: b/servconf.h
+===================================================================
+--- a/servconf.h
++++ b/servconf.h
+@@ -113,6 +113,7 @@
+       int     challenge_response_authentication;
+       int     zero_knowledge_password_authentication;
+                                       /* If true, permit jpake auth */
++      int     permit_blacklisted_keys;        /* If true, permit */
+       int     permit_empty_passwd;    /* If false, do not permit empty
+                                        * passwords. */
+       int     permit_user_env;        /* If true, read ~/.ssh/environment */
+Index: b/ssh-add.1
+===================================================================
+--- a/ssh-add.1
++++ b/ssh-add.1
+@@ -81,6 +81,10 @@
+ .Nm
+ to work.
+ .Pp
++Any keys recorded in the blacklist of known-compromised keys (see
++.Xr ssh-vulnkey 1 )
++will be refused.
++.Pp
+ The options are as follows:
+ .Bl -tag -width Ds
+ .It Fl c
+@@ -183,6 +187,7 @@
+ .Xr ssh 1 ,
+ .Xr ssh-agent 1 ,
+ .Xr ssh-keygen 1 ,
++.Xr ssh-vulnkey 1 ,
+ .Xr sshd 8
+ .Sh AUTHORS
+ OpenSSH is a derivative of the original and free
+Index: b/ssh-add.c
+===================================================================
+--- a/ssh-add.c
++++ b/ssh-add.c
+@@ -142,7 +142,7 @@
+ add_file(AuthenticationConnection *ac, const char *filename)
+ {
+       Key *private, *cert;
+-      char *comment = NULL;
++      char *comment = NULL, *fp;
+       char msg[1024], *certpath;
+       int fd, perms_ok, ret = -1;
+       Buffer keyblob;
+@@ -218,6 +218,14 @@
+       } else {
+               fprintf(stderr, "Could not add identity: %s\n", filename);
+       }
++      if (blacklisted_key(private, &fp) == 1) {
++              fprintf(stderr, "Public key %s blacklisted (see "
++                  "ssh-vulnkey(1)); refusing to add it\n", fp);
++              xfree(fp);
++              key_free(private);
++              xfree(comment);
++              return -1;
++      }
+       /* Now try to add the certificate flavour too */
+Index: b/ssh-keygen.1
+===================================================================
+--- a/ssh-keygen.1
++++ b/ssh-keygen.1
+@@ -670,6 +670,7 @@
+ .Xr ssh 1 ,
+ .Xr ssh-add 1 ,
+ .Xr ssh-agent 1 ,
++.Xr ssh-vulnkey 1 ,
+ .Xr moduli 5 ,
+ .Xr sshd 8
+ .Rs
+Index: b/ssh-vulnkey.1
+===================================================================
+--- /dev/null
++++ b/ssh-vulnkey.1
+@@ -0,0 +1,242 @@
++.\" Copyright (c) 2008 Canonical Ltd.  All rights reserved.
++.\"
++.\" Redistribution and use in source and binary forms, with or without
++.\" modification, are permitted provided that the following conditions
++.\" are met:
++.\" 1. Redistributions of source code must retain the above copyright
++.\"    notice, this list of conditions and the following disclaimer.
++.\" 2. Redistributions in binary form must reproduce the above copyright
++.\"    notice, this list of conditions and the following disclaimer in the
++.\"    documentation and/or other materials provided with the distribution.
++.\"
++.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++.\"
++.Dd $Mdocdate: May 12 2008 $
++.Dt SSH-VULNKEY 1
++.Os
++.Sh NAME
++.Nm ssh-vulnkey
++.Nd check blacklist of compromised keys
++.Sh SYNOPSIS
++.Nm
++.Op Fl q | Fl v
++.Ar file ...
++.Nm
++.Fl a
++.Sh DESCRIPTION
++.Nm
++checks a key against a blacklist of compromised keys.
++.Pp
++A substantial number of keys are known to have been generated using a broken
++version of OpenSSL distributed by Debian which failed to seed its random
++number generator correctly.
++Keys generated using these OpenSSL versions should be assumed to be
++compromised.
++This tool may be useful in checking for such keys.
++.Pp
++Keys that are compromised cannot be repaired; replacements must be generated
++using
++.Xr ssh-keygen 1 .
++Make sure to update
++.Pa authorized_keys
++files on all systems where compromised keys were permitted to authenticate.
++.Pp
++The argument list will be interpreted as a list of paths to public key files
++or
++.Pa authorized_keys
++files.
++If no suitable file is found at a given path,
++.Nm
++will append
++.Pa .pub
++and retry, in case it was given a private key file.
++If no files are given as arguments,
++.Nm
++will check
++.Pa ~/.ssh/id_rsa ,
++.Pa ~/.ssh/id_dsa ,
++.Pa ~/.ssh/identity ,
++.Pa ~/.ssh/authorized_keys
++and
++.Pa ~/.ssh/authorized_keys2 ,
++as well as the system's host keys if readable.
++.Pp
++If
++.Dq -
++is given as an argument,
++.Nm
++will read from standard input.
++This can be used to process output from
++.Xr ssh-keyscan 1 ,
++for example:
++.Pp
++.Dl $ ssh-keyscan -t rsa remote.example.org | ssh-vulnkey -
++.Pp
++Unless the
++.Cm PermitBlacklistedKeys
++option is used,
++.Xr sshd 8
++will reject attempts to authenticate with keys in the compromised list.
++.Pp
++The output from
++.Nm
++looks like this:
++.Pp
++.Bd -literal -offset indent
++/etc/ssh/ssh_host_key:1: COMPROMISED: RSA1 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx root@host
++/home/user/.ssh/id_dsa:1: Not blacklisted: DSA 1024 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /home/user/.ssh/id_dsa.pub
++/home/user/.ssh/authorized_keys:3: Unknown (blacklist file not installed): RSA 1024 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx user@host
++.Ed
++.Pp
++Each line is of the following format (any lines beginning with
++.Dq #
++should be ignored by scripts):
++.Pp
++.Dl Ar filename : Ns Ar line : Ar status : Ar type Ar size Ar fingerprint Ar comment
++.Pp
++It is important to distinguish between the possible values of
++.Ar status :
++.Pp
++.Bl -tag -width Ds
++.It COMPROMISED
++These keys are listed in a blacklist file, normally because their
++corresponding private keys are well-known.
++Replacements must be generated using
++.Xr ssh-keygen 1 .
++.It Not blacklisted
++A blacklist file exists for this key type and size, but this key is not
++listed in it.
++Unless there is some particular reason to believe otherwise, this key
++may be used safely.
++(Note that DSA keys used with the broken version of OpenSSL distributed
++by Debian may be compromised in the event that anyone captured a network
++trace, even if they were generated with a secure version of OpenSSL.)
++.It Unknown (blacklist file not installed)
++No blacklist file exists for this key type and size.
++You should find a suitable published blacklist and install it before
++deciding whether this key is safe to use.
++.El
++.Pp
++The options are as follows:
++.Bl -tag -width Ds
++.It Fl a
++Check keys of all users on the system.
++You will typically need to run
++.Nm
++as root to use this option.
++For each user,
++.Nm
++will check
++.Pa ~/.ssh/id_rsa ,
++.Pa ~/.ssh/id_dsa ,
++.Pa ~/.ssh/identity ,
++.Pa ~/.ssh/authorized_keys
++and
++.Pa ~/.ssh/authorized_keys2 .
++It will also check the system's host keys.
++.It Fl q
++Quiet mode.
++Normally,
++.Nm
++outputs the fingerprint of each key scanned, with a description of its
++status.
++This option suppresses that output.
++.It Fl v
++Verbose mode.
++Normally,
++.Nm
++does not output anything for keys that are not listed in their corresponding
++blacklist file (although it still produces output for keys for which there
++is no blacklist file, since their status is unknown).
++This option causes
++.Nm
++to produce output for all keys.
++.El
++.Sh EXIT STATUS
++.Nm
++will exit zero if any of the given keys were in the compromised list,
++otherwise non-zero.
++.Sh BLACKLIST FILE FORMAT
++The blacklist file may start with comments, on lines starting with
++.Dq # .
++After these initial comments, it must follow a strict format:
++.Pp
++.Bl -bullet -offset indent -compact
++.It
++All the lines must be exactly the same length (20 characters followed by a
++newline) and must be in sorted order.
++.It
++Each line must consist of the lower-case hexadecimal MD5 key fingerprint,
++without colons, and with the first 12 characters removed (that is, the least
++significant 80 bits of the fingerprint).
++.El
++.Pp
++The key fingerprint may be generated using
++.Xr ssh-keygen 1 :
++.Pp
++.Dl $ ssh-keygen -l -f /path/to/key
++.Pp
++This strict format is necessary to allow the blacklist file to be checked
++quickly, using a binary-search algorithm.
++.Sh FILES
++.Bl -tag -width Ds
++.It Pa ~/.ssh/id_rsa
++If present, contains the protocol version 2 RSA authentication identity of
++the user.
++.It Pa ~/.ssh/id_dsa
++If present, contains the protocol version 2 DSA authentication identity of
++the user.
++.It Pa ~/.ssh/identity
++If present, contains the protocol version 1 RSA authentication identity of
++the user.
++.It Pa ~/.ssh/authorized_keys
++If present, lists the public keys (RSA/DSA) that can be used for logging in
++as this user.
++.It Pa ~/.ssh/authorized_keys2
++Obsolete name for
++.Pa ~/.ssh/authorized_keys .
++This file may still be present on some old systems, but should not be
++created if it is missing.
++.It Pa /etc/ssh/ssh_host_rsa_key
++If present, contains the protocol version 2 RSA identity of the system.
++.It Pa /etc/ssh/ssh_host_dsa_key
++If present, contains the protocol version 2 DSA identity of the system.
++.It Pa /etc/ssh/ssh_host_key
++If present, contains the protocol version 1 RSA identity of the system.
++.It Pa /usr/share/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH
++If present, lists the blacklisted keys of type
++.Ar TYPE
++.Pf ( Dq RSA
++or
++.Dq DSA )
++and bit length
++.Ar LENGTH .
++The format of this file is described above.
++RSA1 keys are converted to RSA before being checked in the blacklist.
++Note that the fingerprints of RSA1 keys are computed differently, so you
++will not be able to find them in the blacklist by hand.
++.It Pa /etc/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH
++Same as
++.Pa /usr/share/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH ,
++but may be edited by the system administrator to add new blacklist entries.
++.El
++.Sh SEE ALSO
++.Xr ssh-keygen 1 ,
++.Xr sshd 8
++.Sh AUTHORS
++.An -nosplit
++.An Colin Watson Aq cjwatson@ubuntu.com
++.Pp
++Florian Weimer suggested the option to check keys of all users, and the idea
++of processing
++.Xr ssh-keyscan 1
++output.
+Index: b/ssh-vulnkey.c
+===================================================================
+--- /dev/null
++++ b/ssh-vulnkey.c
+@@ -0,0 +1,387 @@
++/*
++ * Copyright (c) 2008 Canonical Ltd.  All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "includes.h"
++
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <fcntl.h>
++#include <unistd.h>
++
++#include <openssl/evp.h>
++
++#include "xmalloc.h"
++#include "ssh.h"
++#include "log.h"
++#include "key.h"
++#include "authfile.h"
++#include "pathnames.h"
++#include "uidswap.h"
++#include "misc.h"
++
++extern char *__progname;
++
++/* Default files to check */
++static char *default_host_files[] = {
++      _PATH_HOST_RSA_KEY_FILE,
++      _PATH_HOST_DSA_KEY_FILE,
++      _PATH_HOST_KEY_FILE,
++      NULL
++};
++static char *default_files[] = {
++      _PATH_SSH_CLIENT_ID_RSA,
++      _PATH_SSH_CLIENT_ID_DSA,
++      _PATH_SSH_CLIENT_IDENTITY,
++      _PATH_SSH_USER_PERMITTED_KEYS,
++      _PATH_SSH_USER_PERMITTED_KEYS2,
++      NULL
++};
++
++static int verbosity = 0;
++
++static int some_keys = 0;
++static int some_unknown = 0;
++static int some_compromised = 0;
++
++static void
++usage(void)
++{
++      fprintf(stderr, "usage: %s [-aqv] [file ...]\n", __progname);
++      fprintf(stderr, "Options:\n");
++      fprintf(stderr, "  -a          Check keys of all users.\n");
++      fprintf(stderr, "  -q          Quiet mode.\n");
++      fprintf(stderr, "  -v          Verbose mode.\n");
++      exit(1);
++}
++
++static void
++describe_key(const char *filename, u_long linenum, const char *msg,
++    Key *key, const char *comment, int min_verbosity)
++{
++      char *fp;
++
++      fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++      if (verbosity >= min_verbosity) {
++              if (strchr(filename, ':'))
++                      printf("\"%s\"", filename);
++              else
++                      printf("%s", filename);
++              printf(":%lu: %s: %s %u %s %s\n", linenum, msg,
++                  key_type(key), key_size(key), fp, comment);
++      }
++      xfree(fp);
++}
++
++static int
++do_key(const char *filename, u_long linenum,
++    Key *key, const char *comment)
++{
++      Key *public;
++      int blacklist_status;
++      int ret = 1;
++
++      some_keys = 1;
++
++      public = key_demote(key);
++      if (public->type == KEY_RSA1)
++              public->type = KEY_RSA;
++
++      blacklist_status = blacklisted_key(public, NULL);
++      if (blacklist_status == -1) {
++              describe_key(filename, linenum,
++                  "Unknown (blacklist file not installed)", key, comment, 0);
++              some_unknown = 1;
++      } else if (blacklist_status == 1) {
++              describe_key(filename, linenum,
++                  "COMPROMISED", key, comment, 0);
++              some_compromised = 1;
++              ret = 0;
++      } else
++              describe_key(filename, linenum,
++                  "Not blacklisted", key, comment, 1);
++
++      key_free(public);
++
++      return ret;
++}
++
++static int
++do_filename(const char *filename, int quiet_open)
++{
++      FILE *f;
++      char line[SSH_MAX_PUBKEY_BYTES];
++      char *cp;
++      u_long linenum = 0;
++      Key *key;
++      char *comment = NULL;
++      int found = 0, ret = 1;
++
++      /* Copy much of key_load_public's logic here so that we can read
++       * several keys from a single file (e.g. authorized_keys).
++       */
++
++      if (strcmp(filename, "-") != 0) {
++              int save_errno;
++              f = fopen(filename, "r");
++              save_errno = errno;
++              if (!f) {
++                      char pubfile[MAXPATHLEN];
++                      if (strlcpy(pubfile, filename, sizeof pubfile) <
++                          sizeof(pubfile) &&
++                          strlcat(pubfile, ".pub", sizeof pubfile) <
++                          sizeof(pubfile))
++                              f = fopen(pubfile, "r");
++              }
++              errno = save_errno; /* earlier errno is more useful */
++              if (!f) {
++                      if (!quiet_open)
++                              perror(filename);
++                      return -1;
++              }
++              if (verbosity > 0)
++                      printf("# %s\n", filename);
++      } else
++              f = stdin;
++      while (read_keyfile_line(f, filename, line, sizeof(line),
++                  &linenum) != -1) {
++              int i;
++              char *space;
++              int type;
++              char *end;
++
++              /* Chop trailing newline. */
++              i = strlen(line) - 1;
++              if (line[i] == '\n')
++                      line[i] = '\0';
++
++              /* Skip leading whitespace, empty and comment lines. */
++              for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
++                      ;
++              if (!*cp || *cp == '\n' || *cp == '#')
++                      continue;
++
++              /* Cope with ssh-keyscan output and options in
++               * authorized_keys files.
++               */
++              space = strchr(cp, ' ');
++              if (!space)
++                      continue;
++              *space = '\0';
++              type = key_type_from_name(cp);
++              *space = ' ';
++              /* Leading number (RSA1) or valid type (RSA/DSA) indicates
++               * that we have no host name or options to skip.
++               */
++              if ((strtol(cp, &end, 10) == 0 || *end != ' ') &&
++                  type == KEY_UNSPEC) {
++                      int quoted = 0;
++
++                      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 (!*cp)
++                              continue;
++              }
++
++              /* Read and process the key itself. */
++              key = key_new(KEY_RSA1);
++              if (key_read(key, &cp) == 1) {
++                      while (*cp == ' ' || *cp == '\t')
++                              cp++;
++                      if (!do_key(filename, linenum,
++                          key, *cp ? cp : filename))
++                              ret = 0;
++                      found = 1;
++              } else {
++                      key_free(key);
++                      key = key_new(KEY_UNSPEC);
++                      if (key_read(key, &cp) == 1) {
++                              while (*cp == ' ' || *cp == '\t')
++                                      cp++;
++                              if (!do_key(filename, linenum,
++                                  key, *cp ? cp : filename))
++                                      ret = 0;
++                              found = 1;
++                      }
++              }
++              key_free(key);
++      }
++      if (f != stdin)
++              fclose(f);
++
++      if (!found && filename) {
++              key = key_load_public(filename, &comment);
++              if (key) {
++                      if (!do_key(filename, 1, key, comment))
++                              ret = 0;
++                      found = 1;
++              }
++              if (comment)
++                      xfree(comment);
++      }
++
++      return ret;
++}
++
++static int
++do_host(int quiet_open)
++{
++      int i;
++      struct stat st;
++      int ret = 1;
++
++      for (i = 0; default_host_files[i]; i++) {
++              if (stat(default_host_files[i], &st) < 0 && errno == ENOENT)
++                      continue;
++              if (!do_filename(default_host_files[i], quiet_open))
++                      ret = 0;
++      }
++
++      return ret;
++}
++
++static int
++do_user(const char *dir)
++{
++      int i;
++      char *file;
++      struct stat st;
++      int ret = 1;
++
++      for (i = 0; default_files[i]; i++) {
++              xasprintf(&file, "%s/%s", dir, default_files[i]);
++              if (stat(file, &st) < 0 && errno == ENOENT) {
++                      xfree(file);
++                      continue;
++              }
++              if (!do_filename(file, 0))
++                      ret = 0;
++              xfree(file);
++      }
++
++      return ret;
++}
++
++int
++main(int argc, char **argv)
++{
++      int opt, all_users = 0;
++      int ret = 1;
++      extern int optind;
++
++      /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
++      sanitise_stdfd();
++
++      __progname = ssh_get_progname(argv[0]);
++
++      SSLeay_add_all_algorithms();
++      log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
++
++      /* We don't need the RNG ourselves, but symbol references here allow
++       * ld to link us properly.
++       */
++      seed_rng();
++
++      while ((opt = getopt(argc, argv, "ahqv")) != -1) {
++              switch (opt) {
++              case 'a':
++                      all_users = 1;
++                      break;
++              case 'q':
++                      verbosity--;
++                      break;
++              case 'v':
++                      verbosity++;
++                      break;
++              case 'h':
++              default:
++                      usage();
++              }
++      }
++
++      if (all_users) {
++              struct passwd *pw;
++
++              if (!do_host(0))
++                      ret = 0;
++
++              while ((pw = getpwent()) != NULL) {
++                      if (pw->pw_dir) {
++                              temporarily_use_uid(pw);
++                              if (!do_user(pw->pw_dir))
++                                      ret = 0;
++                              restore_uid();
++                      }
++              }
++      } else if (optind == argc) {
++              struct passwd *pw;
++
++              if (!do_host(1))
++                      ret = 0;
++
++              if ((pw = getpwuid(geteuid())) == NULL)
++                      fprintf(stderr, "No user found with uid %u\n",
++                          (u_int)geteuid());
++              else {
++                      if (!do_user(pw->pw_dir))
++                              ret = 0;
++              }
++      } else {
++              while (optind < argc)
++                      if (!do_filename(argv[optind++], 0))
++                              ret = 0;
++      }
++
++      if (verbosity >= 0) {
++              if (some_unknown) {
++                      printf("#\n");
++                      printf("# The status of some keys on your system is unknown.\n");
++                      printf("# You may need to install additional blacklist files.\n");
++              }
++              if (some_compromised) {
++                      printf("#\n");
++                      printf("# Some keys on your system have been compromised!\n");
++                      printf("# You must replace them using ssh-keygen(1).\n");
++              }
++              if (some_unknown || some_compromised) {
++                      printf("#\n");
++                      printf("# See the ssh-vulnkey(1) manual page for further advice.\n");
++              } else if (some_keys && verbosity > 0) {
++                      printf("#\n");
++                      printf("# No blacklisted keys!\n");
++              }
++      }
++
++      return ret;
++}
+Index: b/ssh.1
+===================================================================
+--- a/ssh.1
++++ b/ssh.1
+@@ -1407,6 +1407,7 @@
+ .Xr ssh-agent 1 ,
+ .Xr ssh-keygen 1 ,
+ .Xr ssh-keyscan 1 ,
++.Xr ssh-vulnkey 1 ,
+ .Xr tun 4 ,
+ .Xr hosts.equiv 5 ,
+ .Xr ssh_config 5 ,
+Index: b/ssh.c
+===================================================================
+--- a/ssh.c
++++ b/ssh.c
+@@ -1476,7 +1476,7 @@
+ static void
+ load_public_identity_files(void)
+ {
+-      char *filename, *cp, thishost[NI_MAXHOST];
++      char *filename, *cp, thishost[NI_MAXHOST], *fp;
+       char *pwdir = NULL, *pwname = NULL;
+       int i = 0;
+       Key *public;
+@@ -1533,6 +1533,22 @@
+               public = key_load_public(filename, NULL);
+               debug("identity file %s type %d", filename,
+                   public ? public->type : -1);
++              if (public && blacklisted_key(public, &fp) == 1) {
++                      if (options.use_blacklisted_keys)
++                              logit("Public key %s blacklisted (see "
++                                  "ssh-vulnkey(1)); continuing anyway", fp);
++                      else
++                              logit("Public key %s blacklisted (see "
++                                  "ssh-vulnkey(1)); refusing to send it",
++                                  fp);
++                      xfree(fp);
++                      if (!options.use_blacklisted_keys) {
++                              key_free(public);
++                              xfree(filename);
++                              filename = NULL;
++                              public = NULL;
++                      }
++              }
+               xfree(options.identity_files[i]);
+               identity_files[n_ids] = filename;
+               identity_keys[n_ids] = public;
+Index: b/ssh_config.5
+===================================================================
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -1188,6 +1188,23 @@
+ .Dq any .
+ The default is
+ .Dq any:any .
++.It Cm UseBlacklistedKeys
++Specifies whether
++.Xr ssh 1
++should use keys recorded in its blacklist of known-compromised keys (see
++.Xr ssh-vulnkey 1 )
++for authentication.
++If
++.Dq yes ,
++then attempts to use compromised keys for authentication will be logged but
++accepted.
++It is strongly recommended that this be used only to install new authorized
++keys on the remote system, and even then only with the utmost care.
++If
++.Dq no ,
++then attempts to use compromised keys for authentication will be prevented.
++The default is
++.Dq no .
+ .It Cm UsePrivilegedPort
+ Specifies whether to use a privileged port for outgoing connections.
+ The argument must be
+Index: b/sshconnect2.c
+===================================================================
+--- a/sshconnect2.c
++++ b/sshconnect2.c
+@@ -1489,6 +1489,8 @@
+       /* list of keys stored in the filesystem */
+       for (i = 0; i < options.num_identity_files; i++) {
++              if (options.identity_files[i] == NULL)
++                      continue;
+               key = options.identity_keys[i];
+               if (key && key->type == KEY_RSA1)
+                       continue;
+@@ -1582,7 +1584,7 @@
+                       debug("Offering %s public key: %s", key_type(id->key),
+                           id->filename);
+                       sent = send_pubkey_test(authctxt, id);
+-              } else if (id->key == NULL) {
++              } else if (id->key == NULL && id->filename) {
+                       debug("Trying private key: %s", id->filename);
+                       id->key = load_identity_file(id->filename);
+                       if (id->key != NULL) {
+Index: b/sshd.8
+===================================================================
+--- a/sshd.8
++++ b/sshd.8
+@@ -948,6 +948,7 @@
+ .Xr ssh-agent 1 ,
+ .Xr ssh-keygen 1 ,
+ .Xr ssh-keyscan 1 ,
++.Xr ssh-vulnkey 1 ,
+ .Xr chroot 2 ,
+ .Xr hosts_access 5 ,
+ .Xr login.conf 5 ,
+Index: b/sshd.c
+===================================================================
+--- a/sshd.c
++++ b/sshd.c
+@@ -1598,6 +1598,11 @@
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
++              if (auth_key_is_revoked(key, 1)) {
++                      key_free(key);
++                      sensitive_data.host_keys[i] = NULL;
++                      continue;
++              }
+               switch (key->type) {
+               case KEY_RSA1:
+                       sensitive_data.ssh1_host_key = key;
+Index: b/sshd_config.5
+===================================================================
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -795,6 +795,20 @@
+ Specifies whether password authentication is allowed.
+ The default is
+ .Dq yes .
++.It Cm PermitBlacklistedKeys
++Specifies whether
++.Xr sshd 8
++should allow keys recorded in its blacklist of known-compromised keys (see
++.Xr ssh-vulnkey 1 ) .
++If
++.Dq yes ,
++then attempts to authenticate with compromised keys will be logged but
++accepted.
++If
++.Dq no ,
++then attempts to authenticate with compromised keys will be rejected.
++The default is
++.Dq no .
+ .It Cm PermitEmptyPasswords
+ When password authentication is allowed, it specifies whether the
+ server allows login to accounts with empty password strings.
diff --git a/debian/patches/ssh1-keepalive.patch b/debian/patches/ssh1-keepalive.patch
new file mode 100644 (file)
index 0000000..d5a7fe0
--- /dev/null
@@ -0,0 +1,65 @@
+Description: Partial server keep-alive implementation for SSH1
+Author: Colin Watson <cjwatson@debian.org>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1712
+Last-Update: 2010-02-27
+
+Index: b/clientloop.c
+===================================================================
+--- a/clientloop.c
++++ b/clientloop.c
+@@ -545,16 +545,21 @@
+ static void
+ server_alive_check(void)
+ {
+-      if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
+-              logit("Timeout, server %s not responding.", host);
+-              cleanup_exit(255);
++      if (compat20) {
++              if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
++                      logit("Timeout, server %s not responding.", host);
++                      cleanup_exit(255);
++              }
++              packet_start(SSH2_MSG_GLOBAL_REQUEST);
++              packet_put_cstring("keepalive@openssh.com");
++              packet_put_char(1);     /* boolean: want reply */
++              packet_send();
++              /* Insert an empty placeholder to maintain ordering */
++              client_register_global_confirm(NULL, NULL);
++      } else {
++              packet_send_ignore(0);
++              packet_send();
+       }
+-      packet_start(SSH2_MSG_GLOBAL_REQUEST);
+-      packet_put_cstring("keepalive@openssh.com");
+-      packet_put_char(1);     /* boolean: want reply */
+-      packet_send();
+-      /* Insert an empty placeholder to maintain ordering */
+-      client_register_global_confirm(NULL, NULL);
+ }
+ /*
+@@ -614,7 +619,7 @@
+        */
+       timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
+-      if (options.server_alive_interval > 0 && compat20)
++      if (options.server_alive_interval > 0)
+               timeout_secs = options.server_alive_interval;
+       set_control_persist_exit_time();
+       if (control_persist_exit_time > 0) {
+Index: b/ssh_config.5
+===================================================================
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -1089,7 +1089,10 @@
+ .Cm ServerAliveCountMax
+ is left at the default, if the server becomes unresponsive,
+ ssh will disconnect after approximately 45 seconds.
+-This option applies to protocol version 2 only.
++This option applies to protocol version 2 only; in protocol version
++1 there is no mechanism to request a response from the server to the
++server alive messages, so disconnection is the responsibility of the TCP
++stack.
+ .It Cm ServerAliveInterval
+ Sets a timeout interval in seconds after which if no data has been received
+ from the server,
diff --git a/debian/patches/syslog-level-silent.patch b/debian/patches/syslog-level-silent.patch
new file mode 100644 (file)
index 0000000..90ddca4
--- /dev/null
@@ -0,0 +1,37 @@
+Description: "LogLevel SILENT" compatibility
+ "LogLevel SILENT" (-qq) was introduced in Debian openssh 1:3.0.1p1-1 to
+ match the behaviour of non-free SSH, in which -q does not suppress fatal
+ errors.  However, this was unintentionally broken in 1:4.6p1-2 and nobody
+ complained, so we've dropped most of it.  The parts that remain are basic
+ configuration file compatibility, and an adjustment to "Pseudo-terminal
+ will not be allocated ..." which should be split out into a separate patch.
+Author: Jonathan David Amery <jdamery@ysolde.ucam.org>
+Author: Matthew Vernon <matthew@debian.org>
+Author: Colin Watson <cjwatson@debian.org>
+Last-Update: 2010-03-31
+
+Index: b/log.c
+===================================================================
+--- a/log.c
++++ b/log.c
+@@ -92,6 +92,7 @@
+       LogLevel val;
+ } log_levels[] =
+ {
++      { "SILENT",     SYSLOG_LEVEL_QUIET }, /* compatibility */
+       { "QUIET",      SYSLOG_LEVEL_QUIET },
+       { "FATAL",      SYSLOG_LEVEL_FATAL },
+       { "ERROR",      SYSLOG_LEVEL_ERROR },
+Index: b/ssh.c
+===================================================================
+--- a/ssh.c
++++ b/ssh.c
+@@ -678,7 +678,7 @@
+       /* Do not allocate a tty if stdin is not a tty. */
+       if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
+           options.request_tty != REQUEST_TTY_FORCE) {
+-              if (tty_flag)
++              if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
+                       logit("Pseudo-terminal will not be allocated because "
+                           "stdin is not a terminal.");
+               tty_flag = 0;
diff --git a/debian/patches/user-group-modes.patch b/debian/patches/user-group-modes.patch
new file mode 100644 (file)
index 0000000..01ba055
--- /dev/null
@@ -0,0 +1,202 @@
+Description: Allow harmless group-writability
+ Allow secure files (~/.ssh/config, ~/.ssh/authorized_keys, etc.) to be
+ group-writable, provided that the group in question contains only the
+ file's owner.  Rejected upstream for IMO incorrect reasons (e.g. a
+ misunderstanding about the contents of gr->gr_mem).  Given that
+ per-user groups and umask 002 are the default setup in Debian (for good
+ reasons - this makes operating in setgid directories with other groups
+ much easier), we need to permit this by default.
+Author: Colin Watson <cjwatson@debian.org>
+Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060
+Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347
+Last-Update: 2010-02-27
+
+Index: b/readconf.c
+===================================================================
+--- a/readconf.c
++++ b/readconf.c
+@@ -30,6 +30,8 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <pwd.h>
++#include <grp.h>
+ #include "xmalloc.h"
+ #include "ssh.h"
+@@ -1131,8 +1133,7 @@
+               if (fstat(fileno(f), &sb) == -1)
+                       fatal("fstat %s: %s", filename, strerror(errno));
+-              if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
+-                  (sb.st_mode & 022) != 0))
++              if (!secure_permissions(&sb, getuid()))
+                       fatal("Bad owner or permissions on %s", filename);
+       }
+Index: b/ssh.1
+===================================================================
+--- a/ssh.1
++++ b/ssh.1
+@@ -1298,6 +1298,8 @@
+ .Xr ssh_config 5 .
+ Because of the potential for abuse, this file must have strict permissions:
+ read/write for the user, and not accessible by others.
++It may be group-writable provided that the group in question contains only
++the user.
+ .Pp
+ .It Pa ~/.ssh/environment
+ Contains additional definitions for environment variables; see
+Index: b/ssh_config.5
+===================================================================
+--- a/ssh_config.5
++++ b/ssh_config.5
+@@ -1343,6 +1343,8 @@
+ This file is used by the SSH client.
+ Because of the potential for abuse, this file must have strict permissions:
+ read/write for the user, and not accessible by others.
++It may be group-writable provided that the group in question contains only
++the user.
+ .It Pa /etc/ssh/ssh_config
+ Systemwide configuration file.
+ This file provides defaults for those
+Index: b/auth.c
+===================================================================
+--- a/auth.c
++++ b/auth.c
+@@ -380,8 +380,7 @@
+               user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
+               if (options.strict_modes &&
+                   (stat(user_hostfile, &st) == 0) &&
+-                  ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+-                  (st.st_mode & 022) != 0)) {
++                  !secure_permissions(&st, pw->pw_uid)) {
+                       logit("Authentication refused for %.100s: "
+                           "bad owner or modes for %.200s",
+                           pw->pw_name, user_hostfile);
+@@ -442,8 +441,7 @@
+       /* check the open file to avoid races */
+       if (fstat(fileno(f), &st) < 0 ||
+-          (st.st_uid != 0 && st.st_uid != uid) ||
+-          (st.st_mode & 022) != 0) {
++          !secure_permissions(&st, uid)) {
+               snprintf(err, errlen, "bad ownership or modes for file %s",
+                   buf);
+               return -1;
+@@ -458,8 +456,7 @@
+               strlcpy(buf, cp, sizeof(buf));
+               if (stat(buf, &st) < 0 ||
+-                  (st.st_uid != 0 && st.st_uid != uid) ||
+-                  (st.st_mode & 022) != 0) {
++                  !secure_permissions(&st, uid)) {
+                       snprintf(err, errlen,
+                           "bad ownership or modes for directory %s", buf);
+                       return -1;
+Index: b/misc.c
+===================================================================
+--- a/misc.c
++++ b/misc.c
+@@ -48,8 +48,9 @@
+ #include <netdb.h>
+ #ifdef HAVE_PATHS_H
+ # include <paths.h>
+-#include <pwd.h>
+ #endif
++#include <pwd.h>
++#include <grp.h>
+ #ifdef SSH_TUN_OPENBSD
+ #include <net/if.h>
+ #endif
+@@ -642,6 +643,55 @@
+ }
+ int
++secure_permissions(struct stat *st, uid_t uid)
++{
++      if (st->st_uid != 0 && st->st_uid != uid)
++              return 0;
++      if ((st->st_mode & 002) != 0)
++              return 0;
++      if ((st->st_mode & 020) != 0) {
++              /* If the file is group-writable, the group in question must
++               * have exactly one member, namely the file's owner.
++               * (Zero-member groups are typically used by setgid
++               * binaries, and are unlikely to be suitable.)
++               */
++              struct passwd *pw;
++              struct group *gr;
++              int members = 0;
++
++              gr = getgrgid(st->st_gid);
++              if (!gr)
++                      return 0;
++
++              /* Check primary group memberships. */
++              while ((pw = getpwent()) != NULL) {
++                      if (pw->pw_gid == gr->gr_gid) {
++                              ++members;
++                              if (pw->pw_uid != uid)
++                                      return 0;
++                      }
++              }
++              endpwent();
++
++              pw = getpwuid(st->st_uid);
++              if (!pw)
++                      return 0;
++
++              /* Check supplementary group memberships. */
++              if (gr->gr_mem[0]) {
++                      ++members;
++                      if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
++                          gr->gr_mem[1])
++                              return 0;
++              }
++
++              if (!members)
++                      return 0;
++      }
++      return 1;
++}
++
++int
+ tun_open(int tun, int mode)
+ {
+ #if defined(CUSTOM_SYS_TUN_OPEN)
+Index: b/misc.h
+===================================================================
+--- a/misc.h
++++ b/misc.h
+@@ -103,4 +103,6 @@
+ int    ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
+ int    read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
++int    secure_permissions(struct stat *st, uid_t uid);
++
+ #endif /* _MISC_H */
+Index: b/auth-rhosts.c
+===================================================================
+--- a/auth-rhosts.c
++++ b/auth-rhosts.c
+@@ -256,8 +256,7 @@
+               return 0;
+       }
+       if (options.strict_modes &&
+-          ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+-          (st.st_mode & 022) != 0)) {
++          !secure_permissions(&st, pw->pw_uid)) {
+               logit("Rhosts authentication refused for %.100s: "
+                   "bad ownership or modes for home directory.", pw->pw_name);
+               auth_debug_add("Rhosts authentication refused for %.100s: "
+@@ -283,8 +282,7 @@
+                * allowing access to their account by anyone.
+                */
+               if (options.strict_modes &&
+-                  ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+-                  (st.st_mode & 022) != 0)) {
++                  !secure_permissions(&st, pw->pw_uid)) {
+                       logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
+                           pw->pw_name, buf);
+                       auth_debug_add("Bad file modes for %.200s", buf);
diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in
new file mode 100644 (file)
index 0000000..c619f34
--- /dev/null
@@ -0,0 +1 @@
+[type: gettext/rfc822deb] openssh-server.templates
diff --git a/debian/po/bg.po b/debian/po/bg.po
new file mode 100644 (file)
index 0000000..6b2bc0e
--- /dev/null
@@ -0,0 +1,193 @@
+# translation of bg.po to Bulgarian
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Damyan Ivanov <dmn@debian.org>, 2007, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-19 09:27+0300\n"
+"Last-Translator: Damyan Ivanov <dmn@debian.org>\n"
+"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Да се прекъснат ли текущите връзки по SSH?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Много е вероятно версията на /etc/init.d/ssh, която е инсталирана в момента "
+"да прекъсне активните връзки. Ако извършвате обновяването отдалечено има "
+"опасност връзката да се разпадне и процесът да не завърши нормално."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Това може да бъде поправено ръчно с добавянето на „--pidfile /var/run/sshd."
+"pid“ към командата start-stop-daemon в раздела „stop“ на файла."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Необходим е нов ключ за хоста"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"В момента ключа на хоста в /etc/ssh/ssh_host_key е шифриран с алгоритъма "
+"IDEA. OpenSSH не може да работи с този файл, а програмата ssh-keygen от "
+"старата инсталация не е налична."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Необходимо е да се генерира ръчно нов ключ за хоста."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Забрана на удостоверяването challenge-response?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Изглежда че удостоверяването с парола е забранено в настройката на OpenSSH "
+"сървъра. За пълна забрана на използването на пароли за удостоверяване "
+"(вероятно оставяйки само удостоверяването с публичен ключ) е необходимо да "
+"бъде забранено удостоверяването „challenge-response“. В противен случай е "
+"нужно да се настрои PAM да не позволява удостоверяване чрез файловете с "
+"пароли стил Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Ако удостоверяването chalenge-response е забрането, потребителите няма да "
+"могат да използват пароли за удостоверяване. Ако е разрешено (по "
+"подразбиране), настройката 'PasswordAuthentication no' няма да има ефект, "
+"освен ако не промените настройките за PAM в /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Уязвимите ключове на хоста ще бъдат създадени наново"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Някои от ключовете за услугата OpenSSH на хоста са създадени с версия на "
+"OpenSSL, която използва повреден генератор на случайни числа. Тези ключове "
+"са широко известни, уязвими са към атаки и трябва да бъдат сменени."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Потребителите на системата трябва да бъдат известени за промяната, понеже "
+"при следващият им опит за връзка чрез SSH ще получат предупреждение за "
+"промяна в ключовете на хоста. За да получите отпечатъците на новите ключове "
+"използвайте „ssh-keygen -l -f файл-с-ключ“."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Засегнатите ключове на хоста са:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Възможно е потребителските ключове също да са засегнати от проблема. Можете "
+"да използвате програмата „ssh-vulnkey“ за да ги проверите. За повече "
+"информация погледнете /usr/share/doc/openssh-server/README.compromised-keys."
+"gz."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Създаване на нов файл с настройки за OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Файлът с настройки в тази версия на OpenSSH е силно променен в сравнение "
+#~ "с версията в Debian 'Potato', която изглежда се обновява. Може да бъде "
+#~ "създаден нов файл с настройки (/etc/ssh/sshd.config), който ще работи с "
+#~ "новата версия, но няма да съдържа евентуални промени от стария файл."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Новият файл ще съдържа 'PermitRootLogin yes' (разрешавайки отдалечен "
+#~ "достъп през ssh за административния потребител root). Подробности за "
+#~ "причините за тази настройка има във файла README.Debian."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "Препоръчва се да изберете създаването на нов файл с настройки."
+
+#~ msgid "${HOST_KEYS}"
+#~ msgstr "${HOST_KEYS}"
diff --git a/debian/po/ca.po b/debian/po/ca.po
new file mode 100644 (file)
index 0000000..04bcdea
--- /dev/null
@@ -0,0 +1,352 @@
+#
+# Catalan translation for openssh package.
+# Copyright (C) 2007 Matthew Vernon.
+# This file is distributed under the same license as the openssh package.
+#
+# Aleix Badia i Bosch <abadia@ica.es>, 2004
+# Jordà Polo <jorda@ettin.org>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 1:4.6p1-2\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2007-06-30 01:13+0200\n"
+"Last-Translator: Jordà Polo <jorda@ettin.org>\n"
+"Language-Team: Català <debian-l10n-catalan@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Voleu arriscar-vos a aturar les sessions SSH actives?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"És possible que la versió de «/etc/init.d/ssh» que teniu instal·lada "
+"actualment aturi les instàncies de l'sshd que s'estan executant. Si esteu "
+"actualitzant des d'una sessió SSH, és possible que es talli la connexió i "
+"quedi el procés d'actualització a mitges."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Ho podeu arreglar afegint «--pidfile /var/run/sshd.pid» a la línia «start-stop-"
+"daemon» de la secció «stop» del mateix fitxer."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Nova clau obligatòria"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"L'actual clau de la màquina, a /etc/ssh/ssh_host_key, està xifrada amb "
+"l'algorisme IDEA. OpenSSH no pot gestionar aquest fitxer de clau, i no es "
+"pot trobar l'eina ssh-keygen de la instal·lació d'SSH anterior (non-free)."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Haureu de generar manualment una nova clau per a la màquina."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Voleu desactivar l'autenticació «challenge-response»?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Sembla que l'autenticació per contrasenya està desactivada en l'actual "
+"configuració del servidor OpenSSH. Per tal d'evitar que els usuaris entrin "
+"al sistema utilitzant contrasenyes (i utilitzin només autenticació basada en "
+"clau pública), en les darreres versions d'OpenSSH heu de desactivar "
+"l'autenticació «challenge-response», o altrament assegurar-vos que la "
+"configuració de PAM no permet autenticar mitjançant el fitxer de "
+"contrasenyes de Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Si desactiveu l'autenticació «challenge-response», aleshores els usuaris no "
+"podran entrar utilitzant contrasenyes. Si la deixeu activada (que és l'opció "
+"predeterminada), aleshores «PasswordAuthentication no» no tindrà cap valor a "
+"menys que ajusteu la configuració de PAM a /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Voleu generar un nou fitxer de configuració per a l'OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Els fitxers de configuració de l'OpenSSH s'han modificat considerablement "
+#~ "respecte als de Debian «Potato», versió des de la qual sembla que esteu "
+#~ "actualitzant. Aquest paquet pot generar ara un nou fitxer de configuració "
+#~ "(/etc/sshd/sshd.config), que funcionarà amb la nova versió del servidor "
+#~ "però no contindrà els paràmetres de configuració personalitzats de la "
+#~ "versió anterior."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Tingueu en compte que el nou fitxer de configuració establirà el valor de "
+#~ "«PermitRootLogin» a «yes» (és a dir, qualsevol que conegui la contrasenya "
+#~ "de root podrà connectar-se directament mitjançant ssh). Si us plau, "
+#~ "llegiu el fitxer README.Debian per a més detalls sobre aquesta opció."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "És molt recomanable que trieu generar el nou fitxer de configuració ara."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Avís: heu de crear una nova clau del servidor central"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Avís: el telnetd està instal·lat --- probablement no sigui una bona idea"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Es aconsellable suprimir el paquet telnetd (si no heu d'oferir accés a "
+#~ "telnet) o torneu a instal·lar el paquet telnetd-ssl si més no per "
+#~ "assegurar que les sessions de telnet no enviaran les informació del nom "
+#~ "d'usuari i contrasenya sense xifrar a través de la xarxa."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Avís: el servidor rsh-server està instal·lat --- probablement no sigui "
+#~ "una bona idea"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "si teniu instal·lat l'rsh-server perdreu la seguretat que esperàveu "
+#~ "obtenir instal·lant l'ssh. És aconsellable suprimir el paquet."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "Voleu que el fitxer ssh-keysign s'instal·li SUID root?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr "Podeu instal·lar l'ajudant del ssh-keysign amb el bit SUID definit."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Si definiu l'ssh-keysign SUID podreu utilitzat l'autenticació basada en "
+#~ "l'ordinador central del Protocol 2 de l'SSH."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Si dubteu instal·leu-lo amb el SUID. Si us causa algun problema ho podeu "
+#~ "modificar posteriorment executant l'ordre:  dpkg-reconfigure ssh"
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Permet únicament la versió 2 del protocol d'SSH"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "Aquesta versió de l'OpenSSH suporta la versió 2 del protocol d'ssh, "
+#~ "aquesta versió és molt més segura. És recomanable inhabilitar la versió 1 "
+#~ "del protocol, tot i que això alentirà el funcionament dels ordinadors més "
+#~ "antics i no permetrà les connexions als clients antics (afectarà al "
+#~ "client proporcionat per la \"potato\")."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "Recordeu que les claus que utilitza la versió 1 del protocol són "
+#~ "diferents i no les podreu utilitzar si habiliteu únicament les connexions "
+#~ "de la versió 2 del protocol."
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Si posteriorment canvieu d'opinió respecte a la configuració, podeu "
+#~ "trobar les instruccions per modificar el fitxer sshd_config a README."
+#~ "Debian."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr ""
+#~ "Nota: les opcions de reenviament de les X11 i autorització estan "
+#~ "inhabilitades per defecte."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "Per raons de seguretat  i de forma predeterminada la versió d'ssh de "
+#~ "Debian té les opcions ForwardX11 i ForwardAgent definides a \"off\"."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Ho podeu habilitar pels servidors de confiança, ja sigui en un dels "
+#~ "fitxers de configuració o a través de l'opció de la línia d'ordre -X."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr ""
+#~ "Podeu trobar més informació al fitxer /usr/share/doc/ssh/README.Debian"
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "S'han combinat les claus de l'ssh2 als fitxers de configuració"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "Des de la versió 3 de l'OpenSSH ja no s'utilitzaran fitxers separats per "
+#~ "les claus de l'ssh1 i ssg2. Ja no caldran els fitxer authorized_keys2 i "
+#~ "known_hosts2. Es continuaran llegint per mantenir la compatibilitat amb "
+#~ "les versions anteriors."
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "Voleu executar el servidor d'sshd?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "El paquet conté el client i el servidor d'ssh."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "L'sshd (servidor de l'intèrpret d'ordres segur) s'executarà, normalment, "
+#~ "per permetre l'entrada remota a través de l'ssh."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Podeu inhabilitar l'sshd si voleu utilitzar el client d'ssh únicament per "
+#~ "connexions a l'exterior i no per acceptar connexions remotes."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "S'ha prohibit les opcions d'entorn a les claus."
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "L'OpenSSH inhabilita, per defecte i per evitar diversos atacs (per "
+#~ "exemple LD_PRELOAD), les opcions d'entorn per les claus públiques. Si "
+#~ "utilitzeu aquesta opció al fitxer authorized_keys recordeu que les claus "
+#~ "de la qüestió no funcionaran fins que no se suprimeixi l'opció."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Per tornar a habilitar l'opció definiu \"PermitUserEnvironment yes\" al "
+#~ "fitxer /etc/ssh/sshd_config al finalitzar l'actualització (recordeu la "
+#~ "nota d'avís de la pàgina del manual sshd_config(5)). "
diff --git a/debian/po/cs.po b/debian/po/cs.po
new file mode 100644 (file)
index 0000000..5e023da
--- /dev/null
@@ -0,0 +1,357 @@
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-17 14:49+0200\n"
+"Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
+"Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Chcete riskovat ukončení aktivních SSH spojení?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Stávající verze /etc/init.d/ssh pravděpodobně pozabíjí všechny běžící "
+"instance sshd. Pokud tuto aktualizaci provádíte přes SSH, budete nejspíše "
+"odpojeni a aktualizace skončí na půli cesty."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Můžete to spravit ručním přidáním „--pidfile /var/run/sshd.pid“ na řádek "
+"start-stop-daemon v sekci stop."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Nutný nový serverový klíč"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Aktuální serverový klíč v /etc/ssh/ssh_host_key je šifrovaný algoritmem "
+"IDEA. OpenSSH neumí tento soubor zpracovat a zdá se, že utilita ssh-keygen "
+"ze staré (nesvobodné) instalace SSH není k dispozici."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Musíte ručně vygenerovat nový serverový klíč"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Zakázat autentizaci challenge-response?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Zdá se, že autentizace pomocí hesel je ve vaší stávající konfiguraci OpenSSH "
+"serveru zakázána. Abyste zabránili uživatelům v přihlášení pouze pomocí "
+"hesla, musíte v posledních verzích OpenSSH zakázat autentizaci challenge-"
+"response, nebo jinak zajistit, aby PAM nepovolilo autentizaci vůči unixovému "
+"souboru hesel."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Zakážete-li autentizaci challenge-response, uživatelé se nebudou moci "
+"přihlásit pomocí hesel. Necháte-li ji povolenu (přednastavená odpověď), pak "
+"nebude mít volba „PasswordAuthentication no“ žádný efekt, pokud ovšem "
+"neupravíte nastavení PAM v /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Zranitelné serverové klíče budou přegenerovány"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Některé serverové klíče OpenSSH na tomto systému byly vytvořeny verzí "
+"OpenSSL, která měla narušený generátor náhodných čísel. Ve výsledku jsou "
+"tyto dobře známé klíče předmětem útoků hrubou silou a musí být přegenerovány."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Uživatelé tohoto systému by měli být informováni o změně, protože budou při "
+"příštím přihlášení varováni o změně serverového klíče. Po aktualizaci můžete "
+"zjistit nové otisky serverových klíčů příkazem „ssh-keygen -l -f "
+"SOUBOR_SE_SERVEROVÝM_KLÍČEM“."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Postižené serverové klíče:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Tímto problémem mohou být postiženy také uživatelské klíče. Pro částečnou "
+"kontrolu můžete použít příkaz „ssh-vulnkey“. Více informací naleznete v "
+"souboru /usr/share/doc/openssh-server/README.compromised-keys.gz."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Vytvořit nový konfigurační soubor OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Tato verze OpenSSH má oproti verzi dodávané s Debianem 2.2, kterou nyní "
+#~ "pravděpodobně aktualizujete, značně odlišný konfigurační soubor. Balík "
+#~ "nyní může vytvořit nový konfigurační soubor (/etc/ssh/sshd.config), který "
+#~ "bude fungovat s novou verzí serveru, ale nebude obsahovat žádné úpravy, "
+#~ "které jste provedli ve staré verzi."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "V novém konfiguračním souboru bude parametr PermitRootLogin nastaven na "
+#~ "hodnotu „yes“. To znamená, že se kdokoliv se znalostí rootova hesla může "
+#~ "přihlásit rovnou jako root. Více o tomto rozhodnutí se dozvíte v souboru "
+#~ "README.Debian."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Je vřele doporučeno nechat si nyní vytvořit nový konfigurační soubor."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Varování: musíte vytvořit nový serverový klíč"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr "Varování: je nainstalován telnetd --- to není dobrý nápad"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Doporučujeme buď odstranit balík telnetd (pokud telnet přístup "
+#~ "nepotřebujete), nebo nainstalovat telnetd-ssl, kde je alespoň nějaká "
+#~ "šance, že spojení nebudou po síti zasílat nezašifrovaná jména/hesla/"
+#~ "informace."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr "Varování: je nainstalován rsh-server --- to není dobrý nápad"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "nainstalováním rsh-server si bouráte bezpečnost, kterou jste "
+#~ "pravděpodobně chtěli dosáhnout instalací ssh. Doporučujeme tento balík "
+#~ "odstranit."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "Chcete ssh-keysign nainstalovat jako SUID root?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr ""
+#~ "Můžete si vybrat, zda chcete nainstalovat ssh-keysign s nastaveným SUID "
+#~ "bitem."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Pokud nastavíte ssh-keysign SUID, můžete používat „host-based“ "
+#~ "autentizaci protokolu verze 2."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Pokud jste na pochybách, doporučujeme SUID bit povolit. Pokud zaznamenáte "
+#~ "problémy, můžete nastavení změnit spuštěním:   dpkg-reconfigure ssh"
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Povolit pouze SSH protokol verze 2"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "Tato verze OpenSSH podporuje ssh protokol ve verzi 2, který je mnohem "
+#~ "bezpečnější. Je dobré ssh verze 1 zakázat, nicméně na slabších počítačích "
+#~ "se projeví zpomalení a také tím znemožníte přihlášení starších klientů "
+#~ "(například těch z Debianu 2.2)."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "Také si všimněte, že klíče protokolu verze 1 jsou odlišné a pokud "
+#~ "povolíte pouze protokol verze 2, nebudete je moci použít. "
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Pokud se později rozhodnete jinak, v README.Debian se nachází přesný "
+#~ "návod, jak upravit soubor sshd_config."
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "Klíče ssh2 v konfiguračních souborech byly spojeny"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "OpenSSH verze 3 již nepoužívá oddělené soubory pro klíče verze ssh1 a "
+#~ "ssh2. To znamená, že soubory authorized_keys2 a known_hosts2 již nejsou "
+#~ "potřeba, ovšem z důvodů zachování zpětné kompatibility jsou stále "
+#~ "načítány."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr "POZNÁMKA: Autorizace a přesměrování X11 je standardně vypnuto."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "Z bezpečnostních důvodů má verze ssh v Debianu standardně nastavené "
+#~ "ForwardX11 a ForwardAgent na hodnotu „off“."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Pro servery, kterým důvěřujete, můžete tyto parametry povolit v jednom z "
+#~ "konfiguračních souborů, nebo z příkazové řádky parametrem -X."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr "Více naleznete v /usr/share/doc/ssh/README.Debian"
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "Chcete spustit sshd server?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "Tento balík obsahuje jak klienta ssh, tak server sshd."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "Obvykle se sshd (Secure Shell Server) spouští, aby se vzdálení uživatelé "
+#~ "mohli přihlašovat přes ssh."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Pokud na tomto počítači chcete využívat pouze ssh klienta pro odchozí "
+#~ "spojení, můžete zde sshd zakázat."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "Volby prostředí spojené s klíči jsou zakázány"
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "Pro zamezení určitých typů útoků (např. LD_PRELOAD), tato verze OpenSSH "
+#~ "standardně zabraňuje používat volbu prostředí u veřejných klíčů. Pokud "
+#~ "tuto volbu používáte v souboru authorized_keys, tak postižené klíče "
+#~ "nebudou fungovat, dokud jim tuto volbu nesmažete."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Pro znovupovolení této volby si po aktualizaci přečtěte varování v "
+#~ "manuálové stránce sshd_config(5) a v souboru /etc/ssh/sshd_config zadejte "
+#~ "„PermitUserEnvironment yes“."
diff --git a/debian/po/da.po b/debian/po/da.po
new file mode 100644 (file)
index 0000000..766b82e
--- /dev/null
@@ -0,0 +1,161 @@
+# Danish translation openssh.
+# Copyright (C) 2010 openssh & nedenstående oversættere.
+# This file is distributed under the same license as the openssh package.
+# Claus Hindsgaul <claus.hindsgaul@gmail.com>, 2006.
+# Joe Hansen (joedalton2@yahoo.dk), 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2010-08-12 17:30+01:00\n"
+"Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\n"
+"Language-Team: Danish <debian-l10n-danish@lists.debian.org> \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Vil du risikere at afbryde aktive SSH-forbindelser?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Den udgave af /etc/init.d/ssh, du har installeret, vil sandsynligvis afbryde "
+"alle sshd-instanser. Hvis du foretager denne opgradering via en SSH-session, "
+"vil du højst sandsynlig blive afbrudt og efterlade opgraderingsproceduren "
+"uafsluttet."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Du kan afhjælpe dette ved at tilføje »--pidfile /var/run/sshd.pid« til "
+"linjen start-stop-daemon i stop-afsnittet af filen."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Ny værtsnøgle er krævet"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Den aktuelle værtsnøgle, i /etc/ssh/ssh_host_key, er krypteret med en IDEA-"
+"algoritme. OpenSSH kan ikke håndtere en sådan værtsnøglefil, og værktøjet "
+"ssh-keygen fra den gamle (ikke-frie, 'non-free') SSH-installation lader ikke "
+"til at være tilgængeligt."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Du skal manuelt oprette en ny værtsnøgle."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Slå udfordrings-svar godkendelse fra?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Adgangskodegodkendelse ser ud til at være deaktiveret i din nuværende "
+"OpenSSH-serveropsætning. For at forhindre brugere i at logge ind med "
+"adgangskoder (måske kun med brug af offentlig nøglegodkendelse) med nyere "
+"versioner af OpenSSH, skal du deaktivere udfordrings-svar godkendelse, eller "
+"sikre at din PAM-opsætning ikke tillader godkendelse via Unixadgangskodefil."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Hvis du deaktiverer udfordrings-svar godkendelse, vil brugere ikke være i "
+"stand til at logge ind med adgangskoder. Hvis du lader det være slået til "
+"(standardsvaret), så vil indstillingen 'PasswordAuthentication no' ikke have "
+"nogen effekt, medmindre du også redigerer din PAM-opsætning i /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Sårbare værtsnøgler vil blive oprettet"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Nogle af OpenSSh-serverens værtsnøgler på dette system blev oprettet med en "
+"version af OpenSSL, som havde en ødelagt tilfældighedstalgenerator. Derfor "
+"er disse værtsnøgler fra et velkendt sæt, der er sårbare over for brutale "
+"(brute-force) angreb og skal derfor genskabes."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Brugere af dette system bør informeres om denne ændring, da de vil blive "
+"spurgt om værtsnøgleændringen den næste gang de logger ind. Brug 'ssh-keygen "
+"-l -f HOST_KEY_FILE' efter opgraderingen for at udskrive fingeraftryk på de "
+"nye værtsnøgler."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "De påvirkede værtsnøgler er:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Brugernøgler kan måske også være påvirket af dette problem. Kommandoen 'ssh-"
+"vulnkey' kan bruges som en delvis test vedrørende dette. Se /usr/share/doc/"
+"openssh-server/README.compromised-keys.gz for yderligere detaljer."
diff --git a/debian/po/de.po b/debian/po/de.po
new file mode 100644 (file)
index 0000000..55b363a
--- /dev/null
@@ -0,0 +1,369 @@
+# Translation of openssh debconf templates to German
+# Copyright (C) Helge Kreutzmann <debian@helgefjell.de>, 2006-2008.
+# This file is distributed under the same license as the openssh package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 1:4.7p1-9\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-17 23:09+0200\n"
+"Last-Translator: Helge Kreutzmann <debian@helgefjell.de>\n"
+"Language-Team: de <debian-l10n-german@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Wollen Sie das Beenden aktiver SSH-Sitzungen riskieren?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Die derzeit installierte Version von /etc/init.d/ssh wird vermutlich Ihre "
+"aktiven ssh-Instanzen beenden. Falls Sie dieses Upgrade über eine SSH-"
+"Sitzung durchführen, dann wird die Verbindung wahrscheinlich getrennt und "
+"der Upgrade-Vorgang nicht beendet."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Dieses Problem kann behoben werden, indem »--pidfile /var/run/sshd.pid« an "
+"die start-stop-daemon-Zeile in dem Abschnitt »stop« der Datei /etc/init.d/ssh "
+"manuell hinzugefügt wird."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Neuer Host-Schlüssel verpflichtend"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Der aktuelle Host-Schlüssel in /etc/ssh/ssh_host_key ist mit dem IDEA-"
+"Algorithmus verschlüsselt. OpenSSH kann diese Host-Schlüssel-Datei nicht "
+"verarbeiten und das ssh-keygen-Hilfswerkzeug von der alten (nicht-freien) "
+"SSH-Installation scheint nicht verfügbar zu sein."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Sie müssen manuell einen neuen Host-Schlüssel erzeugen."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Challenge-response-Authentifizierung deaktivieren?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Passwort-Authentifizierung scheint in der aktuellen OpenSSH-Server-"
+"Konfiguration deaktiviert zu sein. Um in neueren Versionen von OpenSSH zu "
+"verhindern, dass Benutzer sich unter Verwendung von Passwörtern anmelden "
+"(möglicherweise stattdessen nur unter Verwendung von Public-Key-"
+"Authentifizierung), müssen Sie Challenge-response-Authentifizierung "
+"deaktivieren oder ansonsten sicherstellen, dass Ihre PAM-Konfiguration keine "
+"Authentifizierung über Unix-Password-Dateien erlaubt."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Falls Sie Challenge-response-Authentifizierung deaktivieren, werden Benutzer "
+"nicht in der Lage sein, sich mit Passwörtern anzumelden. Falls Sie es "
+"aktiviert lassen (die Standard-Antwort) wird die »PasswordAuthentication no«-"
+"Einstellung keinen nützlichen Effekt haben, es sei denn, sie passen auch "
+"Ihre PAM-Konfiguration in /etc/pam.d/ssh an."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Verwundbare Host-Schlüssel werden neu erzeugt"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Einige der OpenSSH-Server-Host-Schlüssel auf diesem System wurden mit einer "
+"Version von OpenSSL erzeugt, die einen defekten Zufallszahlengenerator "
+"hatte. Als Ergebnis stammen diese Host-Schlüssel aus einer wohlbekannten "
+"Menge, unterliegen Rechen- (»brute-force«)-angriffen und müssen neu erstellt "
+"werden."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Die Benutzer dieses Systems sollten über diese Änderung informiert werden, "
+"da sie über die Änderung des Host-Schlüssels bei der nächsten Anmeldung "
+"befragt werden. Führen Sie nach dem Upgrade »ssh-keygen -l -f "
+"HOST_SCHLÜSSEL_DATEI« aus, um die Fingerabdrücke es neuen Host-Schlüssels "
+"anzuzeigen."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Die betroffenen Host-Schlüssel sind:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Die Schüssel der Benutzer könnten auch von diesem Problem betroffen sein. "
+"Der Befehl »ssh-vulnkey« kann dazu verwandt werden, dieses Problem teilweise "
+"zu ermitteln. Lesen Sie /usr/share/doc/openssh-server/README.compromised-"
+"keys.gz für weitere Details."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Eine neue Konfigurationsdatei für OpenSSH erzeugen?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Diese Version von OpenSSH hat eine deutlich geänderte Konfigurationsdatei "
+#~ "gegenüber der in »Potato« ausgelieferten Version, von der Sie anscheinend "
+#~ "ein Upgrade durchführen. Dieses Paket kann jetzt eine neue "
+#~ "Konfigurationsdatei (/etc/ssh/sshd.config) erzeugen, die mit der neuen "
+#~ "Server-Version zusammenarbeitet, aber keine Anpassungen aus der alten "
+#~ "Version enthält."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Bitte beachten Sie, dass die neue Konfigurationsdatei »PermitRootLogin« "
+#~ "auf »yes« setzt (was bedeutet, dass jeder, der das Root-Passwort kennt, "
+#~ "sich direkt via ssh als root anmelden kann). Bitte lesen Sie die Datei "
+#~ "README.Debian für weitergehende Informationen über diese Design-"
+#~ "Entscheidung."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Es wird nachdrücklich empfohlen, dass Sie jetzt eine neue "
+#~ "Konfigurationsdatei erzeugen."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Warnung: Sie müssen einen neuen Host-Schlüssel erzeugen"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr "Warnung: telnetd ist installiert --- wahrscheinlich keine gute Idee"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Wir empfehlen das telnetd Paket zu entfernen (falls Sie keinen telnet "
+#~ "Zugang anbieten) oder telnetd-ssl zu installieren, so daß Sie verhindern "
+#~ "können, daß Login und Passwort unverschlüsselt durch das Netz gesendet "
+#~ "werden."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Warnung: rsh-server ist installiert --- wahrscheinlich keine gute Idee"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "ist es eine schlechte Idee, den rsh-server installiert zu haben, da er "
+#~ "die Sicherheit untergräbt. Wir empfehlen, das Paket zu entfernen."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "Möchten Sie ssh-keysign SUID-Root installieren?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr ""
+#~ "Sie haben die Möglichkeit, den ssh-keysign-Helfer mit gesetzten SUID-Bit "
+#~ "zu installieren."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Falls Sie ssh-keysign SUID installieren, können Sie die Host-basierende "
+#~ "Authentisierung von SSH-Protokoll Version 2 verwenden."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Falls Sie unsicher sind, empfehle ich, mit SUID zu installieren. Falls es "
+#~ "Probleme gibt, können Sie später Ihre Meinung ändern, indem Sie dpkg-"
+#~ "reconfigure ssh aufrufen."
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Nur SSH-Protokoll Version 2 erlauben"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "Diese Version von OpenSSH unterstützt Version 2 des SSH-Protokolls, die "
+#~ "sicherer ist. Es wird empfohlen, Version 1 zu deaktivieren, allerdings "
+#~ "kann dies Vorgänge auf langsamen Maschinen verzögern und alte Clients an "
+#~ "der Verbindungsaufnahme hindern (der ssh-Client von »potato« ist davon "
+#~ "betroffen)."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "Bitte beachten Sie auch, daß sich die für Protokoll 1 verwendeten "
+#~ "Schlüssel unterscheiden und Sie diese daher nicht verwenden können, wenn "
+#~ "Sie nur Protokoll Version 2-Verbindungen erlauben."
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Falls Sie später Ihre Meinung über diese Einstellung ändern, finden Sie "
+#~ "in README.Debian eine Anleitung was Sie mit der sshd_config-Datei machen "
+#~ "müssen."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr "HINWEIS: Weiterleiten von X11 und Berechtigungen ist abgeschaltet."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "Aus Sicherheitsgründen ist bei der Debian-Version von ssh ForwardX11 und "
+#~ "ForwardAgent auf »off« gesetzt."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Sie können dies für Server, denen Sie trauen, entweder per Eintrag in die "
+#~ "Konfigurations-Dateien oder per Kommando-Zeilen Option -X ändern."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr ""
+#~ "Weitere Details können Sie in /usr/share/doc/ssh/README.Debian finden."
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "ssh2-Schlüssel in die Konfigurationsdateien eingefügt"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "Mit Version 3 verwendet OpenSSH nicht mehr separate Dateien für ssh1 und "
+#~ "ssh2 Schlüssel. Dies bedeutet, daß authorized_keys2 und known_hosts2 "
+#~ "nicht mehr benötigt werden. Sie werden noch eingelesen, um "
+#~ "Abwärtskompatibilität zu gewähren."
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "Möchten Sie den sshd Server starten?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "Das Paket enthält sowohl den Client als auch den sshd Server."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "Normalerweise wird der sshd Secure Shell Server für Remote Logins per "
+#~ "sshgestartet."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Wenn Sie nur den ssh client nutzen wollen, um sich mit anderen Rechnern "
+#~ "zu verbinden, und sich nicht per ssh in diesen Computer einloggen wollen, "
+#~ "dann können Sie hier den sshd abschalten."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "Umgebungs-Optionen für Schlüssel wurden missbilligt"
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "Diese Version von OpenSSH deaktiviert standardmäßig die Umgebungsoption "
+#~ "füröffentliche Schlüssel um bestimmte Angriffe (zum Beispiel über "
+#~ "LD_PRELOAD) zu vermeiden. Falls Sie diese Option in einer authorized_keys-"
+#~ "Datei verwenden, beachten Sie, daß die in Frage kommenden Schlüssel nicht "
+#~ "funktionieren werden bis diese Option entfernt wurde."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Um diese Option wieder zu reaktivieren, setzen Sie, unter "
+#~ "Berücksichtigung der Warnung in der sshd_config(5)-Handbuchseite, "
+#~ "»PermitUserEnvironment yes« in /etc/ssh/sshd_config nachdem das Upgrade "
+#~ "erfolgt ist."
diff --git a/debian/po/el.po b/debian/po/el.po
new file mode 100644 (file)
index 0000000..4ca5638
--- /dev/null
@@ -0,0 +1,451 @@
+# translation of el.po to Greek
+# translation of templates.po to Greek
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+#    Developers do not need to manually edit POT or PO files.
+# Konstantinos Margaritis <markos@debian.org>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: el\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2004-10-14 21:34+0300\n"
+"Last-Translator: Konstantinos Margaritis <markos@debian.org>\n"
+"Language-Team: Greek <debian-l10n-greek@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.0.2\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid "Do you want to continue (and risk killing active ssh sessions)?"
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr ""
+"Θέλετε να συνεχίσετε (με κίνδυνο τερματισμού των ενεργών συνεδριών ssh);"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "The version of /etc/init.d/ssh that you have installed, is likely to kill "
+#| "all running sshd instances.  If you are doing this upgrade via an ssh "
+#| "session, that would be a Bad Thing(tm)."
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Η τρέχουσα έκδοση του /etc/init.d/ssh που είναι εγκατεστημένη, πιθανότατα θα "
+"τερματίσει όλες τις συνεδρίες του sshd.  Αν κάνετε αυτήν την αναβάθμιση μέσω "
+"μιας συνεδρίας ssh, αυτό είναι μάλλον κακή ιδέα..."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "You can fix this by adding \"--pidfile /var/run/sshd.pid\" to the start-"
+#| "stop-daemon line in the stop section of the file."
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Μπορείτε να το διορθώσετε αυτό προσθέτοντας \"--pidfile /var/run/sshd.pid\" "
+"στη γραμμή start-stop-daemon στο τμήμα \"stop\" του αρχείου."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Υπάρχει ένα παλαιότερο κλειδί /etc/ssh/ssh_host_key, που είναι "
+"κρυπτογραφημένο με τον αλγόριθμο IDEA. Το OpenSSH δε μπορεί να χειριστεί "
+"αυτό το κλειδί και δεν έχει βρεθεί το εργαλείο ssh-keygen από την παλιά (μη "
+"ελεύθερη) εγκατάσταση του SSH."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+#| msgid "You will need to generate a new host key."
+msgid "You need to manually generate a new host key."
+msgstr "Πρέπει να δημιουργήσετε ένα νέο κλειδί για τον υπολογιστή (host key)."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Να απενεργοποιηθεί η πιστοποίηση challenge-response;"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+#, fuzzy
+#| msgid ""
+#| "Password authentication appears to be disabled in your current OpenSSH "
+#| "server configuration. In order to prevent users from logging in using "
+#| "passwords (perhaps using only public key authentication instead) with "
+#| "recent versions of OpenSSH, you must disable challenge-response "
+#| "authentication, or else ensure that your PAM configuration does not allow "
+#| "Unix password file authentication."
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Η πιστοποίηση με κωδικό είναι απενεργοποιημένη στο τωρινό OpenSSH "
+"εξυπηρετητή. Για να αποτρέψετε την είσοδο τον χρηστών με χρήση κωδικού (για "
+"παράδειγμα να γίνεται χρήση μόνο του δημοσίου κλειδιού) με την πρόσφατες "
+"εκδόσεις του OpenSSH, θα πρέπει να απενεργοποιήσετε την πιστοποίηση "
+"challenge-response ή να επιβεβαιώσετε ότι η διαμόρφωση του PAM δεν επιτρέπει "
+"την πιστοποίηση με αρχείο κωδικών."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Εάν απενεργοποιήσετε την πιστοποίηση challenge-response, οι χρήστες δεν θα "
+"μπορούν να εισέλθουν χρησιμοποιώντας τον κωδικό τους. Εάν το αφήσετε "
+"ενεργοποιημένο (προεπιλογή), τότε η επιλογή 'PasswordAuthetication no' δεν "
+"θα επιδρά εκτός και εάν ρυθμίσετε και το PAM στο αρχείο /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+
+#, fuzzy
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Δημιουργία νέου αρχείου ρυθμίσεων"
+
+#, fuzzy
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Αυτή η έκδοση του OpenSSH έχει σημαντικά διαφοροποιημένο αρχείο ρυθμίσεων "
+#~ "από την έκδοση που περιλαμβάνεται στη διανομή 'Potato' του Debian, από "
+#~ "την οποία φαίνεται ότι πραγματοποιείτε την αναβάθμιση. Στο σημείο αυτό, "
+#~ "σας δίνεται η δυνατότητα να δημιουργήσετε ένα νέο αρχείο ρυθμίσεων (/etc/"
+#~ "ssh/sshd_config), το οποίο χρησιμοποιείται από τη νέα έκδοση του δαίμονα, "
+#~ "αλλά δεν θα περιέχει οποιαδήποτε παραμετροποίηση έχετε ήδη κάνει στην "
+#~ "παλιά έκδοση."
+
+#, fuzzy
+#~| msgid ""
+#~| "Please note that this new configuration file will set the value of "
+#~| "'PermitRootLogin' to yes (meaning that anyone knowing the root password "
+#~| "can ssh directly in as root). It is the opinion of the maintainer that "
+#~| "this is the correct default (see README.Debian for more details), but "
+#~| "you can always edit sshd_config and set it to no if you wish."
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Σημειώστε ότι το νέο αρχείο ρυθμίσεων θα καθορίσει την τιμή της επιλογής "
+#~ "'PermitRootLogin' σε yes (εννοώντας ότι οποιοσδήποτε γνωρίζει τον κωδικό "
+#~ "πρόσβασης του root μπορεί να συνδεθεί ως χρήστης root). Κατά τον "
+#~ "συντηρητή αυτή είναι και η σωστή προκαθορισμένη ρύθμιση (δείτε το README."
+#~ "Debian για περισσότερες λεπτομέρειες), αλλά μπορείτε οποιαδήποτε στιγμή "
+#~ "να αλλάξετε την τιμή σε no στο αρχείο sshd_config."
+
+#, fuzzy
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "Συνιστάται να επιλέξετε την δημιουργία του νέου αρχείου ρυθμίσεων."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr ""
+#~ "Προσοχή: πρέπει να δημιουργήσετε ένα νέο κλειδί για τον υπολογιστή (host "
+#~ "key)"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Προσοχή: είναι ήδη εγκατεστημένος ο telnetd --- όχι και τοσο καλή ιδέα"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Συνιστάται είτε να αφαιρέσετε το πακέτο telnetd (αν δεν είναι πραγματικά "
+#~ "απαραίτητη η πρόσβαση μέσω telnet) ή να εγκαταστήσετε το πακέτο telnetd-"
+#~ "ssl, ώστε να υπάρχει τουλάχιστον μια πιθανότητα οι συνδέσεις telnet να "
+#~ "μην αποστέλλουν μη κρυπτογραφημένες πληροφορίες κωδικών πρόσβασης και "
+#~ "συνεδριών μέσω δικτύου."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Προσοχή: είναι ήδη εγκατεστημένος ο rsh-server --- όχι και τοσο καλή ιδέα"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "Η παρουσία του rsh-server υπονομεύει την ασφάλεια του συστήματος, την "
+#~ "οποία θέλετε να εξασφαλίσετε με την εγκατάσταση του ssh. Συνιστάται η "
+#~ "αφαίρεση αυτού του πακέτου."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "Θέλετε να εγκαταστήσετε το ssh-keysign ως SUID;"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr ""
+#~ "Έχετε την επιλογή της εγκατάστασης του εργαλείου ssh-keysign με το bit "
+#~ "SUID ενεργοποιημένο."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Αν εγκαταστήσετε το ssh-keysign SUID, θα μπορείτε να χρησιμοποιήσετε την "
+#~ "πιστοποίηση υπολογιστή (host-based authentication) του πρωτοκόλου SSH 2."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Αν έχετε αμφιβολίες, συνιστάται να το εγκαταστήσετε SUID.  Αν "
+#~ "διαπιστώσετε προβλήματα μπορείτε να αλλάξετε τη ρύθμιση αυτή εκτελώντας:  "
+#~ "dpkg-reconfigure ssh"
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Να επιτρέπεται μόνο η χρήση του πρωτοκόλλου SSH 2"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "Αυτή η έκδοση του OpenSSH υποστηρίζει την έκδοση 2 του πρωτοκόλλου ssh, "
+#~ "που είναι πολύ πιο ασφαλής.  Συνιστάται η απενεργοποίηση της έκδοσης 1, "
+#~ "ωστόσο αυτό θα γίνει εις βάρος της ταχύτητας σε χαμηλότερων επιδόσεων "
+#~ "συστήματα και θα απαγορέψει τη σύνδεση σε παλαιότερα προγράμματα-πελάτες "
+#~ "(π.χ. ο πελάτης ssh που διανέμεται με την έκδοση \"potato\")."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "Επίσης, σημειώστε ότι τα κλειδιά που χρησιμοποιούνταν στο πρωτόκολλο 1 "
+#~ "είναι διαφορετικά και δε θα είναι δυνατή η χρήση τους αν επιτρέψετε μόνο "
+#~ "τις συνδέσεις με το πρωτόκολλο 2."
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Αν αποφασίσετε διαφορετικά αργότερα για αυτή τη ρύθμιση, το αρχείο README."
+#~ "Debian έχει οδηγίες για την κατάλληλη τροποποίηση του αρχείου sshd_config."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr ""
+#~ "ΣΗΜΕΙΩΣΗ: Η προώθηση των πακέτων X11 και πιστοποίησης είναι "
+#~ "απενεργοποιημένηεξ ορισμού."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "Για λόγους ασφαλείας, η έκδοση του ssh στο Debian έχει τις επιλογές "
+#~ "ForwardX11 και ForwardAgent ορισμένες σε ``off'' εξ ορισμού."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Μπορείτε να τα ενεργοποιήσετε για διακομιστές που εμπιστεύεστε, είτε σε "
+#~ "ένα από τα αρχεία ρυθμίσεων, είτε μέσω της επιλογής -X στη γραμμή εντολών."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr ""
+#~ "Περισσότερες λεπτομέρειες μπορείτε να βρείτε στο αρχείο /usr/share/doc/"
+#~ "ssh/README.Debian"
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "Τα κλειδιά ssh2 συγχωνεύτηκαν στα αρχεία ρυθμίσεων"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "Από την έκδοση 3 και έπειτα, το OpenSSH δεν χρησιμοποιεί πλέον ξεχωριστά "
+#~ "αρχεία για τα κλειδιά των ssh1 και ssh2. Αυτό σημαίνει ότι τα αρχεία "
+#~ "authorized_keys2 και known_hosts2 δεν είναι πλέον απαραίτητα. Θα "
+#~ "χρησιμοποιούνται μόνο για λόγους συμβατότητας."
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "Θέλετε να εκτελέσετε τον δαίμονα sshd;"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "Το πακέτο αυτό περιέχει το πελάτη ssh και το δαίμονα sshd."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "Κανονικά ο δαίμονας sshd (Δαίμονας Ασφαλούς Κελύφους) θα εκτελείται για "
+#~ "απομακρυσμένες συνδέσεις μέσω ssh."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Αν ενδιαφέρεστε μόνο για τη χρήση του πελάτη ssh για εξερχόμενες "
+#~ "συνδέσεις από αυτόν τον υπολογιστή και δεν επιθυμείτε να συνδέεστε σε "
+#~ "αυτόν μέσω ssh, τότε μπορείτε να απενεργοποιήσετε τον sshd στο σημείο "
+#~ "αυτό."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr ""
+#~ "Οι επιλογές περιβάλλοντος κελύφους για τα κλειδιά είναι πλέον παρωχημένες."
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "Αυτή η έκδοση του OpenSSH απενεργοποιεί τις επιλογές περιβάλλοντος "
+#~ "κελύφους για δημόσια κλειδιά εξ ορισμού, ώστε να αποφευχθούν ορισμένου "
+#~ "τύπου επιθέσεις (για παράδειγμα, LD_PRELOAD). Αν χρησιμοποιείτε αυτήν την "
+#~ "επιλογή σε ένα αρχείο authorized_keys, έχετε υπόψιν σας ότι τα "
+#~ "συγκεκριμένα κλειδιά δεν θα χρησιμοποιούνται έως ότου αφαιρεθεί η επιλογή "
+#~ "αυτή."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Για να επανενεργοποιήσετε αυτήν την επιλογή, ορίστε "
+#~ "\"PermitUserEnvironment yes\" στο αρχείο /etc/ssh/sshd_config μετά το "
+#~ "τέλος της αναβάθμισης, έχοντας υπόψιν την προειδοποίηση στη σελίδα "
+#~ "οδηγιών του sshd_config(5)."
+
+#~ msgid "Privilege separation"
+#~ msgstr "Διαχωρισμός Προνομίων"
+
+#~ msgid ""
+#~ "Privilege separation is turned on by default, so if you decide you want "
+#~ "it turned off, you need to add \"UsePrivilegeSeparation no\" to /etc/ssh/"
+#~ "sshd_config."
+#~ msgstr ""
+#~ "Ο διαχωρισμός προνομίων είναι ενεργοποιημένος εξ ορισμού, οπότε αν "
+#~ "αποφασίσετε ότι θέλετε να τον απενεργοποιήσετε, πρέπει να προσθέσετε την "
+#~ "ρύθμιση \"UsePrivilegeSeparation no\" στο αρχείο sshd_config."
+
+#~ msgid "Enable Privilege separation"
+#~ msgstr "Ενεργοποίηση Διαχωρισμού Προνομίων"
+
+#~ msgid ""
+#~ "This version of OpenSSH contains the new privilege separation option. "
+#~ "This significantly reduces the quantity of code that runs as root, and "
+#~ "therefore reduces the impact of security holes in sshd."
+#~ msgstr ""
+#~ "Αυτή η έκδοση του OpenSSH περιλαμβάνει τη νέα επιλογή διαχωρισμού "
+#~ "προνομίων. Αυτό μειώνει δραστικά το ποσοστό των προγραμμάτων που "
+#~ "εκτελούνται ως root, και κατά συνέπεια και τις τρύπες ασφαλείας του sshd."
+
+#~ msgid ""
+#~ "Unfortunately, privilege separation interacts badly with PAM. Any PAM "
+#~ "session modules that need to run as root (pam_mkhomedir, for example) "
+#~ "will fail, and PAM keyboard-interactive authentication won't work."
+#~ msgstr ""
+#~ "Δυστυχώς, ο διαχωρισμός προνομίων δεν συνεργάζεται σωστά με το PAM. "
+#~ "Οποιεσδήποτε μονάδες συνεδρίας (session modules) του PAM που πρέπει να "
+#~ "εκτελεστούν ως root (pam_mkhomedir, για παράδειγμα) θα αποτύχουν, και η "
+#~ "πιστοποίηση μέσω πληκτρολογίου στο PAM δεν θα λειτουργεί."
+
+#~ msgid ""
+#~ "Since you've opted to have me generate an sshd_config file for you, you "
+#~ "can choose whether or not to have privilege separation turned on or not. "
+#~ "Unless you know you need to use PAM features that won't work with this "
+#~ "option, you should enable it."
+#~ msgstr ""
+#~ "Εφόσον έχετε επιλέξει να δημιουργήθεί αυτόματα το αρχείο sshd_config, "
+#~ "μπορείτε να επιλέξετε επίσης αν θέλετε να ενεργοποιήσετε το διαχωρισμό "
+#~ "προνομίων ή όχι. Εκτός αν γνωρίζετε ότι χρειάζεστε να χρησιμοποιήσετε "
+#~ "χαρακτηριστικά του PAM που δε συνεργάζονται με αυτή την επιλογή, "
+#~ "συνιστάται να την ενεργοποιήσετε."
diff --git a/debian/po/es.po b/debian/po/es.po
new file mode 100644 (file)
index 0000000..94667d7
--- /dev/null
@@ -0,0 +1,448 @@
+#
+# openssh debconf translation to spanish
+# Copyright (C) 2003-2007 Software in the Public Interest
+# This file is distributed under the same license as the XXXX package.
+#
+# Changes:
+# - Initial translation
+#    Carlos Valdivia Yagüe <valyag@dat,etsit.upm.es>, 2003
+# - Revision
+#    Javier Fernandez-Sanguino Peña <jfs@computer.org>, 2004
+# - Translation updates
+#    Javier Fernandez-Sanguino Peña <jfs@computer.org>, 2006-2008
+#
+#  Traductores, si no conoce el formato PO, merece la pena leer la 
+#  documentación de gettext, especialmente las secciones dedicadas a este
+#  formato, por ejemplo ejecutando:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+# Equipo de traducción al español, por favor lean antes de traducir
+# los siguientes documentos:
+#
+# - El proyecto de traducción de Debian al español
+#   http://www.debian.org/intl/spanish/coordinacion
+#   especialmente las notas de traducción en
+#   http://www.debian.org/intl/spanish/notas
+#
+# - La guía de traducción de po's de debconf:
+#   /usr/share/doc/po-debconf/README-trans
+#   o http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 3.6.1p2-11\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-22 00:56+0200\n"
+"Last-Translator: Javier Fernandez-Sanguino Peña <jfs@debian.org>\n"
+"Language-Team: Debian L10n Spanish <debian-l10n-spanish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-15\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-POFile-SpellExtra: usr pid PasswordAuthentication PermitRootLogin server\n"
+"X-POFile-SpellExtra: PAM start OpenSSH OpenSSL init sshhostkey daemon var\n"
+"X-POFile-SpellExtra: config pam pidfile vulnkey run Potato keys share stop\n"
+"X-POFile-SpellExtra: gz README ssh sshd doc keygen ARCHIVOCLAVESISTEMA SSH\n"
+"X-POFile-SpellExtra: openssh root compromised\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "¿Desea correr el riesgo de matar las sesiones SSH activas?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"La versión de /etc/init.d/ssh que tiene instalada es muy probable que mate "
+"todas las estancias que están ejecutándose de sshd. Es muy probable que se "
+"le desconecte y el procedimiento de actualización quede a medidas si "
+"continúa y está realizando esta actualizando."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Puede arreglarlo añadiendo manualmente «--pidfile /var/run/sshd.pid» a la "
+"línea «start-stop-daemon», en la sección «stop» del fichero."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Nueva clave de sistema obligatoria"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"La clave actual de su sistema, en /etc/ssh/ssh_host_key, está cifrada con el "
+"algoritmo IDEA. OpenSSH no puede manejar este fichero de clave y tampoco "
+"parece estar disponible la utilidad «ssh-keygen» de la instalación antigua de "
+"SSH (no libre)."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Debe generar manualmente una nueva clave de sistema."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "¿Desea deshabilitar la autenticación basada en desafío-respuesta?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Parece que la configuración actual de su servidor de OpenSSH tiene "
+"deshabilitada la autenticación mediante contraseñas. En las versiones "
+"recientes de OpenSSH para impedir que los usuarios se puedan conectar con "
+"contraseñas (y obligar la utilización de sistemas de autenticación con clave "
+"pública) debe deshabilitar la autenticación basada en desafío-respuesta o "
+"asegurarse de que su configuración PAM no permite autenticación basada en el "
+"fichero de contraseñas Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Si deshabilita la autenticación mediante desafío-respuesta los usuarios no "
+"podrán acceder con contraseñas. Si la deja habilitada (respuesta por "
+"omisión) entonces la opción «PasswordAuthentication no» no tendrá ninguna "
+"utilidad a menos que ajuste su configuración de PAM en «/etc/pam.d/ssh»."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Se regenerarán las claves vulnerables del sistema"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Algunas de las claves de sistema del servidor OpenSSH en este equipo se "
+"generaron con una versión de OpenSSL que tenía un generador de números "
+"aleatorios defectuoso. Consecuentemente, estas claves de sistema son de un "
+"conjunto de claves conocidas y están sujetas a ataques de fuerza bruta por "
+"lo que conviene regenerarlas."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Se informará a los usuarios de este sistema ya que se les informará del "
+"cambio de clave la siguiente vez que se conecten. Utilice «ssh-keygen -l -f "
+"ARCHIVO_CLAVE_SISTEMA» después de la actualización para obtener la huella "
+"digital de las nuevas claves del sistema."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Las claves del sistema afectadas son:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Las claves de los usuarios también pueden estar afectadas por este problema. "
+"Se puede utilizar el programa «ssh-vulnkey» como un test parcial para "
+"detectar el problema. Consulte la información en «/usr/share/doc/openssh-"
+"server/README.compromised-keys.gz» para conocer los detalles."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "¿Desea generar un nuevo fichero de configuración para OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Esta versión de OpenSSH ha cambiado considerablemente el fichero de "
+#~ "configuración del incluido en Debian 'Potato', que es la versión desde la "
+#~ "que parece estar actualizando. Puede crear automáticamente un nuevo "
+#~ "fichero de configuración (/etc/ssh/sshd.config), que funcionará con la "
+#~ "nueva versión del servidor, pero no incluirá las modificaciones que "
+#~ "hiciera en la versión antigua."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Además, recuerde que este nuevo fichero de configuración dirá sí en la "
+#~ "opción «PermitRootLogin», por lo que cualquiera que conozca la contraseña "
+#~ "de root podrá entrar mediante ssh directamente como root. Puede leer "
+#~ "README.Debian si quiere conocer más información sobre esta elección de "
+#~ "diseño."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Es muy recomendable que elija generar un nuevo fichero de configuración "
+#~ "ahora."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Aviso: debe crear una nueva clave para su servidor"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr "Aviso: tiene telnetd instalado (posiblemente no es una buena idea)"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Es muy aconsejable que borre el paquete telnetd si no necesita realmente "
+#~ "ofrecer acceso mediante telnet o instalar telnetd-ssl para que las "
+#~ "contraseñas, nombres de usuario y demás información de las sesiones "
+#~ "telnet no viajen sin cifrar por la red."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Aviso: tiene rsh-server instalado (seguramente, esto no es una buena idea)"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "Tener rsh-server instalado representa un menoscabo de la seguridad que "
+#~ "probablemente desea obtener instalando ssh. Es muy aconsejable que borre "
+#~ "ese paquete."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "¿Quiere instalar ssh-keysign SUID root?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr ""
+#~ "Puede instalar ssh-keysign con el bit SUID (se ejecutará con privilegios "
+#~ "de root)."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Si hace ssh-keysign SUID, podrá usar la autenticación basada en servidor "
+#~ "de la versión 2 del protocolo SSH."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Si duda, se recomienda que lo instale SUID. Si le causa problemas puede "
+#~ "cambiar de opinión posteriormente ejecutando «dpkg-reconfigure ssh»."
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Permitir sólo la versión 2 del protocolo SSH"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "Esta versión de OpenSSH soporta la versión 2 del protocolo ssh, que es "
+#~ "mucho más segura que la anterior. Se recomienda desactivar la versión 1, "
+#~ "aunque funcionará más lento en máquinas modestas y puede impedir que se "
+#~ "conecten clientes antiguos, como, por ejemplo, el incluido en «potato»."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "También tenga en cuenta que las claves utilizadas para el protocolo 1 son "
+#~ "diferentes, por lo que no podrá usarlas si únicamente permite conexiones "
+#~ "mediante la versión 2 del protocolo."
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Si más tarde cambia de opinión, el fichero README.Debian contiene "
+#~ "instrucciones sobre cómo modificar en el fichero sshd_config."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr "NOTA: Reenvío de X11 y Autorización desactivadas por defecto."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "Por razones de seguridad, la versión de ssh de Debian tiene por defecto "
+#~ "ForwardX11 y ForwardAgent desactivadas."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Puede activar estas opciones para los servidores en los que confíe, en "
+#~ "los ficheros de configuración o con la opción -X en línea de comandos."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr "Puede encontrar más detalles en /usr/share/doc/ssh/README.Debian."
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "Las claves ssh2 ya se incluyen en los ficheros de configuración"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "A partir de la versión 3, OpenSSH ya no utiliza ficheros diferentes para "
+#~ "las claves ssh1 y ssh2. Esto quiere decir que ya no son necesarios los "
+#~ "ficheros authorized_keys2 y known_hosts2, aunque aún se seguirán leyendo "
+#~ "para mantener compatibilidad hacia atrás."
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "¿Quiere ejecutar el servidor sshd?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "Este paquete contiene el cliente ssh y el servidor sshd."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "Generalmente, el servidor de ssh (Secure Shell Server) se ejecuta para "
+#~ "permitir el acceso remoto mediante ssh."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Si sólo está interesado en usar el cliente ssh en conexiones salientes "
+#~ "del sistema y no quiere acceder a él mediante ssh, entonces puede "
+#~ "desactivar sshd."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "Las opciones de entorno para las claves, en desuso"
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "Esta versión de OpenSSH tiene desactivada por defecto la opción de "
+#~ "entorno para las claves públicas, para evitar ciertos ataques (por "
+#~ "ejemplo, basados en LD_PRELOAD). Si utiliza esta opción en un fichero "
+#~ "authorized_keys, las claves implicadas no funcionarán hasta que borre la "
+#~ "opción."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Para volver a activar esta opción, escriba «PermitUserEnvironment yes» en /"
+#~ "etc/ssh/sshd_config al terminar la actualización, teniendo en cuenta el "
+#~ "aviso de la página de manual de sshd_config(5)."
+
+#~ msgid "Privilege separation"
+#~ msgstr "Separación de privilegios"
+
+#~ msgid ""
+#~ "Privilege separation is turned on by default, so if you decide you want "
+#~ "it turned off, you need to add \"UsePrivilegeSeparation no\" to /etc/ssh/"
+#~ "sshd_config."
+#~ msgstr ""
+#~ "La separación de privilegios está activa por defecto, por lo que si "
+#~ "decide desactivarla, tiene que añadir «UsePrivilegeSeparation no» al "
+#~ "fichero /etc/ssh/sshd_config."
+
+#~ msgid "Enable Privilege separation"
+#~ msgstr "Activar separación de privilegios"
+
+#~ msgid ""
+#~ "This version of OpenSSH contains the new privilege separation option. "
+#~ "This significantly reduces the quantity of code that runs as root, and "
+#~ "therefore reduces the impact of security holes in sshd."
+#~ msgstr ""
+#~ "Esta versión de OpenSSH incluye una nueva opción de separación de "
+#~ "privilegios que reduce significativamente la cantidad de código que se "
+#~ "ejecuta como root, por lo que reduce el impacto de posibles agujeros de "
+#~ "seguridad en sshd."
+
+#~ msgid ""
+#~ "Unfortunately, privilege separation interacts badly with PAM. Any PAM "
+#~ "session modules that need to run as root (pam_mkhomedir, for example) "
+#~ "will fail, and PAM keyboard-interactive authentication won't work."
+#~ msgstr ""
+#~ "Desafortunadamente, la separación de privilegios no funciona "
+#~ "correctamente con PAM. Cualquier módulo PAM que necesite ejecutarse como "
+#~ "root (como, por ejemplo, pam_mkhomedir) y la autenticación interactiva "
+#~ "PAM con teclado no funcionarán."
+
+#~ msgid ""
+#~ "Since you've opted to have me generate an sshd_config file for you, you "
+#~ "can choose whether or not to have privilege separation turned on or not. "
+#~ "Unless you know you need to use PAM features that won't work with this "
+#~ "option, you should enable it."
+#~ msgstr ""
+#~ "Puesto que ha elegido crear automáticamente el fichero sshd_config, puede "
+#~ "decidir ahora si quiere activar la opción de separación de privilegios. A "
+#~ "menos que necesite usar ciertas características de PAM que no funcionan "
+#~ "con esta opción, debería responder sí a esta pregunta."
+
+#~ msgid ""
+#~ "NB! If you are running a 2.0 series Linux kernel, then privilege "
+#~ "separation will not work at all, and your sshd will fail to start unless "
+#~ "you explicitly turn privilege separation off."
+#~ msgstr ""
+#~ "Nota: Si utiliza un núcleo Linux 2.0, la separación de privilegios "
+#~ "fallará estrepitosamente y sshd no funcionará a no ser que la desactive."
diff --git a/debian/po/eu.po b/debian/po/eu.po
new file mode 100644 (file)
index 0000000..efa16fa
--- /dev/null
@@ -0,0 +1,197 @@
+# translation of openssh-templates.po to basque
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Piarres Beobide <pi@beobide.net>, 2007, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh-templates\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2007-04-27 12:10+0200\n"
+"Last-Translator: Piarres Beobide <pi@beobide.net>\n"
+"Language-Team: librezale <librezale@librezale.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Pootle 0.11\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Irekirik dauden SSH saioak ixteko arriskua hartu nahi duzu?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Instalaturik dagoen /etc/init.d/ssh bertsioak martxan dauden sshd "
+"instantziak hilko ditu. Bertsio berritze hau SSH bidez egiten ari bazara, "
+"ziurrenik deskonektatu egingo zara eta bertsio berritze prozedura ez da "
+"behar bezala amaituko."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Hau eskuz konpondu daiteke  \"--pidfile /var/run/sshd.pid\" gehituaz start-"
+"stop-daemon lerroan fitxategiaren \"stop\" atalean."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Ostalari gako berria beharrezkoa"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"/etc/ssh/ssh_host_key-ko ostalari gakoa IDEA algoritmoaren bidez "
+"enkriptaturik dago. OpenSSH ez da ostalari gako mota hau kudeatzeko gai eta "
+"SSH instalazio zaharreko (ez-librea) ssh-keygen lanabesa dirudienez ez dago "
+"erabilgarri."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Ostalari gako berri bat eskuz sortu behar duzu."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "erronka-erantzun autentifikazioa desgaitu?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Pasahitz egiaztapena dirudienez desgaiturik dago instalaturik dagoen OpenSSH "
+"konfigurazioan. Pasahitzak erabiliaz OpenSSH bertsio berrietan saio hastea "
+"ezintzeko (agian gako publiko autentifikazioa bakarrik erabiliaz), erronka-"
+"erantzun (challenge-response) autentifikazioa desgaitu edo zure PAM "
+"konfigurazioak UNIX pasahitz fitxategi autentifikazioa onartzen ez duela "
+"ziurtatu beharko duzu."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Erronka-erantzun autentifikazioa des\tgaituaz gero erabiltzaileak ez dira "
+"pasahitza erabiliaz saio hasteko gai izango. Berau gaiturik utziaz gero "
+"(lehenetsiriko erantzuna), 'PasswordAuthentication no' aukerak ez du "
+"ondoriorik izango /etc/pam.d/ssh-eko PAM konfigurazioa doitzen ez baduzu."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Ostalari gako ahulak birsortu egingo dira"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Sistema honetako zenbait OpenSSH ostalari gako hondaturiko ausazko zenbasi "
+"sortzaile bat zuen OpenSSL bertsio batez sortuak izan ziren. Hau dela eta, "
+"ostalari gako horiek ezagutza handiko pertsona batek indarrezko erasoei "
+"ahulak dira eta birsortuak izango dira."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Sistema honetako erabiltzaileak aldaketa honetaz ohartu beharko ziren, saio "
+"hasten duten hurrengoan ostalari gako aldaketaz galdetuko zaie eta. 'ssh-"
+"keygen -l -f OSTALARI_GAKO_FITX' erabili bertsio-berritzearen ondoren "
+"ostalari gako berrien hatzmarkak inprimatzeko."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Ostalari gako hauei eragingo die:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Erabiltzaile gakoak ere arazo honengatik eragindak egon daitezke. 'ssh-"
+"vulnkey' komandoak honetarako proba bezala erdi-ziur erabili daiteke. Ikusi /"
+"usr/share/doc/openssh-server/README.compromised-keys.gz xehetasun "
+"gehiagorako."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "OpenSSH-rentzat konfigurazio fitxategi berri bat sortu?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "OpenSSH bertsio honek konfigurazio fitxategia nahiko aldatu du Debian "
+#~ "'Potato' bertsioak banatu zuenetik, dirudienez zu bertsio horretatik "
+#~ "eguneratzen ari zara. Pakete honek konfigurazio fitxategi berri bat sortu "
+#~ "dezake (/etc/ssh/sshd.config) bertsio honetarako funtziona dezan baina ez "
+#~ "ditu zuk bertsio zaharrari egin ahal izan diezazkiokezun "
+#~ "pertsonalizazioak edukiko."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Kontutan izan konfigurazio fitxategi berri honek 'PermitRootLogin' "
+#~ "parametroan balioa 'yes' bezala ezarriko duela (honek root erabiltzaileak "
+#~ "ssh bidez sartzeko aukera emango du). Mesedez irakurri README.Debian "
+#~ "fitxategia ezarpen honen xehetasun gehiagorako."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "Gomendagarria da konfigurazio fitxategi berri bat orain sortzea."
diff --git a/debian/po/fi.po b/debian/po/fi.po
new file mode 100644 (file)
index 0000000..b5e192d
--- /dev/null
@@ -0,0 +1,202 @@
+# translation of fi.po to Finnish
+# openssh translation
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+# Matti Pöllä <mpo@iki.fi>, 2004-2005.
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-17 16:38+0200\n"
+"Last-Translator: Esko Arajärvi <edu@iki.fi>\n"
+"Language-Team: Finnish <debian-l10n-finnish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Haluatko ottaa riskin, että aktiiviset SSH-istunnot tapetaan?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Tiedoston /etc/init.d/ssh asennettuna oleva versio tappaa todennäköisesti "
+"kaikki käynnissä olevat sshd-prosessit. Jos teet tätä päivitystä ssh-"
+"yhteyden yli, yhteytesi luultavasti katkeaa ja päivitysprosessi keskeytyy."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Tämä voidaan korjata lisäämällä merkkijono ”--pidfile /var/run/sshd.pid” "
+"kyseisen tiedoston stop-osion start-stop-daemon-riville."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Uusi järjestelmäavain pakollinen"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Olemassa oleva järjestelmäavain /etc/ssh/ssh_host_key on salattu IDEA-"
+"algoritmilla. OpenSSH ei voi käsitellä tätä järjestelmäavaintiedostoa, eikä "
+"vanhan (ei-vapaan) SSH-asennuksen ssh-keygen-ohjelmaa löydy."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Uuden järjestelmäavaimen (host key) luominen on tarpeen."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Poistetaanko haaste-vaste-autentikointi käytöstä?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"OpenSSH-palvelimen nykyisissä asetuksissa salasana-autentikointi näyttää "
+"olevan poissa käytöstä. Estääksesi kirjautumiset salasanaa käyttäen (esim. "
+"salliaksesi kirjautumisen vain julkista avainta käyttäen), OpenSSH:n uusissa "
+"versioissa haaste-vaste-autentikointi tulee poistaa käytöstä tai muutoin "
+"varmistaa, että PAM-asetukset eivät salli Unixin salasanatiedostoon "
+"perustuvaa autentikointia."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Jos poistat haaste-vaste-autentikoinnin käytöstä, käyttäjät eivät voi "
+"kirjautua käyttäen salasanaa. Jos jätät sen päälle (oletus), asetuksella "
+"”PasswordAuthentication no” ei ole vaikutusta, ellet muuta myös PAM-"
+"asetuksia tiedostossa /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Haavoittuvaiset järjestelmäavaimet luodaan uudelleen"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Jotkin tämän järjestelmän OpenSSH-palvelimen järjestelmäavaimista on luotu "
+"OpenSSL:n versiolla, jossa oli rikkinäinen satunnaislukugeneraattori. Tämän "
+"tuloksena nämä avaimet voidaan murtaa järjestelmällisellä läpikäynnillä ja "
+"ne tulee vaihtaa."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Järjestelmän käyttäjille tulisi tiedottaa tästä muutoksesta, koska heitä "
+"pyydetään hyväksymään muuttunut järjestelmäavain, kun he seuraavan kerran "
+"kirjautuvat järjestelmään. Komennolla ”ssh-keygen -l -f HOST_KEY_FILE” "
+"voidaan tulostaa uusien järjestelmäavainten sormenjäljet päivityksen jälkeen."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Järjestelmäavaimet, joihin tämä vaikuttaa:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Tämä ongelma saattaa vaikuttaa myös käyttäjien avaimiin. Komennolla ”ssh-"
+"vulnkey” voidaan osittain testata tätä. Tiedostossa /usr/share/doc/openssh-"
+"server/README.compromised-keys.gz on lisätietoja."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Luodaanko OpenSSH:lle uusi asetustiedosto?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Tämän OpenSSH:n version käyttämän asetustiedoston muoto poikkeaa "
+#~ "huomattavasti Debianin ”Potato”-julkaisun mukana toimitetusta versiosta, "
+#~ "jota olet päivittämässä. Uusi asetustiedosto (/etc/ssh/sshd.config) "
+#~ "voidaan luoda nyt. Uudet asetukset toimivat uuden palvelinversion kanssa, "
+#~ "mutta vanhaan versioon itse tehdyt muokkaukset menetetään."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Uudessa asetustiedostossa muuttujan ”PermitRootLogin” arvo on "
+#~ "”yes” (tarkoittaen, että kuka tahansa pääkäyttäjän salasanan tietävä voi "
+#~ "kirjautua suoraan ssh:n avulla pääkäyttäjänä). Lisätietoja tästä "
+#~ "valinnasta löytyy (englanniksi) tiedostosta README.Debian."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "Uuden asetustiedoston luominen nyt on erittäin suositeltavaa."
diff --git a/debian/po/fr.po b/debian/po/fr.po
new file mode 100644 (file)
index 0000000..a885690
--- /dev/null
@@ -0,0 +1,211 @@
+# translation of fr.po to French
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+# Christian Perrier <bubulle@debian.org>, 2007, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-15 10:23+0200\n"
+"Last-Translator: Christian Perrier <bubulle@debian.org>\n"
+"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Voulez-vous risquer de rompre les sessions SSH actives ?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"La version de /etc/init.d/ssh actuellement installée va vraisemblablement "
+"interrompre toutes les instances de sshd en cours. Si vous êtes en train de "
+"faire cette mise à niveau à l'aide de SSH, la connexion sera probablement "
+"coupée et la mise à jour sera interrompue."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Cela peut être corrigé en ajoutant « --pidfile /var/run/sshd.pid » à la ligne "
+"« start-stop-daemon » dans /etc/init.d/ssh, dans la section « stop » du "
+"fichier."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Nouvelle clé d'hôte obligatoire"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"La clé d'hôte actuelle, /etc/ssh/ssh_host_key, est chiffrée avec IDEA. "
+"OpenSSH ne peut utiliser ce fichier de clé, et l'utilitaire ssh-keygen de "
+"l'installation précédente (non libre) de SSH n'a pas été trouvé."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Vous devez générer une nouvelle clé d'hôte vous-même."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Faut-il désactiver l'authentification par défi-réponse ?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"L'authentification par mots de passe semble être désactivée dans la "
+"configuration actuelle du serveur OpenSSH. Afin d'empêcher les utilisateurs "
+"de se connecter avec un mot de passe (pour, par exemple n'autoriser que "
+"l'authentification par clé publique) avec les versions récentes d'OpenSSH, "
+"vous devez aussi désactiver l'authentification par défi-réponse, ou alors "
+"vous assurer que votre configuration de PAM n'autorise pas "
+"l'authentification avec le fichier de mots de passe Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Si vous désactivez l'authentification par défi-réponse, alors les "
+"utilisateurs ne pourront pas se connecter en entrant un mot de passe. Si "
+"vous la laissez active (ce qui est la valeur par défaut), alors l'option "
+"« PasswordAuthentication no » n'aura d'effet que si vous ajustez aussi la "
+"configuration de PAM dans /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Recréation des clés d'hôte vulnérables"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Certaines clés d'hôte OpenSSH de ce serveur ont été créées avec une version "
+"d'OpenSSL affligée d'un défaut dans le générateur de nombres aléatoires. En "
+"conséquence, ces clés ont un contenu prévisible et peuvent être vulnérables "
+"à des attaques par force brute. Elles doivent être recréées."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Les utilisateurs de ce système devraient être informés de cette modification "
+"car le système leur signalera le changement de clé d'hôte à leur prochaine "
+"connexion. Vous pouvez utiliser la commande « ssh-keygen -l -f "
+"HOST_KEY_FILE » après la mise à jour pour afficher l'empreinte des nouvelles "
+"clés d'hôte."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Les clés concernées sont les suivantes :"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Les clés OpenSSH des utilisateurs sont aussi potentiellement affectées par "
+"ce problème. La commande « ssh-vulnkey » offre un test partiel pour cette "
+"vulnérabilité. Veuillez consulter le fichier /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz pour plus d'informations."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Faut-il créer un nouveau fichier de configuration pour OpenSSH ?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Cette version d'OpenSSH utilise un fichier de configuration qui a "
+#~ "fortement changé depuis la version contenue dans la distribution Debian "
+#~ "« Potato », depuis laquelle vous semblez faire une mise à jour. Un nouveau "
+#~ "fichier de configuration (/etc/ssh/sshd.config) qui fonctionnera avec la "
+#~ "nouvelle version du serveur peut être créé, mais ne contiendra aucun des "
+#~ "réglages que vous aviez faits avec la version précédente."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Veuillez noter que ce nouveau fichier de configuration positionnera la "
+#~ "valeur de « PermitRootLogin » à « yes » (ce qui signifie que quiconque "
+#~ "connaissant le mot de passe du superutilisateur peut se connecter en tant "
+#~ "que tel sur la machine). Veuillez consulter le fichier README.Debian pour "
+#~ "plus d'informations à propos de ce choix."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Il est fortement recommandé de créer un nouveau fichier de configuration."
diff --git a/debian/po/gl.po b/debian/po/gl.po
new file mode 100644 (file)
index 0000000..acbb341
--- /dev/null
@@ -0,0 +1,236 @@
+# Galician translation of openssh's debconf templates.
+# This file is distributed under the same license as the openssh package.
+#
+# 2006, 2007, 2008 Jacobo Tarrio <jtarrio@debian.org>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-17 10:29+0100\n"
+"Last-Translator: Jacobo Tarrio <jtarrio@debian.org>\n"
+"Language-Team: Galician <proxecto@trasno.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "¿Quere arriscarse a matar as sesións de SSH activas?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"É posible que a versión de /etc/init.d/ssh que instalou vaia matar tódalas "
+"instancias de sshd en execución. Se está a facer esta actualización mediante "
+"unha sesión SSH, é probable que se desconecte e este procedemento de "
+"actualización quede sen rematar."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Isto pode arranxarse engadindo \"--pidfile /var/run/sshd.pid\" á liña start-"
+"stop-daemon da sección stop do ficheiro."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "É obrigatorio ter unha nova clave de servidor"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"A clave de servidor actual, armacenada en /etc/ssh/ssh_host_key, está "
+"cifrada mediante o algoritmo IDEA. OpenSSH non pode xestionar este ficheiro "
+"de clave de servidor, e non semella que estea dispoñible a utilidade ssh-"
+"keygen da anterior instalación de SSH (non libre)."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Ten que xerar unha nova clave de servidor."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "¿Desactivar a autenticación por desafío-resposta?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Semella que a autenticación por contrasinal está desactivada na "
+"configuración actual do servidor de OpenSSH. Para impedir que os usuarios se "
+"conecten empregando contrasinais (empregando no seu canto, por exemplo, "
+"autenticación mediante clave pública), nas versións recentes de OpenSSH ten "
+"que desactivar a autenticación por desafío-resposta ou asegurarse de que a "
+"súa configuración de PAM non permita a autenticación por ficheiro de "
+"contrasinais de Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Se desactiva a autenticación por desafío-resposta, os usuarios non han poder "
+"conectarse empregando contrasinais. Se a deixa activada (a resposta por "
+"defecto) a opción \"PasswordAuthentication no\" non ha ter ningún efecto "
+"útil a menos que tamén axuste a súa configuración de PAM en /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Hanse rexenerar as claves de servidor vulnerables"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Algunhas das claves de servidor de OpenSSH deste sistema xeráronse cunha "
+"versión de OpenSSL que tiña un xerador de números aleatorios que non "
+"funcionaba correctamente. Coma resultado, esas claves de servidor pertencen "
+"a un conxunto coñecido, son vulnerables a ataques por forza bruta, e teñen "
+"que se rexenerar."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"É preciso informar deste cambio aos usuarios deste sistema, xa que se lles "
+"ha avisar do cambio de clave de servidor a próxima vez que se conecten. "
+"Empregue a orde \"ssh-keygen -l -f FICHEIRO_DE_CLAVE\" trala actualización "
+"para amosar as pegadas dactilares das novas claves de servidor."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "As claves de servidor afectadas son:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"As claves dos usuarios tamén poden estar afectadas por este problema. Pódese "
+"empregar a orde \"ssh-vulnkey\" para facer unha comprobación parcial disto. "
+"Consulte /usr/share/doc/openssh-server/README.compromised-keys.gz para máis "
+"detalles."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "¿Xerar un novo ficheiro de configuración para OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Esta versión de OpenSSH ten un ficheiro de configuración que cambiou "
+#~ "moito con respecto á versión que se subministrou con Debian \"Potato\", "
+#~ "desde a que semella que se está a actualizar. Este paquete pode xerar "
+#~ "agora un novo ficheiro de configuración (/etc/ssh/sshd.config) que ha "
+#~ "funcionar coa nova versión do servidor, pero que non ha conter ningunha "
+#~ "personalización que teña feito na versión antiga."
+
+# | msgid ""
+# | "Please note that this new configuration file will set the value of "
+# | "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+# | "can ssh directly in as root). Please read the README.Debian file for more "
+# | "details about this design choice."
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Teña en conta que este novo ficheiro de configuración ha establecer o "
+#~ "valor de de \"PermitRootLogin\" a \"yes\" (o que significa que calquera "
+#~ "que coñeza o contrasinal do administrador ha poder conectarse "
+#~ "directamente coma \"root\" mediante ssh). Consulte o ficheiro README."
+#~ "Debian para ter máis detalles sobre esta decisión de deseño."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Recoméndase encarecidamente que xere agora un novo ficheiro de "
+#~ "configuración."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Aviso: ten que crear unha nove chave de servidor"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Aviso: telnetd está instalado --- seguramente non sexa unha boa idea"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Recoméndase que elimine o paquete telnetd (se non precisa de fornecer "
+#~ "acceso por telnet) ou instale telnetd-ssl para que exista alomenos "
+#~ "algunha posibilidade de que as sesións telnet non envíen información de "
+#~ "usuario/contrasinal e das sesións sen cifrar pola rede."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Aviso: rsh-server está instalado --- seguramente non sexa unha boa idea"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "ao ter rsh-server instalado pérdese a seguridade que probablemente "
+#~ "pretendía obter ao instalar ssh. Recoméndase que se desinstale ese "
+#~ "paquete."
diff --git a/debian/po/it.po b/debian/po/it.po
new file mode 100644 (file)
index 0000000..047dd3f
--- /dev/null
@@ -0,0 +1,202 @@
+# Italian (it) translation of debconf templates for openssh
+# Copyright (C) 2006 Software in the Public Interest
+# This file is distributed under the same license as the openssh package.
+# Renato Gini <rgini@openlabs.it>, 2003 - 2005
+# Luca Monducci <luca.mo@tiscali.it>, 2006, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 4.7p1 italian debconf templates\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-18 12:08+0200\n"
+"Last-Translator: Luca Monducci <luca.mo@tiscali.it>\n"
+"Language-Team: Italian <debian-l10n-italian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Si vuole rischiare di terminare le sessioni SSH attive?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"È probabile che la versione di /etc/init.d/ssh attualmente installata "
+"termini tutte le istanze di sshd attive. Se si sta effettuando questo "
+"aggiornamento tramite una sessione SSH, è possibile che la sessione venga "
+"chiusa e che la procedura di aggiornamento rimanga incompleta."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"È possibile evitare ciò aggiungendo manualmente «--pidfile /var/run/sshd.pid» "
+"alla riga start-stop-daemon nella sezione stop del file."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Necessaria una nuova chiave host"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"L'attuale chiave host, contenuta in /etc/ssh/ssh_host_key, è cifrata con "
+"l'algoritmo IDEA. OpenSSH non è in grado di gestire questa chiave host e non "
+"è disponibile il programma (non-free) ssh-keygen dalla precedente "
+"installazione di SSH."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "È necessario generare manualmente una nuova chiave host."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Disabilitare l'autenticazione interattiva?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Nell'attuale configurazione del server OpenSSH è disabilitata "
+"l'autenticazione tramite password. Con le versioni più recenti di OpenSSH "
+"per impedire l'accesso degli utenti al sistema con la password (per esempio "
+"l'accesso deve essere possibile solo tramite chiavi pubbliche) si deve "
+"disabilitare l'autenticazione interattiva oppure si deve verificare che PAM "
+"sia configurato in modo da non consentire l'autenticazione tramite il file "
+"delle password Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Se l'autenticazione interattiva è disabilitata gli utenti non possono "
+"effettuare l'accesso al sistema con la password. Invece se, come previsto "
+"dalla configurazione predefinita, è abilitata allora l'opzione "
+"«PasswordAuthentication no» non ha effetto fino a quando non si interviene "
+"anche sulla configurazione di PAM in /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Le chiavi host vulnerabili devono essere rigenerate"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Alcune delle chiavi host OpenSSH per server presenti su questo sistema sono "
+"state create con una versione di OpenSSL afflitta da un problema al "
+"generatore di numeri casuali. Di conseguenza queste chiavi host appartengono "
+"a un insieme noto, quindi sono vulnerabili ad attacchi di tipo forza bruta e "
+"devono essere rigenerate."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Gli utenti del sistema dovrebbero essere informati di questo cambiamento "
+"poiché al prossimo accesso al sistema verrà loro mostrato un avvertimento "
+"relativo al cambiamento della chiave host. Dopo l'aggiornamento usare \"ssh-"
+"keygen -l -f FILE_CHIAVE_HOST\" per stampare i fingerprint delle nuove "
+"chiavi host."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Le chiavi host vulnerabili sono:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Anche le chiavi utente potrebbero essere afflitte dallo stesso problema. È "
+"possibile usare il comando \"ssh-vulnkey\" per fare un test parziale sulla "
+"loro vulnerabilità. Si veda /usr/share/doc/openssh-server/README.compromised-"
+"keys.gz per ulteriori informazioni."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Generare un nuovo file di configurazione per OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Questa versione di OpenSSH contiene un file di configurazione decisamente "
+#~ "diverso da quello distribuito in Debian \"Potato\", che sembra essere "
+#~ "quello che si sta aggiornando. Questo pacchetto è in grado di generare "
+#~ "automaticamente un nuovo file di configurazione (/etc/ssh/sshd.config) "
+#~ "adatto alla nuova versione del server, ma che non contiene nessuna delle "
+#~ "personalizzazioni apportate nella precedente versione."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Notare che nel nuovo file di configurazione il valore di «PermitRootLogin» "
+#~ "è impostato a «yes» (quindi chiunque conosca la password di root può "
+#~ "collegarsi tramite ssh direttamente come root). Per ulteriori dettagli su "
+#~ "questa scelta si veda il file README.Debian."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "È vivamente raccomandata la scelta di far generare automaticamente un "
+#~ "nuovo file di configurazione."
diff --git a/debian/po/ja.po b/debian/po/ja.po
new file mode 100644 (file)
index 0000000..b011ddc
--- /dev/null
@@ -0,0 +1,197 @@
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-17 21:28+0900\n"
+"Last-Translator: Kenshi Muto <kmuto@debian.org>\n"
+"Language-Team: Japanese <debian-japanese@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "接続中の SSH セッションが切れるかもしれませんがよいですか?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"現在インストールされたバージョンの /etc/init.d/ssh は、おそらく実行中の sshd "
+"インスタンスをすべて殺します。このアップグレードを SSH セッション経由で行って"
+"いる場合、あなたは切断され、アップグレード処理は不完全なままになるでしょう。"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"この状況を修正するには、ファイルの stop セクションの start-stop-daemon の行に"
+"「--pidfile /var/run/sshd.pid」と手動で追加します。"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "新しいホストキーが必要です"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"/etc/ssh/ssh_host_key にある現在のホストキーは IDEA で暗号化されていあす。"
+"OpenSSH はこのホストキーファイルを扱えず、古い (フリーではない) SSH の ssh-"
+"keygen ユーティリティはもう利用できません。"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "新しいホストキーを手動で生成する必要があります。"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "チャレンジ-レスポンス認証を無効にしますか?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"現在の OpenSSH サーバの設定ではパスワード認証が無効になっているようです。"
+"OpenSSH の最近のバージョンでパスワードを使ってユーザがログインするのを防ぐ "
+"(多分公開鍵認証だけを代わりに使う) ためには、チャレンジ-レスポンス認証を無効"
+"にするか、PAM 設定で Unix パスワードファイル認証を絶対に許可しないようにする"
+"必要があります。"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"チャレンジ-レスポンス認証を無効にする場合、ユーザはパスワードを使ってログイン"
+"できなくなります。有効 (デフォルト) のままにしておくと、/etc/pam.d/ssh にあ"
+"る PAM 設定を調節しない限り、'PasswordAuthentication no' オプションは効果を持"
+"たなくなります。"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "脆弱なホストキーは再生成されます"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"このシステムの OpenSSH サーバのホストキーのいくつかが、壊れた乱数生成器を持"
+"つ OpenSSL バージョンで生成されていました。結果として、これらのホストキーは既"
+"知の組み合わせから成り、ブルートフォース攻撃を受けやすいものになっているた"
+"め、再生成する必要があります。"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"次回のログイン時にホストキーの変更が示されることで、このシステムのユーザは、"
+"この変更の通知を受け取ることになります。更新後に新しいホストキーの指紋を表示"
+"するには、'ssh-keygen -l -f HOST_KEY_FILE' を使います。"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "影響を受けるホストキーは次のとおりです:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"ユーザキーもこの問題の影響を受けている恐れがあります。この部分的なテストとし"
+"て、'ssh-vulnkey' コマンドを利用できます。詳細については /usr/share/doc/"
+"openssh-server/README.compromised-keys.gz を参照してください。"
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "OpenSSH の新しい設定ファイルを作りますか?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "OpenSSH のこのバージョンは、Debian 'Potato' で提供していたバージョン (い"
+#~ "ま、そのバージョンからのバージョンアップを試みているところ) から、設定ファ"
+#~ "イルが大幅に変化しています。このパッケージは、新しいバージョンのサーバで使"
+#~ "うことができる新しい設定ファイル (/etc/ssh/sshd.config) を今生成することが"
+#~ "できますが、古いバージョンの設定ファイルに加えていたカスタマイズはいずれも"
+#~ "含まれません。"
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "この新しい設定ファイルは、「PermitRootLogin」を「yes」に設定します (つま"
+#~ "り、root のパスワードを知っている人なら誰でも直接ログインできます)。このよ"
+#~ "うな設計を選んでいる理由の詳細については、README.Debian を読んでください。"
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "新しい設定ファイルを今生成することを強くお勧めします。"
diff --git a/debian/po/ko.po b/debian/po/ko.po
new file mode 100644 (file)
index 0000000..7cbf4c1
--- /dev/null
@@ -0,0 +1,189 @@
+# Korean translations for openssh package
+# openssh 패키지에 대한 한국어 번역문.
+# Copyright (C) 2007 THE openssh'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the openssh package.
+# Sunjae Park <darehanl@gmail.com>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-06-06 16:06-0400\n"
+"Last-Translator: Sunjae Park <darehanl@gmail.com>\n"
+"Language-Team: Korean <debian-l10n-korean@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "현재 사용중인 SSH 세션을 죽여도 괜찮습니까?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"현재 설치된 /etc/init.d/ssh 버전은 사용중인 sshd 인스턴스를 모두 죽일 것입니"
+"다. 만약 SSH 세션을 통해 이 업그레이드를 하고 있다면 도중에 연결이 해제되어 "
+"업그레이드 작업이 도중에 중단될 수 있습니다."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"파일의 stop 구역에 있는 start-stop-daemon에 \"--pidfile /var/run/sshd.pid"
+"\"을 추가하시면 이 문제를 해결할 수 있습니다."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "호스트키 새로 만들어야 함"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"/etc/ssh/ssh_host_key에 있는 현재 호스트키늘 IDEA 알고리즘으로 암호화되어있습"
+"니다. OpenSSH는 이 호스트키 파일을 다루지 못하며, 이전에 설치되었던 (비자유) "
+"SSH 프로그램의 ssh-keygen 응용프로그램이 없는 것 같습니다."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "호스트키를 직접 새로 생성하셔야 합니다."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "제기-응답 인증방식을 해제하도록 할까요?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"현재의 OpenSSH 서버 설정에 비밀번호 인증방식이 해제되어 있습니다. 최근 버전"
+"의 OpenSSH에서 사용자들이 (공개키 방식만 허용하기 위해서 등의 이유로) 비밀번"
+"호로 로그인하지 못하도록 하시려면 제기-응답 인증방식을 해제하시든지 유닉스 "
+"password 파일 인증방식을 사용하지 못하도록 PAM 설정을 하셔야 합니다."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"제기-응답 인증방식을 해제하면 사용자들은 비밀번호를 이용하여 로그인하지 못하"
+"게 됩니다. (기본 설정대로) 해제하지 않으시면 /etc/pam.d/ssh에 있는 PAM 설정"
+"을 변경하지 않으실 경우 'PasswordAuthentication no' 옵션은 아무런 영향을 주"
+"지 못합니다."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "취약한 호스트키를 다시 생성합니다"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"이 시스템에 있는 OpenSSH 서버의 호스트키는 잘못된 난수생성기를 사용한 버전의 "
+"OpenSSL를 통해 만들어졌습니다. 이러한 호스트키들은 잘 알려진 범위 내에 있게 "
+"되므로 brute-force 공격에 약할 수 있으며, 따라서 다시 만들어야 합니다."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"이 시스템을 사용한 사람들은 다음에 로그인할 때 호스트키가 변경되었다는 사실"
+"을 감지하게 되기 때문에 사용자들에게 이 사항을 알려주셔야 합니다. 업그레이드 "
+"후 'ssh-keygen -l -f 호스트키 파일명'을 사용하여 새로운 호스트키의 핑거프린트"
+"를 출력받을 수 있습니다."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "관련된 호스트키의 목록은:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"사용자 키 역시 이 문제에 영향을 받을 수 있습니다. 'ssh-vulnkey' 명령을 사용하"
+"여 부분적으로나마 그렇한지를 검사할 수 있습니다. 자세한 정보는 /usr/share/"
+"doc/openssh-server/README.compromised-keys.gz를 참조하십시오."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "OpenSSH 설정 파일을 새로 만들까요?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "이번 OpenSSH 버전은 지금 사용하고 계시는 듯한 데비안 'Potato'의 OpenSSH 버"
+#~ "전과는 크게 다른 설정 파일을 사용합니다. 이 꾸러미는 새로 설치되는 서버 버"
+#~ "전에 맞는 설정 파일(/etc/ssh/sshd.config)을 새로 만들 수 있습니다만, 이전 "
+#~ "버전에서 변경한 내역은 적용되지 않습니다."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "참고로 새로 설치되는 설정파일은 'PermitRootLogin'의 값을 'yes'로 설정합니"
+#~ "다(따라서 root 비밀번호를 알고 있는 사람은 누구나 root로 직접 ssh 로그인"
+#~ "할 수 있습니다). 이렇게 결정한 이유에 대해서 자세히 알고자 하신다면 "
+#~ "README.Debian 파일을 참조하시기 바랍니다."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "설정 파일을 지금 새로 만드시길 강력히 권장합니다."
diff --git a/debian/po/nb.po b/debian/po/nb.po
new file mode 100644 (file)
index 0000000..415d5fa
--- /dev/null
@@ -0,0 +1,196 @@
+# translation of nb.po to Norwegian Bokmål
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Bjørn Steensrud <bjornst@powertech.no>, 2007.
+# Bjørn Steensrud <bjornst@skogkatt.homelinux.org>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: nb\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-17 11:04+0200\n"
+"Last-Translator: Bjørn Steensrud <bjornst@skogkatt.homelinux.org>\n"
+"Language-Team: Norwegian Bokmål <i18n-nb@lister.ping.uio.no>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Vil du risikere å avbryte aktive SSH-økter?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Den versjonen av /etc/init.d/ssh som nå er installert vil antakelig stoppe "
+"alle sshd-instanser som kjører. Hvis denne oppgraderingen gjøres over en SSH-"
+"økt, så risikerer du å bli frakoblet og oppgraderingen blir ikke fullført."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Dette kan rettes på ved å legge til manuelt «--pidfile /var/run/sshd.pid» til "
+"start-stop-daemon linja i stopp-delen av fila."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Ny vertsnøkkel obligatorisk"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Den gjeldende vertsnøkkelen, i /etc/ssh/ssh_host_key, er kryptert med IDEA-"
+"algoritmen. OpenSSH kan ikke håndtere denne vertsnøkkelfila, og det ser ikke "
+"ut til at verktøyet ssh-keygen fra den gamle (ikke-frie) SSH-installasjonen "
+"er tilgjengelig."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "En ny vertsnøkkel må lages manuelt."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Skal autentisering med utfordring/svar slås av?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Det ser ut til at passord-autentisering er slått av i det gjeldende "
+"tjeneroppsettet for OpenSSH. For å hindre brukere i å logge inn med passord "
+"med nyere versjoner av OpenSSH (kanskje med autentisering med kryptonøkler i "
+"stedet), så må autentisering med utfordring-svar slås av, eller det må "
+"sjekkes at PAM-oppsettet er satt til ikke å tillate autentisering mot Unix "
+"passord-fila."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Hvis autentisering med utfordring-svar er slått av, så kan brukere ikke "
+"logge inn med passord. Hvis det står på (som er standard), så har det ingen "
+"virkning å sette «PasswordAuthentication no» med mindre PAM-oppsettet i /etc/"
+"pam.d/ssh også justeres."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Sårbare vertsnøkler vil bli laget på nytt"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Noen av OpenSSHs vertsnøkler på dette systemet ble opprettet med versjon av "
+"OpenSSH som hadde en feil på slumptallsgeneratoren. Derfor tilhører disse "
+"nøklene et velkjent sett nøkler, kan knekkes med «rå kraft»-metoden og må "
+"lages på nytt."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"De som bruker dette systemet bør få opplysning om denne endringen, siden de "
+"vkil få spørsmål om vertsnøkkelendringen neste gang de logger inn. Etter "
+"oppgraderingen kan fingeravtrykkene for de nye vertsnøklene skrives ut med "
+"kommandoen «keygen -l -f VERTSNØKKELFIL»."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "De vertsnøklene dette gjelder er:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Det kan være at brukernøkler også har dette problemet. En delvis test på "
+"dette kan gjøres med kommandoen «ssh-vulnkey». Mer detaljer finnes i /usr/"
+"share/doc/openssh-server/README.compromised-keys.gz."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Skal ny oppsettsfil for OpenSSH lages?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Det ser ut til at du oppgraderer fra Debian «Potato», og denne versjonen "
+#~ "av OpenSSH har ganske store endringer i oppsettsfila. Denne pakka kan nå "
+#~ "lage en ny oppsettsfil (/etc/ssh/sshd.config) som fungerer med den nye "
+#~ "tjenerversjonen, men ikke inneholder noen tilpasninger som kan være gjort "
+#~ "lokalt i den gamle versjonen."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Merk at denne nye oppsettsfila setter verdien av «PermitRootLogin» til "
+#~ "«yes» (slik at alle som kjenner root-passordet kan logge inn direkte med "
+#~ "ssh som root). Les README.Debian-fila for å finne ut mer om dette "
+#~ "oppsettsvalget."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Det anbefales sterkt at denne pakka får lov til å lage en ny oppsettsfil "
+#~ "nå."
diff --git a/debian/po/nl.po b/debian/po/nl.po
new file mode 100644 (file)
index 0000000..b88ca82
--- /dev/null
@@ -0,0 +1,208 @@
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 3.6.1p2-9\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-26 15:19+0200\n"
+"Last-Translator: Bart Cornelis <cobaco@skolelinux.no>\n"
+"Language-Team: debian-l10n-dutch <debian-l10n-dutch@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Dutch\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Wilt u het afsluiten van actieve SSH-sessies riskeren?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"De /etc/init.d/ssh versie die u geïnstalleerd hebt sluit waarschijnlijk alle "
+"lopende sshd-instanties af. Als u deze opwaardering via een SSH-sessie "
+"uitvoert verliest u waarschijnlijk de verbinding waardoor de "
+"opwaarderingsprocedure onafgemaakt blijft."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"U kunt dit handmatig repareren door \"--pidfile /var/run/sshd.pid\" toe te "
+"voegen aan de start-stop-daemon regel in de stop-sectie van het bestand."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Een nieuwe computersleutel is verplicht"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"De huidige computersleutel in /etc/ssh/ssh_host_key is versleuteld met het "
+"IDEA-algoritme. OpenSSH kan dit computer-sleutelbestand niet aan, en het ssh-"
+"keygen programma van de oude (niet-vrije) SSH-installatie is niet "
+"beschikbaar."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "U dient bijgevolg handmatig een nieuwe computersleutel te genereren."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Challenge-response-authenticatie deactiveren?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Zo te zien is wachtwoord-authenticatie momenteel gedeactiveerd in uw OpenSSH-"
+"serverconfiguratie. Om te voorkomen dat gebruikers van recente OpenSSH-"
+"versies inloggen met behulp van wachtwoorden (en in plaats daarvan enkel "
+"publieke-sleutel authenticatie te gebruiken), dient challenge-response-"
+"authenticatie gedeactiveerd te worden, of dient u ervoor te zorgen dat uw "
+"PAM-configuratie geen Unix 'password'-bestand-authenticatie toe laat."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Wanneer u challenge-response-authenticatie deactiveert kunnen gebruikers "
+"niet meer inloggen met behulp van wachtwoorden. Als u het geactiveerd laat "
+"(de standaarwaarde) zal de 'PasswordAuthentication no' optie geen (nuttig) "
+"effect hebben tenzij u ook de PAM-configuratie aanpast in /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Kwetsbare computersleutels worden opnieuw aangemaakt"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Er zijn op dit systeem OpenSSH-computersleutels aangetroffen die aangemaakt "
+"zijn door een versie van OpenSSL met een onjuiste random-nummer-generator. "
+"Hierdoor zijn deze computersleutels kwetsbaar voor 'brute-force'-aanvallen "
+"en moeten ze opnieuw aangemaakt worden."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Gebruikers van dit systeem krijgen een melding omtrent de "
+"computersleutelverandering op hun scherm de volgende keer dat ze inloggen "
+"via ssh. U dient hun hierover dus te berichten. De vingerafdrukken van de "
+"nieuwe computersleutels kunt na de opwaardering opvragen via het commando "
+"'ssh-keygen -l -f HOST_KEY_FILE'."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "De getroffen computersleutels zijn:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Sleutels van gebruikers kunnen ook getroffen zijn door dit probleem. Het "
+"'ssh-vulnkey' commando kan gebruikt worden als een gedeeltelijke test, meer "
+"details vindt u in /usr/share/doc/openssh-server/README.compromised-keys."
+"gz . "
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr ""
+#~ "Wilt u dat er een nieuw configuratiebestand aangemaakt wordt voor OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Deze versie van OpenSSH gebruikt een configuratiebestand dat sterk "
+#~ "veranderd is ten opzichte van dat in Debian 'Potato' (waarvan u lijkt op "
+#~ "te waarderen). Het pakket kan nu een nieuw configuratiebestand (/etc/ssh/"
+#~ "sshd.config) genereren dat met de nieuwe versie werkt. Dit gegenereerde "
+#~ "bestand zal echter de door u gemaakte aanpassingen in het oude "
+#~ "configuratiebestand niet overnemen."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Merk op dat dit nieuwe configuratiebestand de waarde van "
+#~ "'PermitRootLogin' op 'yes' zet (wat betekent dat iedereen die het root-"
+#~ "wachtwoord kent via ssh rechtstreeks als root kan aanmelden). Meer "
+#~ "informatie over deze ontwerpkeuze vindt u in het bestand README.Debian."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Het wordt ten sterkste aangeraden om nu het nieuwe configuratiebestand te "
+#~ "laten genereren."
diff --git a/debian/po/pl.po b/debian/po/pl.po
new file mode 100644 (file)
index 0000000..e70ee26
--- /dev/null
@@ -0,0 +1,432 @@
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2004-04-08 18:28+0200\n"
+"Last-Translator: Emil Nowak <emil5@go2.pl>\n"
+"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid "Do you want to continue (and risk killing active ssh sessions)?"
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Czy chcesz kontynuowaæ (i ryzykowaæ przerwaniem aktywnych sesji ssh) ?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "The version of /etc/init.d/ssh that you have installed, is likely to kill "
+#| "all running sshd instances.  If you are doing this upgrade via an ssh "
+#| "session, that would be a Bad Thing(tm)."
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Zainstalowana w³a¶nie wersja /etc/init.d/ssh mo¿e zabiæ wszystkie dzia³aj±ce "
+"obecnie kopie sshd. Je¶li wykonujesz t± aktualizacjê przez ssh, to by³aby "
+"Z³a Rzecz(tm)."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "You can fix this by adding \"--pidfile /var/run/sshd.pid\" to the start-"
+#| "stop-daemon line in the stop section of the file."
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Mo¿esz to naprawiæ dodaj±c \"--pidfile /var/run/sshd.pid\" do linijki start-"
+"stop-daemon w sekcji stop tego pliku."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Istnieje stary /etc/ssh/ssh_host_key, który jest zaszyfrowany przez IDEA. "
+"OpenSSH nie umie korzystaæ z tak zaszyfrowanego klucza, a nie mo¿e znale¼æ "
+"polecenia ssh-keygen ze starego SSH (non-free)."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+#| msgid "You will need to generate a new host key."
+msgid "You need to manually generate a new host key."
+msgstr "Bêdziesz musia³ wygenerowaæ nowy klucz hosta."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+
+#, fuzzy
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Wygeneruj nowy plik konfiguracyjny"
+
+#, fuzzy
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "W tej wersji OpenSSH zmieni³ siê plik konfiguracyjny w stosunku do wersji "
+#~ "dostarczanej z Debianem 'Potato', któr± zdajesz siê aktualizowaæ. Mogê "
+#~ "teraz wygenerowaæ nowy plik konfiguracyjny (/etc/ssh/sshd.config), który "
+#~ "bêdzie dzia³a³ z now± wersj± serwera, ale nie bêdzie zawiera³ ¿adnych "
+#~ "dokonanych przez ciebie w starej wersji zmian."
+
+#, fuzzy
+#~| msgid ""
+#~| "Please note that this new configuration file will set the value of "
+#~| "'PermitRootLogin' to yes (meaning that anyone knowing the root password "
+#~| "can ssh directly in as root). It is the opinion of the maintainer that "
+#~| "this is the correct default (see README.Debian for more details), but "
+#~| "you can always edit sshd_config and set it to no if you wish."
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Zauwa¿ proszê, ¿e nowy plik konfiguracyjny bêdzie ustawia³ warto¶æ opcji "
+#~ "'PermitRootLogin' na 'tak' (co oznacza, ¿e ka¿dy kto zna has³o root'a "
+#~ "mo¿e zdalnie zalogowaæ siê przez ssh jako root). W opinii opiekuna "
+#~ "pakietu to jest poprawna warto¶æ domy¶lna (szczegó³y w README.Debian), "
+#~ "ale mo¿esz sobie wyedytowaæ sshd_config i ustawiæ tê opcjê na 'nie' je¶li "
+#~ "siê z t± opini± nie zgadzasz."
+
+#, fuzzy
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Jest bardzo wskazane aby¶ pozwoli³ mi wygenerowaæ nowy plik "
+#~ "konfiguracyjny."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Uwaga: musisz utworzyæ nowy klucz hosta"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Uwaga: telnetd jest zainstalowany --- prawdopodobnie nienajlepszy pomys³"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Radzi³bym albo usun±æ pakiet telnetd (je¶li nie potrzebujesz koniecznie "
+#~ "udostêpniaæ telnet'a) albo zainstalowaæ telnetd-ssl aby by³a choæ "
+#~ "szansza, ¿e sesje telnet nie bêd± przesy³aæ niezaszyfrowanego loginu/"
+#~ "has³a oraz danych sesji przez sieæ."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Uwaga: serwer rsh jest zainstalowany --- prawdopodobnie nienajlepszy "
+#~ "pomys³"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "Posiadanie zainstalowanego serwera rsh podminowuje zabezpieczenia, które "
+#~ "prawdopodobnie starasz siê uzyskaæ instaluj±c ssh. Radzi³bym usun±æ ten "
+#~ "pakiet."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "Czy chcesz aby ssh-keysign by³ zainstalowany jako SUID root?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr ""
+#~ "Masz mo¿liwo¶æ zainstalowania pomocniczego programu ssh-keysign z "
+#~ "w³±czonym bitem SETUID."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Je¶li uczynisz ssh-keysign SUIDowym, bêdziesz móg³ u¿ywaæ opartej na "
+#~ "hostach autoryzacji drugiej wersji protoko³u SSH."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Je¶li masz w±tpliwo¶ci, radzê zainstalowaæ go z SUIDem. Je¶li to sprawia "
+#~ "problemy, mo¿esz zmieniæ swoje zdanie uruchamiaj±c pó¼niej polecenie: "
+#~ "dpkg-reconfigure ssh"
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Zezwalaj wy³±cznie na wersjê 2 protoko³u SSH"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "Ta wersja OpenSSH wspiera drug± wersjê protoko³u ssh, która jest znacznie "
+#~ "bardziej bezpieczna. Wy³±czenie ssh 1 jest zalecane, choæ spowalnia to "
+#~ "dzia³anie na starych maszynach i mo¿e uniemo¿liwiæ po³±czenie starszym "
+#~ "wersjom klientów (dotyczy to np. klienta ssh do³±czanego do \"potato\")."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "Ponadto, zauwa¿ proszê, ¿e klucze u¿ywane przez protokó³ 1 s± inne, wiêc "
+#~ "nie bêdziesz móg³ ich u¿ywaæ je¶li zezwolisz na korzystanie wy³±cznie z "
+#~ "wersji 2 protoko³u."
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Je¶li pó¼niej zmienisz zdanie co do tego ustawienia, to instrukcje co "
+#~ "zmieniæ w sshd_config znajduj± siê w README.Debian."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr ""
+#~ "UWAGA: Przekazywanie (forwarding) X11 i Autoryzacji jest domy¶lnie "
+#~ "wy³±czone."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "Ze wzglêdów bezpieczeñstwa Debianowa wersja ssh ma ForwardX11 i "
+#~ "ForwardAgent ustawione  domy¶lnie na 'off'."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Dla zaufanych serwerów mo¿esz w³±czyæ te opcje w pliku konfiguracyjnym "
+#~ "lub przy pomocy opcji -X z linii komend."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr "Wiêcej szczegó³ów znajdziesz w /usr/share/doc/ssh/README.Debian."
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "klucze ssh2 w³±czone do plików konfiguracyjnych"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "Pocz±wszy od wersji 3 OpenSSH nie u¿ywa ju¿ osobnych plików dla kluczy "
+#~ "ssh1 i ssh2. Oznacza to, ¿e pliki authorized_keys2 i known_hosts2 nie s± "
+#~ "ju¿ potrzebne. Bêd± one jednak odczytywane aby zachowaæ wsteczn± "
+#~ "kompatybilno¶æ."
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "Czy chcesz uruchamiaæ serwer sshd ?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "Ten pakiet zawiera zarówno klienta ssh, jak i serwer sshd."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "Normalnie serwer sshd (Secure Shell Server) bêdzie uruchomiony aby "
+#~ "umo¿liwiæ zdalny dostêp przez ssh."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Je¶li jeste¶ zainteresowany u¿ywaniem wy³±cznie klienta ssh dla po³±czeñ "
+#~ "wychodz±cych z tej maszyny, i nie chcesz siê na ni± logowaæ przy pomocy "
+#~ "ssh, to mo¿esz teraz wy³±czyæ serwer sshd."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "Odradzamy stosowanie ustawieñ ¶rodowiskowych dla kluczy."
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "Ta wersja OpenSSH ma wy³±czon± opcjê wykorzystywania ustawieñ "
+#~ "¶rodowiskowych dla kluczy publicznych. Mo¿na dziêki temu unikn±æ pewnych "
+#~ "ataków (jak np.: LD_PRELOAD). Je¿eli u¿ywasz tej opcji w pliku "
+#~ "authorized_keys, to zawarte w nim klucze nie bêd± dzia³aæ dopóki ta opcja "
+#~ "nie zostanie usuniêta."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Aby ponownie w³±czyæ tê opcjê, nale¿y dodaæ wpis \"PermitUserEnvironment "
+#~ "yes\" do pliku /etc/ssh/sshd_config po ukoñczeniu aktualizacji. Przy "
+#~ "zmianie konfiguracji nale¿y zapoznaæ siê z informacjami zawartymi na "
+#~ "stronie podrêcznika systemowego sshd_config(5)."
+
+#~ msgid "Privilege separation"
+#~ msgstr "Separacja uprawnieñ"
+
+#~ msgid ""
+#~ "Privilege separation is turned on by default, so if you decide you want "
+#~ "it turned off, you need to add \"UsePrivilegeSeparation no\" to /etc/ssh/"
+#~ "sshd_config."
+#~ msgstr ""
+#~ "Separacja uprawnieñ jest domy¶lnie w³±czona, wiêc je¶li zdecydujesz siê "
+#~ "j± wy³±czyæ, musisz dodaæ \"UsePrivilegeSeparation no\" do pliku /etc/ssh/"
+#~ "sshd_config."
+
+#~ msgid "Enable Privilege separation"
+#~ msgstr "W³±czenie separacji uprawnieñ"
+
+#~ msgid ""
+#~ "This version of OpenSSH contains the new privilege separation option. "
+#~ "This significantly reduces the quantity of code that runs as root, and "
+#~ "therefore reduces the impact of security holes in sshd."
+#~ msgstr ""
+#~ "Ta wersja OpenSSH zawiera now± opcjê separacji uprawnieñ. Znacz±co "
+#~ "zmniejsza ona ilo¶æ kodu, który jest uruchamiany jako root i co za tym "
+#~ "idzie redukuje efekty luk bezpieczeñstwa w sshd."
+
+#~ msgid ""
+#~ "Unfortunately, privilege separation interacts badly with PAM. Any PAM "
+#~ "session modules that need to run as root (pam_mkhomedir, for example) "
+#~ "will fail, and PAM keyboard-interactive authentication won't work."
+#~ msgstr ""
+#~ "Niestety separacja uprawnieñ ¼le reaguje z PAMem. Jakikolwiek modu³ sesji "
+#~ "PAM, który musi byæ uruchamiany jako root (pam_mkhomedir, na przyk³ad) "
+#~ "zawiedzie. Nie bêdzie dzia³aæ równie¿ interaktywna autentykacja z "
+#~ "klawiatury (keyboard-interactive authentication)."
+
+#, fuzzy
+#~ msgid ""
+#~ "Since you've opted to have me generate an sshd_config file for you, you "
+#~ "can choose whether or not to have privilege separation turned on or not. "
+#~ "Unless you know you need to use PAM features that won't work with this "
+#~ "option, you should enable it."
+#~ msgstr ""
+#~ "Zdecydowa³e¶ siê na to abym wygenerowa³ dla ciebie plik sshd_config, i "
+#~ "mo¿esz wybraæ czy chcesz w³±czyæ Separacjê Uprawnieñ, czy te¿ nie. Je¶li "
+#~ "nie u¿ywasz j±dra z serii 2.0 (w którym to przypadku *musisz* "
+#~ "odpowiedzieæ tutaj 'nie' albo sshd w ogóle nie ruszy) i je¶li nie musisz "
+#~ "korzystaæ z mo¿liwo¶ci PAMa, które nie bêd± dzia³a³y z t± opcj±, "
+#~ "powiniene¶ odpowiedzieæ tutaj 'tak'."
+
+#~ msgid ""
+#~ "NB! If you are running a 2.0 series Linux kernel, then privilege "
+#~ "separation will not work at all, and your sshd will fail to start unless "
+#~ "you explicitly turn privilege separation off."
+#~ msgstr ""
+#~ "UWAGA! Je¿eli u¿ywasz j±dra Linux'a z serii 2.0, to separacja uprawnieñ w "
+#~ "ogóle nie bêdzie dzia³aæ i sshd nie wystartuje dopóki w³asnorêcznie nie "
+#~ "wy³±czysz separacji uprawnieñ w /etc/ssh/sshd_config."
diff --git a/debian/po/pt.po b/debian/po/pt.po
new file mode 100644 (file)
index 0000000..7fe576f
--- /dev/null
@@ -0,0 +1,195 @@
+# Portuguese translation of openssh debconf messages.
+# This file is distributed under the same license as the openssh package.
+# Ricardo Silva <ardoric@gmail.com>, 2007.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 4.7p1-9\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-18 14:48+0100\n"
+"Last-Translator: Ricardo Silva <ardoric@gmail.com>\n"
+"Language-Team: Native Portuguese <traduz@debianpt.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Quer arriscar matar sessões activas de SSH?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"A versão do /etc/init.d/ssh que tem instalado provavelmente terminará todas "
+"as instâncias de sshd. Se vai actualizar através de uma sessão ssh, é "
+"possível que a sua sessão seja terminada e que deixe o procedimento de "
+"actualização por terminar."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Isto pode ser arranjado adicionando \"--pidfile /var/run/sshd.pid\" à linha "
+"start-stop-daemon na secção stop do ficheiro."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Uma nova chave de anfitrião é obrigatória"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"A chave actual, em /etc/ssh/ssh_host_key, está cifrada com o algoritmo IDEA. "
+"O OpenSSH não consegue usar este ficheiro, e o utilitário ssh-keygen da "
+"antiga (e não livre) instalação do SSH não parece estar disponível."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Terá de gerar manualmente uma nova chave para o host."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Desactivar autenticação por desafio-resposta?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Autenticação por palavra-chave aparenta estar desactivada na sua "
+"configuração actual do servidor OpenSSH. De forma a impedir que os "
+"utilizadores se liguem usando palavras-chave (talvez usando apenas "
+"autenticação por chave pública) com versões recentes do OpenSSH, tem de "
+"desactivar a autenticação por desafio-resposta, ou assegurar-se que a sua "
+"configuração do PAM não permite autenticação pelo ficheiro password de Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Se desactivar autenticação por pedido-resposta, os utilizadores não serão "
+"capazes de se ligar usando palavras-chave. Se deixar activado (a resposta "
+"por omissão), então a opção 'PasswordAuthentication no' não terá efeito a "
+"não ser que também ajuste a configuração do PAM em /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Chaves do anfitrião vulneráveis serão regeneradas"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Algumas das chaves do servidor OpenSSH neste sistema foram criadas com uma "
+"versão do OpenSSL que tem um gerador de números aleatórios com problemas. "
+"Como resultado estas chaves, que fazem parte de um conjunto bem conhecido, "
+"estão sujeitas a ataques por força bruta, e têm de ser geradas de novo."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Os utilizadores deste sistema devem ser informados desta mudança, uma vez "
+"que vão ser avisados da mudança de chave da próxima vez que se ligarem. "
+"Utilize o comando 'ssh-keygen -l -f FICHEIRO_DA_CHAVE' depois da "
+"actualização para imprimir as impressões das novas chaves."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "As chaves afectadas são:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"As chaves de utilizador também podem ser afectadas por este problema. O "
+"comando 'ssh-vulnkey' pode ser usado como um teste parcial para este caso. "
+"Veja o ficheiro /usr/share/doc/openssh-server/README.compromised-keys.gz "
+"para mais detalhes."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Gerar um ficheiro de configuração novo para o OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Esta versão do OpenSSH tem um ficheiro de configuração bastante diferente "
+#~ "da versão que vinha com o Debian 'Potato', que parece ser de onde está a "
+#~ "actualizar. Este pacote pode agora gerar um novo ficheiro de configuração "
+#~ "(/etc/ssh/sshd.config), que irá funcionar com a nova versão do servidor, "
+#~ "mas não conterá nenhuma alteração que tenha feito à versão antiga."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Por favor note que este novo ficheiro de configuração terá "
+#~ "'PermitRootLogin' definido para 'yes' (o que significa que qualquer "
+#~ "pessoa que saiba a palavra-chave de root pode ligar-se directamente como "
+#~ "root a partir do ssh). Por favor leia o ficheiro README.Debian para mais "
+#~ "detalhes sobre esta escolha."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "É fortemente recomendado que escolha gerar um novo ficheiro de "
+#~ "configuração agora."
diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po
new file mode 100644 (file)
index 0000000..fe22271
--- /dev/null
@@ -0,0 +1,203 @@
+# openssh Brazilian Portuguese translation
+# Copyright (C) 2007, André Luís Lopes
+# This file is distributed under the same license as the openssh package.
+# André Luís Lopes <andrelop@debian.org>, 2007.
+# Eder L. Marques (frolic) <frolic@debian-ce.org>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 1:4.7p1-9\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-27 10:10-0300\n"
+"Last-Translator: Eder L. Marques (frolic) <frolic@debian-ce.org>\n"
+"Language-Team: Brazilian Portuguese <debian-l10n-portuguese@lists.debian."
+"org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"pt_BR utf-8\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Você deseja arriscar matar (\"kill\") as sessões SSH ativas?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"A versão instalada atualmente de /etc/init.d/ssh está prestes a derrubar "
+"todas as instâncias sshd em execução. Se você estiver fazendo esta "
+"atualização através de uma sessão SSH, você provavelmente será desconectado "
+"e deixará este processo de atualização incompleto."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Você pode corrigir isto adicionando \"--pidfile /var/run/sshd.pid\" na linha "
+"start-stop-daemon na seção stop deste arquivo."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Nova chave de máquina obrigatória"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"A chave de máquina atual, em /etc/ssh/ssh_host_key, é criptografada "
+"utilizando o algoritmo IDEA. O OpenSSH não pode gerenciar esse arquivo de "
+"chave de máquina, e o utilitário ssh-keygen da antiga (e não livre) "
+"instalação SSH não parece estar disponível."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Você precisa gerar manualmente uma chave de máquina."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Desabilitar autenticação desafio-resposta (\"challenge-response\")?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"A autenticação através de senha parece estar desabilitada em sua "
+"configuração atual do servidor OpenSSH. Para que seja possível evitar que "
+"usuários se autentiquem utilizando senhas (talvez utilizando somente "
+"autenticação através de chaves públicas) em versões recentes do OpenSSH você "
+"deve desabilitar a autenticação desafio-resposta (\"challenge-response\") ou "
+"então se certificar que sua configuração PAM não permita autenticação "
+"através do arquivos de senhas Unix (\"password\")."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Caso você desabilite a autenticação desafio-resposta (\"challenge-response"
+"\"), os usuários não poderão se autenticar utilizando suas senhas. Se você "
+"deixá-la habilitada (a resposta padrão), então a opção "
+"'PasswordAuthentication no' não terá efeito útil a menos que você também "
+"ajuste sua configuração PAM em /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Chaves de host vulneráveis serão regeradas"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Algumas das chaves de host do servidor OpenSSH neste sistema foram geradas "
+"com uma versão do OpenSSL que tem um gerador de números aleatórios quebrado. "
+"Como resultado, estas chaves de host são originárias de um conjunto bem "
+"conhecido, ficando sujeitas a ataques de força bruta, e devem ser regeradas."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Usuários deste sistema deverão ser informados desta mudança, pois eles serão "
+"alertados sobre a mudança de chave de host na próxima vez que logarem. Use "
+"'ssh-keygen -l -f ARQUIVO_COM_A_CHAVE_DE_HOST' após a atualização para "
+"exibir as impressões digitais (\"fingerprints\") das novas chaves de host."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "As chaves de host afetadas são:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Chaves de usuários também podem ser afetadas por este problema. O comando "
+"'ssh-vulnkey' pode ser usado como um teste parcial para isso. Veja /usr/"
+"share/doc/openssh-server/README.compromised-keys.gz para mais detalhes."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Gerar um novo arquivo de configuração para o OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Esta versão do OpenSSH possui um arquivo de configuração "
+#~ "consideravelmente diferente da versão fornecida com o Debian 'Potato', a "
+#~ "versão do Debian a partir da qual você parece estar atualizando. Este "
+#~ "pacote pode agora gerar um novo arquivo de configuração (/etc/ssh/"
+#~ "sshd_config), o qual irá funcionar com a nova versão do servidor sshd mas "
+#~ "não irá conter nenhuma personalização que você possa ter feito na versão "
+#~ "anterior."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Por favor, note que este novo arquivo de configuração irá definir o valor "
+#~ "da opção 'PermitRootLogin' para 'yes' (o que significa que qualquer "
+#~ "pessoa que conheça a senha do root poderá conectar via ssh diretamente "
+#~ "como root). Por favor, leia os arquivos README.Debian para maiores "
+#~ "detalhes sobre essa escolha de projeto."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "É fortemente recomendado que você escolha gerar um novo arquivo de "
+#~ "configuração agora."
diff --git a/debian/po/ro.po b/debian/po/ro.po
new file mode 100644 (file)
index 0000000..87480db
--- /dev/null
@@ -0,0 +1,224 @@
+# Romanian translation of openssh.
+# Copyright (C) 2006 THE openssh'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the openssh package.
+#
+# Stan Ioan-Eugen <stan.ieugen@gmail.com>, 2006.
+# Igor Stirbu <igor.stirbu@gmail.com>, 2007.
+# Cătălin Feștilă <catalinfest@gmail.com>,2008
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 1.4\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-28 17:54+0200\n"
+"Last-Translator: Cătălin Feștilă <catalinfest@gmail.com>\n"
+"Language-Team: Romanian <debian-l10n-romanian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
+"20)) ? 1 : 2;\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Doriți să riscați întreruperea sesiunilor ssh active?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Este foarte probabil ca această versiune de /etc/init.d/ssh pe care o aveți "
+"instalată să omoare toate instanțele sshd care rulează. Dacă faceți această "
+"actualizare printr-o sesiune ssh, atunci este posibil să fiți deconectați și "
+"actualizarea să rămână neterminată."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Puteți repară manual acest lucru adăugând „--pidfile /var/run/sshd.pid” la "
+"linia start-stop-daemon în secțiunea stop a fișierului."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "O cheie nouă este obligatorie"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Cheia curentă în /etc/ssh/ssh_host_key este criptată cu algoritmul IDEA. "
+"OpenSSH nu suportă acest tip de cheie, iar utilitarul ssh-keygen din "
+"versiunea SSH (non-liberă) anterior instalată nu pare să fie disponibil."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Va trebui să generați manual o nouă cheie pentru sistem."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Dezactivează modul de autentificare provocare-răspuns?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Autentificarea pe bază de parole pare dezactivată în configurația curentă a "
+"serverului OpenSSH. Pentru a împiedica utilizatorii să se autentifice "
+"folosind parole (probabil folosind doar autentificarea cu chei publice) în "
+"versiunile recente OpenSSH trebuie să dezactivați autentificarea tip "
+"provocare-răspuns, sau asigurați-vă că configurația PAM nu permite "
+"autentificarea cu fișierul de parole Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Dacă dezactivați autentificarea pe bază de provocare-răspuns, utilizatorii "
+"nu vor mai putea să se autentifice folosind parolele. Dacă nu o dezactivați "
+"(răspunsul implicit), atunci opțiunea 'PasswordAuthentification no' va fi "
+"utilizabilă doar dacă modificați și configurația PAM din /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Cheile vulnerabile vor fi regenerate"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Unele dintre cheile serverului OpenSSH gazdă de pe acest sistem au fost "
+"generate cu o versiune de OpenSSL, care a avut un generator de numere "
+"aleatorii stricat. Ca rezultat, aceste chei gazda sunt un set binecunoscut, "
+"sunt supuse la atacuri brute-force și trebuie să fie regenerate."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Utilizatorii acestui sistem ar trebui să fie informați ce se schimbă, "
+"deoarece se va solicita cheia gazdă ce se schimba data viitoare când se "
+"autentifică. Folosiți 'ssh-keygen -l -f HOST_KEY_FILE' după ce faceți "
+"actualizare pentru a imprima amprentele digitale ale noilor chei gazdă."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Cheile gazdă afectate sunt:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Cheile utilizatorului de asemenea, pot fi afectate de această problemă. "
+"Comanda 'ssh-vulnkey' poate fi folosită ca un test parțial pentru acestea. A "
+"se vedea /usr/share/doc/openssh-server/README.compromised-keys.gz pentru mai "
+"multe detalii."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Să se genereze un fișier nou de configurare pentru OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Această versiune de OpenSSH are un fișier de configurare considerabil "
+#~ "modificat față de versiunea care vine cu Debian 'Potato', pe care se pare "
+#~ "că o actualizați. Acest pachet poate genera acum un nou fișier de "
+#~ "configurare (/etc/ssh/sshd.config), care va funcționa cu noua versiune de "
+#~ "server, dar nu va conține nici o personalizare făcută pentru versiunea "
+#~ "anterioară."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "A se reține că acest fișier nou de configurare va stabili valoarea "
+#~ "opțiunii 'PermitRootLogin' la „yes” (ceea ce înseamnă că cine știe parola "
+#~ "de root se poate autentifica prin ssh direct ca root). Părerea "
+#~ "responsabilului de pachet este că aceasta trebuie să fie valoarea "
+#~ "implicită (a se vedea fișierul README.Debian pentru detalii "
+#~ "suplimentare), dar, dacă doriți, puteți edita oricând fișierul "
+#~ "sshd_config pentru a stabili valoarea opțiunii la „no”."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Este indicat să alegeți acum generarea un nou fișier de configurare."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Avertizare: trebuie să creați o nouă cheie pentru sistem"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr ""
+#~ "Avertizare: telnetd este instalat --- probabil că nu este o idee bună"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Un sfat bun este fie să ștergeți pachetul telnetd (dacă întradevăr nu-l "
+#~ "utilizați) fie să instalați telnetd-ssl astfel încât să existe "
+#~ "posibilitatea ca sesiunile telnet să nu trimită informații necriptate de "
+#~ "autentificare/parole prin rețea."
+
+#~ msgid "${HOST_KEYS}"
+#~ msgstr "${HOST_KEYS}"
diff --git a/debian/po/ru.po b/debian/po/ru.po
new file mode 100644 (file)
index 0000000..23b8c03
--- /dev/null
@@ -0,0 +1,209 @@
+# translation of ru.po to Russian
+# translation of openssh to Russian
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+#    Developers do not need to manually edit POT or PO files.
+#
+# Yuriy Talakan' <yt@drsk.ru>, 2007.
+# Yuri Kozlov <kozlov.y@gmail.com>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 1:4.7p1-9\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-18 08:55+0400\n"
+"Last-Translator: Yuri Kozlov <kozlov.y@gmail.com>\n"
+"Language-Team: Russian <debian-l10n-russian@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms:  nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Вы хотите пойти на риск потерять активные SSH соединения?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Установленная в настоящее время версия /etc/init.d/ssh, вероятно, уничтожит "
+"все запущенные экземпляры sshd. Если вы выполняете это обновление через SSH "
+"соединение, то скорее всего вы будете отключены и процедура обновления "
+"останется не завершенной."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Это может быть исправлено вручную добавлением \"--pidfile /var/run/sshd.pid"
+"\" в строку start-stop-daemon в разделе stop этого файла."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Необходим новый ключ хоста"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Текущий ключ хоста, /etc/ssh/ssh_host_key, зашифрован алгоритмом IDEA. "
+"OpenSSH не может работать с таким файлом ключа хоста, а утилита создания ssh-"
+"ключа (ssh-keygen) из прежней (не свободной) установки SSH, кажется, "
+"недоступна."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Вам нужно вручную создать новый ключ хоста."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Отключить аутентификацию запрос-ответ?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Кажется, что парольная аутентификация отключена в текущей настройке сервера "
+"OpenSSH. Чтобы запретить пользователям вход с использованием паролей "
+"(возможно, использовав вместо этого только аутентификацию по публичному "
+"ключу) в новых версиях OpenSSH, вы должны отключить аутентификацию запрос-"
+"ответ, либо убедиться, что ваша настройка PAM не разрешает аутентификацию по "
+"файлу паролей Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Если вы запретите аутентификацию запрос-ответ, пользователи не смогут войти "
+"с использованием паролей. Если вы оставите её разрешенной (ответ по "
+"умолчанию), то параметр 'PasswordAuthentication no' не будет иметь силы до "
+"тех пор, пока вы также не откорректируете настройки PAM в /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Уязвимые ключи хоста будут созданы заново"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Некоторые ключи хоста сервера OpenSSH в этой системе были созданы с помощью "
+"версии OpenSSL, в которой был испорченный генератор случайных чисел. В "
+"результате, такие ключи хоста входили во всем известный список, что "
+"позволяло применять атаку последовательного подбора ключей. Ключи должны "
+"быть созданы заново."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Пользователи этой системы будут проинформированы об этом изменении, так как "
+"им будет выведено сообщение о смене ключа хоста при следующем подключении. "
+"Используйте команду 'ssh-keygen -l -f HOST_KEY_FILE' после обновления для "
+"распечатки отпечатков новых ключей хоста."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Ключи хоста, которые будут заменены:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Пользовательские ключи также имеют данную проблему. Для частичной проверки "
+"можно воспользоваться командой 'ssh-vulnkey'. В файле /usr/share/doc/openssh-"
+"server/README.compromised-keys.gz дано более подробное описание."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Создать новый файл настроек для OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Файл настроек этой версии OpenSSH значительно отличается от файла версии, "
+#~ "которая поставлялась с Debian 'Potato', и которую вы, кажется, "
+#~ "обновляете. Этот пакет может сейчас создать новый файл настроек (/etc/ssh/"
+#~ "sshd.config), который будет работать с сервером новой версии, но не будет "
+#~ "содержать настроек, которые вы сделали в старой версии."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Обратите внимание, что этот новый файл настроек установит значение "
+#~ "параметра 'PermitRootLogin' в 'yes' (это означает, что каждый знающий "
+#~ "пароль суперпользователя может войти в систему по ssh как "
+#~ "суперпользователь). Пожалуйста, прочтите файл README.Debian для "
+#~ "разъяснения деталей этого выбора."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Настоятельно рекомендуется выбрать сейчас создание нового файла настроек."
diff --git a/debian/po/sk.po b/debian/po/sk.po
new file mode 100644 (file)
index 0000000..a10e09b
--- /dev/null
@@ -0,0 +1,188 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 1_4.6p1-5\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-29 08:51+0100\n"
+"Last-Translator: Ivan Masár <helix84@centrum.sk>\n"
+"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Chcete riskovať zrušenie aktívnych SSH relácií?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Momentálne nainštalovaná verzia /etc/init.d/ssh pravdepodobne ukončí všetky "
+"prebiehajúce inštancie sshd. Ak túto aktualizáciu vykonávate cez reláciu SSH "
+"pravdepodobne budete odpojený a aktualizácia zostane nedokončená."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Toto je možné manuálne napraviť tým, že pridáte „--pidfile /var/run/sshd."
+"pid“ do stop sekcie súboru start-stop-daemon."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Nový kľúč hostiteľa je povinný"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Aktuálny kľúč hostiteľa v /etc/ssh/ssh_host_key je kryptovaný algoritmom "
+"IDEA. OpenSSH nemôže pracovať s týmto súborom s kľúčom hostiteľa a nástroj "
+"ssh-keygen zo starej (neslobodnej) inštalácie SSH nie je dostupný."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Musíte ručne vygenerovať nový kľúč hostiteľa."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Vypnúť autentifikáciu výzva-odpoveď?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Zdá sa, že autentifikácia pomocou hesla je v aktuálnej konfigurácii OpenSSH "
+"servera vypnutá. Aby ste zabránili používateľom prihlasovať sa pomocou "
+"hesiel (snáď iba použitím autentifikácie svojím verejným kľúčom) pri novších "
+"verziách OpenSSH musíte vypnúť autentifikáciu výzva-odpoveď alebo sa inak "
+"uistiť, že vaša konfigurácia PAM neumožňuje autentifikáciu pomocu unixového "
+"súboru s heslami."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Ak vypnete autentifikáciu výzva-odpoveď, používatelia sa nebudú môcť "
+"prihlasovať pomocou hesiel. Ak ju necháte zapnutú (štandardná odpoveď), "
+"potom nebude mať voľba „PasswordAuthentication no“ žiadny účinok v prípade, "
+"že tiež vhodne nenastavíte vašu konfiguráciu PAM v /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Namiesto zneužiteľných kľúčov hostiteľa sa vytvoria nové"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Niektoré z OpenSSH klúčov hostiteľa na tomto systéme boli vytvorené verziou "
+"OpenSSL, ktorá mala chybný generátor náhodných čísel. Dôsledkom je, že tieto "
+"klúče hostiteľa sú z vopred známej množiny, je možné ich prelomiť hrubou "
+"silou a je potrebné vytvoriť namiesto nich nové."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Používateľov tohoto systému by ste mali informovať o tejto zmene, pretože "
+"pri najbližšom prihlásení sa im zobrazí výzva o zmenenom kľúči hostiteľa. Po "
+"aktualizácii vypíšete odtlačky nových kľúčov hostiteľa príkazom „ssh-keygen -"
+"l -f HOST_KEY_FILE“."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Postihnuté kľúče sú:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Používateľské kľúče tiež mohol ovplyvniť tento problém. Na čiastočný test "
+"zraniteľnosti je možné použiť príkaz „ssh-vulnkey“. Podrobnosti nájdete v /"
+"usr/share/doc/openssh-server/README.compromised-keys.gz"
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Vytvoriť nový konfiguračný súbor pre OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Táto verzia OpenSSH má podstatne zmenený konfiguračný súbor v porovnaní s "
+#~ "versiou, ktorá sa dodávala s Debian „Potato“, z ktorej, zdá sa, "
+#~ "aktualizujete. Tento balík teraz môže vytvoriť nový konfiguračný súbor (/"
+#~ "etc/ssh/sshd.config), ktorý bude fungovať s novou verziou servera, ale "
+#~ "nebude obsahovať akékoľvek zmeny, ktoré ste urobili v starej verzii."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Prosím, majte na pamäti, že tento nový konfiguračný súbor nastaví hodnotu "
+#~ "„'PermitRootLogin“ na „áno“ (čo znamená, že každý, kto pozná heslo účtu "
+#~ "root, sa bude môcť pomocou ssh prihlásiť priamo ako root). Prosím, "
+#~ "prečítajte si podrobnosti o tejto voľbe pri návrhu v súbore README.Debian."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Silne sa odporúča, aby ste teraz zvolili vytvorenie nového konfiguračného "
+#~ "súboru."
diff --git a/debian/po/sv.po b/debian/po/sv.po
new file mode 100644 (file)
index 0000000..cd28386
--- /dev/null
@@ -0,0 +1,197 @@
+# translation of openssh.po to swedish
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Martin Bagge <martin.bagge@bthstudent.se>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-25 23:32+0200\n"
+"Last-Translator: Martin Bagge <martin.bagge@bthstudent.se>\n"
+"Language-Team: swedish <sv@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Vill du riskera att döda aktiva SSH-sessioner?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Den för närvarande installerade versionen av /etc/init.d/ssh kommer "
+"antagligen döda alla körande instanser av sshd.  Om du gör denna "
+"uppgradering via en SSH-session kommer du sannolikt att kopplas ner och "
+"uppgraderingsprocessen lämnas ofärdig."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Det här kan rättas till genom att manuellt lägga till \"--pidfile /var/run/"
+"sshd.pid\" till raden \"start-stop-daemon\" i sektionen \"stop\" i filen."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Ny värdnyckel är obligatorisk"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Den aktuella värdnyckeln i /etc/ssh/ssh_host_key är krypterad med IDEA-"
+"algoritmen. OpenSSH kan inte hantera den här värdnyckelfilen och verktyget "
+"ssh-keygen från den gamla (ickefria) SSH-installationen verkar inte finnas "
+"tillgänglig."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Du behöver manuellt generera en ny värdnyckel."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Inaktivera challenge-response-autentisering?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Lösenordsautentisering verkar vara inaktiverat i din aktuella konfiguration "
+"av OpenSSH-servern. För att förhindra att användare loggar in med lösenord "
+"(istället kanske endast använder publik nyckelautentisering) med senare "
+"versioner av OpenSSH, måste du inaktivera challenge-response-autentisering "
+"eller försäkra dig om att din PAM-konfiguration inte tillåter autentisering "
+"via Unix lösenordsfil."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Om du inaktiverar  challenge-response-autentisering så kan användarna inte "
+"logga in med lösenord. Om du lämnar det aktiverat (som är standard) så "
+"kommer \"PasswordAuthentication no\" inte att ha någon effekt om du inte "
+"justerar din PAM-konfiguration i /etc/pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Sårbara värdnycklar kommer att omskapas"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Några av värdnycklarna för OpenSSH skapades med en version av OpenSSL som "
+"innehöll ett fel i slumptalsgeneratorn. På grund av detta är värden sårbar "
+"för en så kallad brute force-attack då nycklarna kommer från ett litet och "
+"välkänt spektra."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Användarna på det här systemet borde informeras om den här förändringen då "
+"de kommer att bli varse bytet av värdnyckel nästa gång de loggar in. Använd "
+"'ssh-keygen -l -f HOST_KEY_FILE' efter uppgraderingen har slutförst för att "
+"skriva ut fingeravtrycken för de nya värdnycklarna"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "De drabbade värdnycklarna är:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Användarnycklar kan också vara drabbade av detta fel. Kommandot 'ssh-"
+"vulnkey' kan användas som ett deltest. Läs /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz för mer ingående detaljer."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Generera en ny konfigurationsfil för OpenSSH?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Denna version av OpenSSH har ändrat konfigurationsfilen ansenligt från "
+#~ "den version som skickades med i Debians \"Potato\"-utgåva som du verkar "
+#~ "uppgradera från. Detta paket kan nu generera en ny konfigurationsfil (/"
+#~ "etc/ssh/sshd.config) som kommer att fungera med den nya serverversionen "
+#~ "men kommer inte att innehålla några anpassningar som du gjorde med den "
+#~ "gamla versionen."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Observera att den nya konfigurationsfilen kommer att ställa in värdet för "
+#~ "\"PermitRootLogin\" till \"yes\" (vilket betyder att vem som helst som "
+#~ "kan root-lösenordet kan logga in direkt som root). Läs filen README."
+#~ "Debian för mer information om det här designvalet."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Det rekommenderas starkt att du väljer att generera en ny "
+#~ "konfigurationsfil nu."
diff --git a/debian/po/ta.po b/debian/po/ta.po
new file mode 100644 (file)
index 0000000..cab323a
--- /dev/null
@@ -0,0 +1,181 @@
+# translation of openssh.po to TAMIL
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Dr.T.Vasudevan <agnihot3@gmail.com>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2007-04-24 20:52+0530\n"
+"Last-Translator: Dr.T.Vasudevan <agnihot3@gmail.com>\n"
+"Language-Team: TAMIL <ubuntu-l10n-tam@lists.ubuntu.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr ""
+"செயலில் இருக்கும் எஸ்எஸ்ஹெச் அமர்வுகளை செயல் நீக்கம் செய்வதை அனுமதிக்க விரும்புகிறீகளா?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"இப்போது நிறுவியுள்ள /etc/init.d/ssh பதிப்பு எல்லா செயலில் இருக்கும் எஸ்எஸ்ஹெச் "
+"அமர்வுகளை செயல் நீக்கம் செய்யும். நீங்கள் இந்த மேம்படுத்தலை எஸ்எஸ்ஹெச் அமர்வு வழியாக செய்து "
+"கொண்டிருந்தால் வலை இணப்பு துண்டிக்கப்பட்டு மேம்படுத்தல் நிறைவுறாது."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"இது கைமுறையாக கோப்பின் நிறுத்து பகுதியில் ஆரம்பி-நிறுத்து-கிங்கரன் வரியில் \"--"
+"pidfile /var/run/sshd.pid\" என சேர்ப்பதால் சரி செய்யப்படும்."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "புதிய புரவலன் விசை கட்டாயமாகும்"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"இப்போதைய /etc/ssh/ssh_host_key இல் உள்ள புரவலன் விசை IDEA அல்காரிதத்தில் குறியீடு "
+"செய்யப்பட்டது. இந்த புரவலன் விசையை ஓபன் எஸ்எஸ்ஹெச் கையாள இயலாது. பழைய பதிப்பிலிருந்து "
+"ssh-keygen பயன்பாடு இருப்பில் இல்லை."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "நீங்கள் கைமுறையாக புதிய புரவலன் விசையை உருவாக்க வேண்டும்."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "கேள்வி பதில் உறுதிப்படுத்தலை செயலிழக்க செய்யவா?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"இப்போதைய ஓபன் எஸ்எஸ்ஹெச் சேவையக வடிவமைப்பில் கடவுச்சொல் உறுதிப்படுத்தலை செயலிழக்க "
+"செய்துள்ளது. (திறந்த விசையை பயன்படுத்தி) பயனர்கள் உள்நுழைவதை தடுக்க சமீபத்திய ஓபன் "
+"எஸ்எஸ்ஹெச் பதிப்புகளில் நீங்கள் கேள்வி பதில் உறுதிப்படுத்தலை செயலிழக்க செய்ய வேண்டும். அல்லது "
+"உங்கள் பாம் வடிவமைப்பு யூனிக்ஸ் கடவுச்சொல் கோப்பு உறுதிப்படுத்தலை ஏற்காதவாறு அமைக்க "
+"வேண்டும்."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"நீங்கள் கேள்வி பதில் உறுதிப்படுத்தலை செயலிழக்க செய்தால் பயனர்கள் கடவுச்சொற்களை பயன் படுத்தி "
+"உள் நுழைய இயலாது. அதை செயல் படச்செய்தால் (கடவுச்சொல் உறுதிப்படுத்தல் தேர்வு இல்லை) "
+"'PasswordAuthentication no'  தேர்வு /etc/pam.d/ssh இல் பாம் வடிவமைப்பை சரி "
+"செய்தால் ஒழிய பயன் தராது."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "ஓபன் எஸ்எஸ்ஹெச் க்கு புதிய வடிவமைப்பு கோப்பை உருவாக்கவா?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "இந்த பதிப்பு ஓபன் எஸ்எஸ்ஹெச் நீங்கள் மேம்படுத்தும் டெபியன் பொடாடோவில் அமைந்த பதிப்பை "
+#~ "காட்டிலும் மிக மாறிய வடிவம் உடையது. இந்த பொதி இப்போது புதிய வடிவமைப்பு கோப்பை "
+#~ "உருவாக்கும். (/etc/ssh/sshd.config). இது புதிய சேவையக பதிப்பில் வேலை செய்யும். "
+#~ "ஆனால் நீங்கள் பழைய பதிப்பில் செய்த தனிப்படுத்தல் இயலாது."
+
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "இந்த புதிய வடிவமைப்பு கோப்பு 'PermitRootLogin மதிப்பை ஆம் என அமைக்கும் என "
+#~ "அறியவும். அதாவது ரூட் கடவுச்சொல் அறிந்த யாரும் ரூட்டாக ஓபன் எஸ்எஸ்ஹெச் வழியே "
+#~ "உள்நுழையலாம். இந்த வடிவமைப்பு குறித்து மேலும் README.Debian கோப்பில் காணவும்."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "நீங்கள் இப்போது புதிய வடிவமைப்பு கோப்பை உருவாக்க தேர்வு செய்ய பலமாக "
+#~ "பரிந்துரைக்கப்படுகிறது."
diff --git a/debian/po/templates.pot b/debian/po/templates.pot
new file mode 100644 (file)
index 0000000..de8023b
--- /dev/null
@@ -0,0 +1,131 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
diff --git a/debian/po/tr.po b/debian/po/tr.po
new file mode 100644 (file)
index 0000000..cff4ffa
--- /dev/null
@@ -0,0 +1,377 @@
+# Turkish translation of ssh.
+# This file is distributed under the same license as the ssh package.
+# Mert Dirik <mertdirik@gmail.com>, 2008.
+# Recai Oktaş <roktas@omu.edu.tr>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ssh\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-23 16:24+0200\n"
+"Last-Translator: Mert Dirik <mertdirik@gmail.com>\n"
+"Language-Team: Turkish <debian-l10n-turkish@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Etkin SSH oturumlarının öldürülmesi riskini göze alıyor musunuz?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Kurmuş olduğunuz /etc/init.d/ssh sürümü büyük olasılıkla, çalışıyor olan tüm "
+"sshd süreçlerini öldürecek. Bu yükseltmeyi bir ssh oturumu üzerinden "
+"yapıyorsanız büyük olasılıkla bağlantınız kopacak ve yükseltme işlemi yarım "
+"kalacak."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Bu sorunu dosyanın (/etc/init.d/ssh) stop bölümündeki start-stop-daemon "
+"satırına \"--pidfile /var/run/sshd.pid\" ekleyerek düzeltebilirsiniz."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Yeni makine anahtarı zorunlu"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Şu anda kullandığınız makine anahtarı, /etc/ssh/ssh_host_key, IDEA "
+"algoritmasıyla şifrelenmiş. OpenSSH bu anahtar dosyasını yönetemez; ayrıca "
+"eski (özgür olmayan) SSH kurulumuna ait ssh-keygen aracı da ulaşılabilir "
+"değil."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Yeni bir makine anahtarı oluşturmanız gerekiyor."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Sorgula-yanıtla yöntemiyle kimlik doğrulama devre dışı bırakılsın mı?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Şu anda kullanılan OpenSSH yapılandırmasında parola ile kimlik doğrulama "
+"devre dışı gibi görünüyor. OpenSSH'ın yeni versiyonlarında kullanıcıların "
+"parola kullanarak oturum açmalarını engellemek için (belki  bunun yerine "
+"açık anahtar yöntemiyle kimlik doğrulamayı kullanabilirsiniz) sorgula-"
+"yanıtla yöntemiyle kimlik doğrulamayı devre dışı bırakmalı ya da PAM "
+"yapılandırmanızın Unix parola dosyası yöntemiyle kimlik doğrulamaya izin "
+"vermediğinden emin olmalısınız."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Sorgula-yanıtla kimlik doğrulamayı devre dışı bırakırsanız, kullanıcılar "
+"parola kullanarak oturum açamayacaklar. Eğer sorgula-yanıtla kimlik "
+"doğrulamayı etkin halde bırakırsanız (öntanımlı yanıt); /etc/pam.d/ssh'daki "
+"PAM yapılandırmasını ayarlamadığınız sürece 'PasswordAuthentication no' "
+"seçeneği bir işe yaramayacak."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Saldırıya açık makine anahtarları yeniden yaratılacak"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Bu sistemdeki OpenSSH sunucusu makine anahtarlarından bazıları OpenSSL'in "
+"rastgele sayı üreticisi bozuk olan bir versiyonuyla oluşturulmuş. Sonuç "
+"olarak, bu makine anahtarları iyi bilinen bir gruptan ve kaba kuvvet "
+"saldırılarına açık. Bu anahtarlar yeniden oluşturulmalı."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Bu sistemin kullanıcılarını makine anahtarı değişikliğinden haberdar "
+"etmelisiniz, çünkü  kullanıcılar sisteme ilk oturum açışlarında uyarılacak "
+"ve kullanıcılara oturum açmaya devam etmek isteyip istemedikleri sorulacak. "
+"Yeni makine anahtarlarının parmak izlerini görmek için yükseltmeden sonra "
+"'ssh-keygen -l -f MAKİNE_ANAHTARI_DOSYASI' komutunu kullanın."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Etkilenmiş makine anahtarları:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Kullanıcı anahtarları da bu sorundan etkilenebilir.  'ssh-vulnkey' komutu bu "
+"sorun için kısmi bir test olarak kullanılabilir. Ayrıntılar için  /usr/share/"
+"doc/openssh-server/README.compromised-keys.gz belgesine bakın."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "OpenSSH için yeni yapılandırma dosyası oluşturulsun mu?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Debian 'Potato' dağıtımından yükseltme yapmış gibi görünüyorsunuz. "
+#~ "OpenSSH'ın bu sürümü Debian 'Potato' ile birlikte gelen sürümden çok "
+#~ "farklı bir yapılandırma dosyası kullanmakta. Bu paket şimdi sizin için "
+#~ "yeni bir yapılandırma dosyası (/etc/ssh/sshd.config) üretebilir. Bu dosya "
+#~ "yeni sunucu sürümüyle çalışacak, fakat eski sürümde yaptığınız "
+#~ "özelleştirmeleri içermeyecek."
+
+#~| msgid ""
+#~| "Please note that this new configuration file will set the value of "
+#~| "'PermitRootLogin' to yes (meaning that anyone knowing the root password "
+#~| "can ssh directly in as root). It is the opinion of the maintainer that "
+#~| "this is the correct default (see README.Debian for more details), but "
+#~| "you can always edit sshd_config and set it to no if you wish."
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Yeni yapılandırma dosyasının 'PermitRootLogin' seçeneğini 'yes' olarak "
+#~ "ayarlayacağını (yani root parolasını bilen herhangi birisinin ssh ile "
+#~ "doğrudan sisteme girebileceğini) unutmayın. Öntanımlı ayarın böyle olması "
+#~ "gerektiği paket geliştiricisinin kanaatidir (ayrıntılar için README."
+#~ "Debian dosyasını okuyun)."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr ""
+#~ "Şimdi yeni bir yapılandırma dosyası üretmeyi seçmeniz kuvvetle tavsiye "
+#~ "edilir."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Uyarı: yeni bir makine anahtarı oluşturmalısınız"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr "Uyarı: telnetd kurulmuş --- bu muhtemelen iyi bir fikir değil"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Telnetd paketini (eğer gerçekten telnet erişimi sunmak gibi bir "
+#~ "zorunluluğunuz yoksa) kaldırmanızı veya en azından, telnet oturumlarında "
+#~ "şifrelenmemiş giriş/parola ve oturum bilgilerinin ağ üzerinden "
+#~ "gönderilmemesi olanağını sunan telnetd-ssl paketini kurmanızı öneririm."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr "Uyarı: rsh-server kurulmuş --- bu muhtemelen iyi bir fikir değil"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "rsh-server'ın kurulu durumda olması muhtemelen ssh'ı kurmakla elde "
+#~ "edilmesini istediğiniz güvenliği gölgeliyor. Bu paketi kaldırmanızı "
+#~ "öneririm."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr ""
+#~ "ssh-keysign'ın root haklarıyla kurulmasını (SUID root) ister misiniz?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr ""
+#~ "ssh-keysign yardımcı aracının SUID bit'i etkinleştirilerek kurulması "
+#~ "seçeneğine sahipsiniz."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Eğer ssh-keysign'ı SUID yaparsanız, SSH'ın makine tabanlı Protokol 2 "
+#~ "yetkilendirmesini kullanabileceksiniz."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Bu konuda şüpheliyseniz, size SUID'li kurulumu öneririm. Eğer bu "
+#~ "sorunlara yol açarsa ileride fikrinizi değiştirmek için şu komutu "
+#~ "çalıştırabilirsiniz: dpkg-reconfigure ssh"
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Sadece SSH protokol 2'ye izin ver"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "OpenSSH'ın bu sürümü ssh'ın çok daha güvenli olan sürüm 2 protokolünü "
+#~ "destekler. Sürüm 1 protokolünün etkisizleştirilmesini teşvik ediyoruz, "
+#~ "bununla beraber böyle yapılması halinde düşük düzeyli makinelerde "
+#~ "işlemler yavaşlayacak ve eski sürüm ssh istemcilerinden (\"potato\" ile "
+#~ "birlikte gelen ssh istemcisi gibi) bağlantı kurulamayacaktır."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "Protokol 1 anahtarları çok farklı olduğundan, sadece protokol 2 "
+#~ "bağlantılarına izin vermeniz halinde bu anahtarları kullanamayacağınızı "
+#~ "da lütfen not edin."
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Bu ayar hakkındaki fikriniz ileride değişirse, sshd_config dosyasında "
+#~ "yapacağınız işlemlerle ilgili talimatları README.Debian dosyasında "
+#~ "bulabilirsiniz."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr ""
+#~ "NOT: X11 yönlendirme ve yetkilendirmesi öntanımlı olarak "
+#~ "etkisizleştirilmiştir."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "Güvenlik gerekçeleriyle ssh'ın Debian sürümünde ForwardX11 ve "
+#~ "ForwardAgent seçenekleri öntanımlı ``off'' değerine ayarlıdır."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Güvendiğiniz sunucular için bu seçeneği yapılandırma dosyalarından "
+#~ "birinde veya -X komut satırı seçeneğiyle etkinleştirebilirsiniz."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr ""
+#~ "Daha ayrıntılı bilgi /usr/share/doc/ssh/README.Debian dosyasında "
+#~ "bulunabilir."
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "yapılandırma dosyalarındaki ssh2 anahtarları birleştirildi"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "Sürüm 3 itibarıyla OpenSSH artık, ssh1 ve ssh2 için ayrı yapılandırma "
+#~ "dosyaları kullanmamaktadır. Bu, authorized_keys2 ve known_hosts2 "
+#~ "dosyalarının artık gerekmediği anlamına gelir. Geriye doğru uyumluluğu "
+#~ "korumak için bu dosyalar yine de okunacaktır."
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "SSH sunucusu sshd'yi çalıştırmak istiyor musunuz?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "Bu paket hem ssh istemcisini hem de sshd sunucusunu içeriyor."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "Güvenli Kabuk Sunucusu sshd, normalde ssh ile uzaktan girişlere izin "
+#~ "vermek için çalıştırılacaktır."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Eğer amacınız sadece bu makinedeki dış bağlantılar için ssh istemcisini "
+#~ "kullanmak ise ve bu makineye ssh'la girmek gibi bir şeyi de "
+#~ "istemiyorsanız, sshd sunucusunu bu adımda etkisizleştirebilirsiniz."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "Anahtarlara ilişkin ortam seçenekleri geçerliliğini kaybetmiştir"
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "OpenSSH'ın bu sürümü belirli atakları önlemek için (ör. LD_PRELOAD) ortak "
+#~ "anahtarlara ait ortam seçeneklerini öntanımlı olarak etkisizleştirir. "
+#~ "Eğer bu seçeneği bir authorized_keys dosyasında kullanıyorsanız, ilgili "
+#~ "seçenek silininceye kadar bu anahtarın artık çalışmayacağını unutmayın."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Bu seçeneği tekrar etkinleştirmek için, sshd_config(5) kılavuz "
+#~ "sayfasındaki uyarı notunu dikkate alarak, sshd yükseltmesi "
+#~ "tamamlandığında /etc/ssh/ssh_config dosyasında \"PermitUserEnvironment yes"
+#~ "\" satırını kullanın."
diff --git a/debian/po/uk.po b/debian/po/uk.po
new file mode 100644 (file)
index 0000000..7663a96
--- /dev/null
@@ -0,0 +1,387 @@
+# translation of openssh to Ukrainian
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans#
+#    Developers do not need to manually edit POT or PO files.
+# Eugeniy Meshcheryakov <eugen@univ.kiev.ua>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh-uk\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2005-03-28 22:28+0300\n"
+"Last-Translator: Eugeniy Meshcheryakov <eugen@univ.kiev.ua>\n"
+"Language-Team: Ukrainian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+"Plural-Forms:  nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid "Do you want to continue (and risk killing active ssh sessions)?"
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr ""
+"Чи бажаєте ви продовжувати (та ризикувати втратити активні сеанси ssh)?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "The version of /etc/init.d/ssh that you have installed, is likely to kill "
+#| "all running sshd instances.  If you are doing this upgrade via an ssh "
+#| "session, that would be a Bad Thing(tm)."
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Версія /etc/init.d/ssh, яку ви встановили, імовірно зупинить всі запущені "
+"процеси sshd. Якщо ви оновлюєтеся через ssh, це буде Погана річ (tm)."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "You can fix this by adding \"--pidfile /var/run/sshd.pid\" to the start-"
+#| "stop-daemon line in the stop section of the file."
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Ви можете виправити це, додавши \"--pidfile /var/run/sshd.pid\" до рядка з "
+"викликом start-stop-daemon в частині зупинки цього файла."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Старий ключ в /etc/ssh/ssh_host_key зашифрований за допомогою IDEA. OpenSSH "
+"не може обробляти такий файл ключа вузла, також неможливо знайти програму "
+"ssh-keygen зі старої (невільної) версії SSH."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+#| msgid "You will need to generate a new host key."
+msgid "You need to manually generate a new host key."
+msgstr "Вам потрібно створити новий ключ вузла."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Заборонити автентифікацію запит-відповідь?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+#, fuzzy
+#| msgid ""
+#| "Password authentication appears to be disabled in your current OpenSSH "
+#| "server configuration. In order to prevent users from logging in using "
+#| "passwords (perhaps using only public key authentication instead) with "
+#| "recent versions of OpenSSH, you must disable challenge-response "
+#| "authentication, or else ensure that your PAM configuration does not allow "
+#| "Unix password file authentication."
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Схоже, що автентифікація з використанням паролів заборонена у поточній "
+"конфігурації сервера OpenSSH. Щоб перешкодити користувачам реєструватися з "
+"використанням паролів (можливо, для автентифікації тільки за допомогою "
+"відкритих ключів) з останніми версіями OpenSSH, необхідно заборонити "
+"автентифікацію виклик-відгук або впевнитися, що налаштування PAM не "
+"дозволяють автентифікацію за допомогою файла паролів Unix."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Якщо ви забороните автентифікацію виклик-відгук, то ваші користувачі не "
+"зможуть реєструватися використовуючи паролі. Якщо ви залишите її дозволеною "
+"(відповідь за замовчанням), то опція 'PasswordAuthentication no' не буде "
+"мати корисного ефекту доки ви не пристосуєте також налаштування PAM в /etc/"
+"pam.d/ssh."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+
+#, fuzzy
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Створити новий файл налаштувань"
+
+#, fuzzy
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "В цій версії OpenSSH значно змінений файл налаштувань, в порівнянні з "
+#~ "версією, що входила в Debian 'Potato', і яку ви, схоже, оновлюєте. Зараз "
+#~ "можна створити новий файл налаштувань (/etc/ssh/sshd.config), що буде "
+#~ "працювати з новою версією сервера, але не буде містити будь-які зміни, "
+#~ "які ви внесли у стару версію."
+
+#, fuzzy
+#~| msgid ""
+#~| "Please note that this new configuration file will set the value of "
+#~| "'PermitRootLogin' to yes (meaning that anyone knowing the root password "
+#~| "can ssh directly in as root). It is the opinion of the maintainer that "
+#~| "this is the correct default (see README.Debian for more details), but "
+#~| "you can always edit sshd_config and set it to no if you wish."
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Зауважте, що в новій версії файла налаштувань змінна 'PermitRootLogin' "
+#~ "буде мати значення yes (що означає, що будь-яка людина, котра знає пароль "
+#~ "користувача root, зможе увійти в систему через ssh). На думку "
+#~ "супроводжуючого пакунку - це вірне значення за замовчанням (дивіться "
+#~ "також README.Debian), але ви завжди можете змінити значення цього "
+#~ "параметра у файлі sshd_config."
+
+#, fuzzy
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "Рекомендується дозволити створити новий файл налаштувань."
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "Попередження: ви повинні створити новий ключ вузла"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr "Попередження: telnetd встановлений - це погана ідея"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "Рекомендується або видалити пакунок telnetd (якщо вам не потрібно "
+#~ "надавати доступ через telnet), або встановити telnetd-ssl, щоб мати "
+#~ "можливість не передавати незашифровані логін/пароль та іншу інформацію "
+#~ "через мережу."
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr "Попередження: rsh-server встановлений - це погана ідея"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "Встановлений rsh-server знижує рівень безпеки, який ви, можливо, хотіли "
+#~ "отримати встановивши ssh. Рекомендується видалити цей пакунок."
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "Чи бажаєте ви, щоб ssh-keysign мав встановлений біт SUID?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr "Ви маєте можливість встановити біт SUID для програми ssh-keysign."
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "Якщо ви встановите біт SUID для ssh-keysign, ви зможете використовувати "
+#~ "вузлову автентифікацію протоколу SSH версії 2."
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "Якщо сумніваєтесь, то рекомендується дозволити встановити біт SUID. Якщо "
+#~ "це викликатиме проблеми, ви зможете все змінити запустивши dpkg-"
+#~ "reconfigure ssh"
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "Дозволити тільки SSH-протокол версії 2"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "Ця версія OpenSSH підтримує версію 2 протоколу SSH, яка є більш "
+#~ "безпечною. Рекомендується заборонити версію 1, однак це може уповільнити "
+#~ "роботу на слабких системах та зробити неможливим з'єднання з "
+#~ "використанням старих клієнтів (включно з клієнтом ssh з \"potato\")."
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "Також зверніть увагу, що ключі для версії 1 відрізняються від ключів для "
+#~ "версії 2, тому ви не зможете використовувати їх, якщо дозволите з'єднання "
+#~ "тільки по протоколу версії 2."
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "Якщо ви пізніше передумаєте щодо цього параметра, файл README.Debian "
+#~ "містить інструкції щодо внесення змін до файла sshd_config."
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "ssh2-ключі злиті у файлах налаштувань"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "У версії 3 OpenSSH більше не використовує окремі файли для ключів ssh1 та "
+#~ "ssh2. Це означає, що файли authorized_keys2 та known_hosts2 більше "
+#~ "непотрібні. Вони будуть читатися з метою забезпечення зворотної "
+#~ "сумісності."
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr ""
+#~ "ЗАУВАЖЕННЯ: Форвардинг X11 та Authorization заборонені за замовчанням."
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "З міркувань безпеки в Debian-версії ssh параметри ForwardX11 та "
+#~ "ForwardAgent за замовчанням мають значення \"off\"."
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "Ви можете дозволити їх для серверів, яким довіряєте, або у одному з "
+#~ "файлів налаштувань, або за допомогою параметра командного рядка -X."
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr "Подробиці можна прочитати у файлі /usr/share/doc/ssh/README.Debian"
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "Чи бажаєте ви запустити сервер sshd?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "Цей пакунок містить як клієнт ssh, так і сервер sshd."
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr ""
+#~ "Звичайно sshd (Secure Shell Server) запускається щоб зробити можливим "
+#~ "віддалену реєстрацію в системі за допомогою ssh."
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "Якщо вас цікавить використання тільки клієнта ssh на цій машині і ви не "
+#~ "бажаєте реєструватися на ній використовуючи ssh, тоді ви можете "
+#~ "заборонити sshd."
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "Опції оточення для ключів не повинні використовуватися"
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "В цій версії OpenSSH, з метою уникнення деяких атак (наприклад "
+#~ "LD_PRELOAD), за замовчанням заборонені опції оточення для відкритих "
+#~ "ключів. Якщо ви використовуєте цю опцію у файлі authorized_keys, майте на "
+#~ "увазі, що ключі з такими опціями не будуть працювати, доки опція не буде "
+#~ "видалена."
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "Щоб дозволити цю опцію, встановіть \"PermitUserEnvironment yes\" в /etc/"
+#~ "ssh/sshd_config після завершення оновлення; зверніть увагу на "
+#~ "попередження на сторінці підручника sshd_config(5)."
diff --git a/debian/po/vi.po b/debian/po/vi.po
new file mode 100644 (file)
index 0000000..a94514c
--- /dev/null
@@ -0,0 +1,212 @@
+# Vietnamese translation for OpenSSH.
+# Copyright © 2008 Free Software Foundation, Inc.
+# Clytie Siddall <clytie@riverland.net.au>, 2007-2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 1:4.7p1-9\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2008-05-19 16:49+0930\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: LocFactoryEditor 1.7b3\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "Bạn có muốn rủi ro giết phiên bản SSH đang chạy không?"
+
+# The version of /etc/init.d/ssh that you have installed, is likely to kill
+# all running sshd instances.  If you are doing this upgrade via an ssh
+# session, that would be a Bad Thing(tm).
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"Phiên bản « /etc/init.d/ssh » được cài đặt hiện thời rất có thể giết mọi tiến "
+"trình sshd đang chạy. Nếu bạn có nâng cấp qua phiên chạy SSH, rất có thể bạn "
+"bị ngắt kết nối, để lại tiến trình nâng cấp chưa hoàn tất."
+
+# You can fix this by adding \"--pidfile /var/run/sshd.pid\" to the start-
+# stop-daemon line in the stop section of the file.
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"Bạn vẫn còn có thể sửa chữa vấn đề này bằng cách tự thêm chuỗi « --pidfile /"
+"var/run/sshd.pid » vào dòng « start-stop-daemon » (khởi/ngừng chạy trình nền) "
+"trong phần « stop » (ngừng chạy) của tập tin đó."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr "Bắt buộc phải có khoá máy mới"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"Khoá máy hiện thời, trong « /etc/ssh/ssh_host_key », được mặt mã bằng thuật "
+"toán IDEA. Phần mềm OpenSSH không thể xử lý tập tin khoá máy kiểu này; cũng "
+"có vẻ là tiện ích « ssh-keygen » (tạo khoá SSH) thuộc về bản cài đặt SSH cũ "
+"(khác tự do) không sẵn sàng."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "You need to manually generate a new host key."
+msgstr "Vậy bạn cần phải tự tạo một khoá máy mới."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr "Tắt chức năng xác thực kiểu yêu cầu/đáp ứng không?"
+
+# Password authentication appears to be disabled in your current OpenSSH
+# server configuration. In order to prevent users from logging in using
+# passwords (perhaps using only public key authentication instead) with
+# recent versions of OpenSSH, you must disable challenge-response
+# authentication, or else ensure that your PAM configuration does not allow
+# Unix password file authentication.
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+"Có vẻ là chức năng xác thực bằng mật khẩu bị tắt trong cấu hình trình phục "
+"vụ OpenSSH hiện thời. Để ngăn cản người dùng đăng nhập bằng mật khẩu (có lẽ "
+"chỉ xác thực bằng khoá công)  với phiên bản OpenSSH gần đây, bạn cần phải "
+"tắt khả năng xác thực kiểu yêu cầu/đáp ứng (challenge-response "
+"authentication), không thì đảm bảo cấu hình PAM không cho phép xác thực bằng "
+"tập tin mật khẩu UNIX."
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+"Nếu bạn tắt khả năng xác thực kiểu yêu cầu/đáp ứng, người dùng sẽ không thể "
+"đăng nhập bằng mật khẩu. Để lại hoạt động (trả lời mặc định) thì tùy chọn « "
+"PasswordAuthentication no » (xác thực bằng mật khẩu : không) sẽ không có tác "
+"động thật, nếu bạn không điều chỉnh cấu hình PAM trong « /etc/pam.d/ssh »"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr "Mọi khoá máy dễ bị tấn công đều sẽ được tạo lại"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+"Một số khoá máy kiểu trình phục vụ OpenSSH trên hệ thống này đã được tạo "
+"bằng một phiên bản OpenSSL có một cơ chế tạo số ngẫu nhiên mà bị hỏng. Kết "
+"quả là những khoá máy này thuộc về một tập hợp ai cũng biết, có thể bị tấn "
+"công dùng sức mạnh vũ phu, và phải được tạo lại."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+"Các người dùng của hệ thống này nên được thông báo về thay đổi này, vì họ sẽ "
+"được nhắc cho thay đổi khoá máy này lần kế tiếp đăng nhập. Hãy dùng câu lệnh "
+"« ssh-keygen -l -f TẬP_TIN_KHOÁ_MÁY » sau khi nâng cấp, để in ra các vân tay "
+"của những khoá máy mới."
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr "Những máy khoá bị ảnh hưởng:"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+"Các khoá kiểu người dùng cũng có thể bị vấn đề này ảnh hưởng. Câu lệnh « ssh-"
+"vulnkey » có thể được sử dụng làm thử bộ phận để phát hiện các khoá vẫn còn "
+"dễ tấn công. Xem tài liệu Đọc Đi «  /usr/share/doc/openssh-server/README."
+"compromised-keys.gz » để tìm thêm chi tiết."
+
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "Tao ra tập tin cấu hình mới cho OpenSSH không?"
+
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "Phiên bản OpenSSH này có một tập tin cấu hình đã thay đổi nhiều so với "
+#~ "phiên bản có sẵn trong bản phát hành « Potato » của Debian, trong đó có vẻ "
+#~ "là bạn đang cập nhật. Gói hiện thời có khả năng tạo ra một tập tin cấu "
+#~ "hình mới (/etc/ssh/sshd.config), mà sẽ hoạt động được với phiên bản trình "
+#~ "phục vụ mới, nhưng không còn chứa lại mục sửa đổi nào bạn đã tạo trong "
+#~ "phiên bản cũ."
+
+# Please note that this new configuration file will set the value of
+# 'PermitRootLogin' to yes (meaning that anyone knowing the root password
+# can ssh directly in as root). It is the opinion of the maintainer that
+# this is the correct default (see README.Debian for more details), but you
+# can always edit sshd_config and set it to no if you wish.
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "Ghi chú rằng tập tin cấu hình mới này sẽ đặt giá trị của « PermitRootLogin "
+#~ "» thành « yes » (có : nghĩa là ai đó biết mật khẩu người chủ thì có khả "
+#~ "năng truy cập trực tiếp qua ssh với tư cách là người chủ). Xem tập tin "
+#~ "Đọc Đi « README.Debian » để tìm thêm chi tiết về sự chọn thiết kế này."
+
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "Rất khuyên bạn chọn tạo ra tập tin cấu hình mới ngay bây giờ."
diff --git a/debian/po/zh_CN.po b/debian/po/zh_CN.po
new file mode 100644 (file)
index 0000000..9eee59a
--- /dev/null
@@ -0,0 +1,389 @@
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openssh 3.6.1p2-11\n"
+"Report-Msgid-Bugs-To: openssh@packages.debian.org\n"
+"POT-Creation-Date: 2010-01-02 08:55+0000\n"
+"PO-Revision-Date: 2004-02-02 18:48+1300\n"
+"Last-Translator: Hiei Xu <nicky@mail.edu.cn>\n"
+"Language-Team: Chinese/Simplified <i18n-translation@lists.linux.net.cn>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid "Do you want to continue (and risk killing active ssh sessions)?"
+msgid "Do you want to risk killing active SSH sessions?"
+msgstr "您要继续吗(会有杀死活动的 ssh 会话的危险)?"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "The version of /etc/init.d/ssh that you have installed, is likely to kill "
+#| "all running sshd instances.  If you are doing this upgrade via an ssh "
+#| "session, that would be a Bad Thing(tm)."
+msgid ""
+"The currently installed version of /etc/init.d/ssh is likely to kill all "
+"running sshd instances. If you are doing this upgrade via an SSH session, "
+"you're likely to be disconnected and leave the upgrade procedure unfinished."
+msgstr ""
+"您安装的 /etc/init.d/ssh 版本很可能会杀死所有运行中的 sshd 例程。如果您是在通"
+"过 ssh 会话进行这项升级,那可真是件糟糕的事情(tm)。"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:1001
+#, fuzzy
+#| msgid ""
+#| "You can fix this by adding \"--pidfile /var/run/sshd.pid\" to the start-"
+#| "stop-daemon line in the stop section of the file."
+msgid ""
+"This can be fixed by manually adding \"--pidfile /var/run/sshd.pid\" to the "
+"start-stop-daemon line in the stop section of the file."
+msgstr ""
+"您可以通过添加“--pidfile /var/run/sshd.pid”到这个文件的 stop 部分的 start-"
+"stop-daemon 行来修正这个问题。"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+msgid "New host key mandatory"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+msgid ""
+"The current host key, in /etc/ssh/ssh_host_key, is encrypted with the IDEA "
+"algorithm. OpenSSH can not handle this host key file, and the ssh-keygen "
+"utility from the old (non-free) SSH installation does not appear to be "
+"available."
+msgstr ""
+"/etc/ssh/ssh_host_key 是由 IDEA 加密的旧密钥文件。OpenSSH 不能处理这种密钥文"
+"件,我也无法找到旧的(非自由的) SSH 安装所带的 ssh-keygen 密钥生成工具。"
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:2001
+#, fuzzy
+#| msgid "You will need to generate a new host key."
+msgid "You need to manually generate a new host key."
+msgstr "您需要创建一个新的主机密钥。"
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid "Disable challenge-response authentication?"
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"Password authentication appears to be disabled in the current OpenSSH server "
+"configuration. In order to prevent users from logging in using passwords "
+"(perhaps using only public key authentication instead) with recent versions "
+"of OpenSSH, you must disable challenge-response authentication, or else "
+"ensure that your PAM configuration does not allow Unix password file "
+"authentication."
+msgstr ""
+
+#. Type: boolean
+#. Description
+#: ../openssh-server.templates:3001
+msgid ""
+"If you disable challenge-response authentication, then users will not be "
+"able to log in using passwords. If you leave it enabled (the default "
+"answer), then the 'PasswordAuthentication no' option will have no useful "
+"effect unless you also adjust your PAM configuration in /etc/pam.d/ssh."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "Vulnerable host keys will be regenerated"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Some of the OpenSSH server host keys on this system were generated with a "
+"version of OpenSSL that had a broken random number generator. As a result, "
+"these host keys are from a well-known set, are subject to brute-force "
+"attacks, and must be regenerated."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"Users of this system should be informed of this change, as they will be "
+"prompted about the host key change the next time they log in. Use 'ssh-"
+"keygen -l -f HOST_KEY_FILE' after the upgrade to print the fingerprints of "
+"the new host keys."
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid "The affected host keys are:"
+msgstr ""
+
+#. Type: note
+#. Description
+#: ../openssh-server.templates:4001
+msgid ""
+"User keys may also be affected by this problem. The 'ssh-vulnkey' command "
+"may be used as a partial test for this. See /usr/share/doc/openssh-server/"
+"README.compromised-keys.gz for more details."
+msgstr ""
+
+#, fuzzy
+#~ msgid "Generate a new configuration file for OpenSSH?"
+#~ msgstr "生成新的配置文件"
+
+#, fuzzy
+#~ msgid ""
+#~ "This version of OpenSSH has a considerably changed configuration file "
+#~ "from the version shipped in Debian 'Potato', which you appear to be "
+#~ "upgrading from. This package can now generate a new configuration file (/"
+#~ "etc/ssh/sshd.config), which will work with the new server version, but "
+#~ "will not contain any customizations you made with the old version."
+#~ msgstr ""
+#~ "看来您正在从 Debian “Potato”升级,当前版本和 Debian “Potato”所带的 "
+#~ "OpenSSH 版本的配置文件对比有了相当多的改变。我现在可以生成适用于新服务器版"
+#~ "本的新配置文件 (/etc/ssh/sshd_config),但是它不会保留您为旧版本定制的任何"
+#~ "配置。"
+
+#, fuzzy
+#~| msgid ""
+#~| "Please note that this new configuration file will set the value of "
+#~| "'PermitRootLogin' to yes (meaning that anyone knowing the root password "
+#~| "can ssh directly in as root). It is the opinion of the maintainer that "
+#~| "this is the correct default (see README.Debian for more details), but "
+#~| "you can always edit sshd_config and set it to no if you wish."
+#~ msgid ""
+#~ "Please note that this new configuration file will set the value of "
+#~ "'PermitRootLogin' to 'yes' (meaning that anyone knowing the root password "
+#~ "can ssh directly in as root). Please read the README.Debian file for more "
+#~ "details about this design choice."
+#~ msgstr ""
+#~ "请注意新的配置文件将会把“PermitRootLogin”的值设置为 yes,(这意味着任何一个"
+#~ "知道 root 密码的人都可以直接以 root 登录)。维护者认为这是一个正确的默认值 "
+#~ "(详情请阅读 README.Debian),但如果您希望,也可以编辑 sshd_config 文件将其"
+#~ "设置为 no。"
+
+#, fuzzy
+#~ msgid ""
+#~ "It is strongly recommended that you choose to generate a new "
+#~ "configuration file now."
+#~ msgstr "强烈建议让我为您生成一份新的配置文件。"
+
+#~ msgid "Warning: you must create a new host key"
+#~ msgstr "警告:您必须创建一个新的主机密钥"
+
+#~ msgid "Warning: telnetd is installed --- probably not a good idea"
+#~ msgstr "警告:已经安装了 telnetd 服务器 --- 可能不是个好主意"
+
+#~ msgid ""
+#~ "I'd advise you to either remove the telnetd package (if you don't "
+#~ "actually need to offer telnet access) or install telnetd-ssl so that "
+#~ "there is at least some chance that telnet sessions will not be sending "
+#~ "unencrypted login/password and session information over the network."
+#~ msgstr ""
+#~ "我建议您删除 telnetd 包(如果您不是真的需要提供 telnet 访问),或者安装 "
+#~ "telnetd-ssl,这样至少有时候 telnet 会话不会将未加密的 登录名/密码 和会话信"
+#~ "息通过网络发送。"
+
+#~ msgid "Warning: rsh-server is installed --- probably not a good idea"
+#~ msgstr "警告:已经安装了 rsh 服务器 --- 可能不是个好主意"
+
+#~ msgid ""
+#~ "having rsh-server installed undermines the security that you were "
+#~ "probably wanting to obtain by installing ssh.  I'd advise you to remove "
+#~ "that package."
+#~ msgstr ""
+#~ "安装 rsh 服务器很可能会降低您想要通过安装 ssh 得到的安全性。我建议您删除这"
+#~ "个包。"
+
+#~ msgid "Do you want ssh-keysign to be installed SUID root?"
+#~ msgstr "您要将 ssh-keysign 安装为 SUID root 程序吗?"
+
+#~ msgid ""
+#~ "You have the option of installing the ssh-keysign helper with the SUID "
+#~ "bit set."
+#~ msgstr "您使用为 ssh-keysign 帮助者程序设置 SUID 位的选项。"
+
+#~ msgid ""
+#~ "If you make ssh-keysign SUID, you will be able to use SSH's Protocol 2 "
+#~ "host-based authentication."
+#~ msgstr ""
+#~ "如果您为 ssh-keysign 设置了 SUID,您将可以使用 SSH 协议 2 的基于主机的认证"
+#~ "方式。"
+
+#~ msgid ""
+#~ "If in doubt, I suggest you install it with SUID.  If it causes problems "
+#~ "you can change your mind later by running:   dpkg-reconfigure ssh"
+#~ msgstr ""
+#~ "如果有疑问,我建议您将它安装为 SUID。如果它带来麻烦,您可以通过运行:dpkg-"
+#~ "reconfigure ssh 来改变主意"
+
+#~ msgid "Allow SSH protocol 2 only"
+#~ msgstr "只允许 SSH 协议 2 (ssh2)。"
+
+#~ msgid ""
+#~ "This version of OpenSSH supports version 2 of the ssh protocol, which is "
+#~ "much more secure.  Disabling ssh 1 is encouraged, however this will slow "
+#~ "things down on low end machines and might prevent older clients from "
+#~ "connecting (the ssh client shipped with \"potato\" is affected)."
+#~ msgstr ""
+#~ "这个版本的 OpenSSH 支持更加安全的第二版本 ssh 协议。我们鼓励您禁用 ssh 1,"
+#~ "然而这会降低低端机器速度,并且会阻止老版客户端的连接(“potato”所带的 ssh 客"
+#~ "户端会受到影响)。"
+
+#~ msgid ""
+#~ "Also please note that keys used for protocol 1 are different so you will "
+#~ "not be able to use them if you only allow protocol 2 connections."
+#~ msgstr ""
+#~ "也请注意协议 1 所用的密钥是不同的,因此如果您只允许协议 2 连接将会导致不能"
+#~ "使用它们。"
+
+#~ msgid ""
+#~ "If you later change your mind about this setting, README.Debian has "
+#~ "instructions on what to do to your sshd_config file."
+#~ msgstr ""
+#~ "如果您稍后想改变这个设置,README.Debian 上有说明告诉您如何修改 "
+#~ "sshd_Config 文件。"
+
+#~ msgid "NOTE: Forwarding of X11 and Authorization disabled by default."
+#~ msgstr "注意:X11 转发和认证默认被禁止。"
+
+#~ msgid ""
+#~ "For security reasons, the Debian version of ssh has ForwardX11 and "
+#~ "ForwardAgent set to ``off'' by default."
+#~ msgstr ""
+#~ "因为安全性原因,默认情况下 Debian 版本的 ssh 将 ForwardX11 和 "
+#~ "ForwardAgent 设置为 off。"
+
+#~ msgid ""
+#~ "You can enable it for servers you trust, either in one of the "
+#~ "configuration files, or with the -X command line option."
+#~ msgstr ""
+#~ "您可以为信赖的服务器启用这个选项,可以通过其中之一的配置文件或者使用 -X 命"
+#~ "令行选项来实现。"
+
+#~ msgid "More details can be found in /usr/share/doc/ssh/README.Debian"
+#~ msgstr "更多细节可以在 /usr/share/doc/ssh/README.Debian 找到"
+
+#~ msgid "ssh2 keys merged in configuration files"
+#~ msgstr "ssh2 密钥被合并到配置文件"
+
+#~ msgid ""
+#~ "As of version 3 OpenSSH no longer uses separate files for ssh1 and ssh2 "
+#~ "keys. This means the authorized_keys2 and known_hosts2 files are no "
+#~ "longer needed. They will still be read in order to maintain backwards "
+#~ "compatibility"
+#~ msgstr ""
+#~ "在 OpenSSH 第 3 版不再为 ssh1 和 ssh2 的密钥使用不同的文件。这意味着 "
+#~ "authorized_keys2 和 known_hosts2 文件将不再需要。但为了保持向后兼容性,它"
+#~ "们仍会被读取。"
+
+#~ msgid "Do you want to run the sshd server?"
+#~ msgstr "您要运行 sshd 服务器吗?"
+
+#~ msgid "This package contains both the ssh client, and the sshd server."
+#~ msgstr "这个软件包内含 ssh 客户端和 sshd 服务器。"
+
+#~ msgid ""
+#~ "Normally the sshd Secure Shell Server will be run to allow remote logins "
+#~ "via ssh."
+#~ msgstr "通常 sshd 安全 Shell 服务器都会运行以便允许通过 ssh 进行远程登录。"
+
+#~ msgid ""
+#~ "If you are only interested in using the ssh client for outbound "
+#~ "connections on this machine, and don't want to log into it at all using "
+#~ "ssh, then you can disable sshd here."
+#~ msgstr ""
+#~ "如果您只要在这台机器上使用 ssh 客户端对外连接,完全不想通过 ssh 登录到本"
+#~ "机,那么您可以在这里禁用 sshd 服务器。"
+
+#~ msgid "Environment options on keys have been deprecated"
+#~ msgstr "密钥的环境选项已被废弃"
+
+#~ msgid ""
+#~ "This version of OpenSSH disables the environment option for public keys "
+#~ "by default, in order to avoid certain attacks (for example, LD_PRELOAD). "
+#~ "If you are using this option in an authorized_keys file, beware that the "
+#~ "keys in question will no longer work until the option is removed."
+#~ msgstr ""
+#~ "为了避免一些攻击(如 LD_PRELOAD),这个版本的 OpenSSH 默认禁用了公钥上的环境"
+#~ "选项。如果您在某个授权密钥(authorized_keys)文件中用了这个参数,请注意除非"
+#~ "删除了此选项,否则这个可疑的密钥将不再起作用。"
+
+#~ msgid ""
+#~ "To re-enable this option, set \"PermitUserEnvironment yes\" in /etc/ssh/"
+#~ "sshd_config after the upgrade is complete, taking note of the warning in "
+#~ "the sshd_config(5) manual page."
+#~ msgstr ""
+#~ "要重新启用这个选项,升级完成后请在 /etc/ssh/sshd_config 中加入一"
+#~ "行:“PermitUserEnvironment yes”。请注意 sshd_config(5) 手册页中提到的警"
+#~ "告。"
+
+#~ msgid "Privilege separation"
+#~ msgstr "权限分离"
+
+#~ msgid ""
+#~ "Privilege separation is turned on by default, so if you decide you want "
+#~ "it turned off, you need to add \"UsePrivilegeSeparation no\" to /etc/ssh/"
+#~ "sshd_config."
+#~ msgstr ""
+#~ "权限分离选项是默认打开的。如果想要关闭此选项,您需要在 /etc/ssh/"
+#~ "sshd_config 文件中添加一行“UsePrivilegeSeparation no”。"
+
+#~ msgid "Enable Privilege separation"
+#~ msgstr "启用权限分离"
+
+#~ msgid ""
+#~ "This version of OpenSSH contains the new privilege separation option. "
+#~ "This significantly reduces the quantity of code that runs as root, and "
+#~ "therefore reduces the impact of security holes in sshd."
+#~ msgstr ""
+#~ "这个版本的 OpenSSH 包含了一个新的权限分离的选项,目的是为了减少以 root 运"
+#~ "行的代码数目,进而减少了 sshd 被安全漏洞影响的机会。"
+
+#~ msgid ""
+#~ "Unfortunately, privilege separation interacts badly with PAM. Any PAM "
+#~ "session modules that need to run as root (pam_mkhomedir, for example) "
+#~ "will fail, and PAM keyboard-interactive authentication won't work."
+#~ msgstr ""
+#~ "不幸的是,权限分离和 PAM 同时使用会很糟糕。任何需要以 root 运行的 PAM 会话"
+#~ "模块 (如 pam_mkhomedir) 都会失败,而且 PAM 键盘交互式认证都不起作用。"
+
+#~ msgid ""
+#~ "Since you've opted to have me generate an sshd_config file for you, you "
+#~ "can choose whether or not to have privilege separation turned on or not. "
+#~ "Unless you know you need to use PAM features that won't work with this "
+#~ "option, you should enable it."
+#~ msgstr ""
+#~ "因为您选择了让我为您生成 sshd_config 文件,您可以选择是否打开权限分离选"
+#~ "项。除非您知道需要使用 PAM 这个不能和权限分离同时工作的功能,否则就应该启"
+#~ "用它。"
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..ce56fde
--- /dev/null
@@ -0,0 +1,226 @@
+#!/usr/bin/make -f
+
+# Uncomment this to turn on verbose mode.
+# export DH_VERBOSE=1
+
+include /usr/share/hardening-includes/hardening.make
+
+# This has to be exported to make some magic below work.
+export DH_OPTIONS
+
+ifeq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
+OPTFLAGS := -O2
+else
+OPTFLAGS := -O0
+endif
+
+ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
+  RUN_TESTS := yes
+else
+  RUN_TESTS :=
+endif
+
+DEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
+  CC := gcc
+else
+  CC := $(DEB_HOST_GNU_TYPE)-gcc
+  RUN_TESTS :=
+endif
+
+DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS 2>/dev/null)
+DEB_HOST_ARCH_CPU := $(shell dpkg-architecture -qDEB_HOST_ARCH_CPU 2>/dev/null)
+
+# Take account of old dpkg-architecture output.
+ifeq ($(DEB_HOST_ARCH_OS),)
+  DEB_HOST_ARCH_OS := $(subst -gnu,,$(shell dpkg-architecture -qDEB_HOST_GNU_SYSTEM))
+  ifeq ($(DEB_HOST_ARCH_OS),gnu)
+    DEB_HOST_ARCH_OS := hurd
+  endif
+endif
+ifeq ($(DEB_HOST_ARCH_CPU),)
+  DEB_HOST_ARCH_CPU := $(shell dpkg-architecture -qDEB_HOST_GNU_CPU)
+  ifeq ($(DEB_HOST_ARCH_CPU),x86_64)
+    DEB_HOST_ARCH_CPU := amd64
+  endif
+endif
+
+ifneq (,$(findstring :$(DEB_HOST_ARCH_OS):,:linux:knetbsd:))
+  ifneq (,$(findstring :$(DEB_HOST_ARCH_CPU):,:mips:mipsel:))
+    # Apparently this is not implied by -fPIE, at least on the mipsen.
+    PIC_CFLAGS := -fPIC
+    PIC_LDFLAGS := -fPIC
+  endif
+endif
+
+# Change the version string to include the Debian version
+SSH_EXTRAVERSION := Debian-$(shell dpkg-parsechangelog | sed -n -e '/^Version:/s/Version: //p' | sed -e 's/[^-]*-//')
+
+DISTRIBUTOR := $(shell dpkg-vendor --derives-from Ubuntu 2>/dev/null && echo Ubuntu)
+ifeq ($(DISTRIBUTOR),Ubuntu)
+DEFAULT_PATH := /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games
+else
+DEFAULT_PATH := /usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
+endif
+SUPERUSER_PATH := /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11
+
+ifeq ($(DISTRIBUTOR),Ubuntu)
+server_recommends := ssh-import-id
+else
+server_recommends :=
+endif
+
+# Common path configuration.
+confflags += --sysconfdir=/etc/ssh
+
+# Common build options.
+confflags += --disable-strip
+confflags += --with-mantype=doc
+confflags += --with-4in6
+confflags += --with-privsep-path=/var/run/sshd
+
+# The Hurd needs libcrypt for res_query et al.
+ifeq ($(DEB_HOST_ARCH_OS),hurd)
+confflags += --with-libs=-lcrypt
+endif
+
+# Everything above here is common to the deb and udeb builds.
+confflags_udeb := $(confflags)
+
+# Options specific to the deb build.
+confflags += --with-tcp-wrappers
+confflags += --with-pam
+confflags += --with-libedit
+confflags += --with-kerberos5=/usr
+confflags += --with-ssl-engine
+ifeq ($(DEB_HOST_ARCH_OS),linux)
+confflags += --with-selinux
+endif
+
+# The deb build wants xauth; the udeb build doesn't.
+confflags += --with-xauth=/usr/bin/xauth
+confflags_udeb += --without-xauth
+
+# Default paths. The udeb build has /usr/bin/X11 and /usr/games removed.
+confflags += --with-default-path=$(DEFAULT_PATH) --with-superuser-path=$(SUPERUSER_PATH)
+confflags_udeb += --with-default-path=/usr/local/bin:/usr/bin:/bin --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+
+# Compiler flags.
+cflags := $(OPTFLAGS) $(PIC_CFLAGS) $(HARDENING_CFLAGS)
+cflags += -DLOGIN_PROGRAM=\"/bin/login\" -DLOGIN_NO_ENDOPT
+cflags += -DSSH_EXTRAVERSION=\"$(SSH_EXTRAVERSION)\"
+cflags_udeb := -Os
+cflags_udeb += -DSSH_EXTRAVERSION=\"$(SSH_EXTRAVERSION)\"
+confflags += --with-cflags='$(cflags)'
+confflags_udeb += --with-cflags='$(cflags_udeb)'
+
+# Linker flags.
+confflags += --with-ldflags='$(strip -Wl,--as-needed $(PIC_LDFLAGS) $(HARDENING_LDFLAGS))'
+confflags_udeb += --with-ldflags='-Wl,--as-needed'
+
+%:
+       dh $@
+
+override_dh_auto_configure:
+       dh_auto_configure -Bbuild-deb -- $(confflags)
+       dh_auto_configure -Bbuild-udeb -- $(confflags_udeb)
+
+override_dh_auto_build:
+       # Debian's /var/log/btmp has inappropriate permissions.
+       perl -pi -e 's,.*#define USE_BTMP .*,/* #undef USE_BTMP */,' build-deb/config.h
+       perl -pi -e 's,.*#define USE_BTMP .*,/* #undef USE_BTMP */,' build-udeb/config.h
+
+       # Avoid libnsl linkage. Ugh.
+       perl -pi -e 's/ +-lnsl//' build-udeb/config.status
+       cd build-udeb && ./config.status
+
+       $(MAKE) -C build-deb -j 2 ASKPASS_PROGRAM='/usr/bin/ssh-askpass'
+       $(MAKE) -C build-udeb -j 2 ASKPASS_PROGRAM='/usr/bin/ssh-askpass' ssh scp sftp sshd ssh-keygen
+
+       $(MAKE) -C contrib gnome-ssh-askpass2 CC='$(CC) $(OPTFLAGS) -g -Wall -Wl,--as-needed'
+
+override_dh_auto_test:
+ifeq ($(RUN_TESTS),yes)
+       $(MAKE) -C debian/tests
+endif
+
+override_dh_auto_clean:
+       rm -rf build-deb build-udeb
+ifeq ($(RUN_TESTS),yes)
+       $(MAKE) -C debian/tests clean
+endif
+       $(MAKE) -C contrib clean
+       (cat debian/copyright.head; iconv -f ISO-8859-1 -t UTF-8 LICENCE) \
+               > debian/copyright
+
+override_dh_auto_install:
+       $(MAKE) -C build-deb DESTDIR=`pwd`/debian/tmp install-nokeys
+
+override_dh_install:
+       rm -f debian/tmp/etc/ssh/sshd_config
+
+       dh_install -Nopenssh-client-udeb -Nopenssh-server-udeb --fail-missing
+       dh_install -popenssh-client-udeb -popenssh-server-udeb \
+               --sourcedir=build-udeb
+
+       install -s -o root -g root -m 755 contrib/gnome-ssh-askpass2 debian/ssh-askpass-gnome/usr/lib/openssh/gnome-ssh-askpass
+
+       install -o root -g root debian/openssh-server.if-up debian/openssh-server/etc/network/if-up.d/openssh-server
+       install -o root -g root -m 644 debian/openssh-server.ufw.profile debian/openssh-server/etc/ufw/applications.d/openssh-server
+
+       # Remove version control tags to avoid unnecessary conffile
+       # resolution steps for administrators.
+       sed -i '/\$$OpenBSD:/d' \
+               debian/openssh-client/etc/ssh/moduli \
+               debian/openssh-client/etc/ssh/ssh_config
+
+override_dh_installdocs:
+       dh_installdocs -Nopenssh-server -Nssh
+       dh_installdocs -popenssh-server -pssh --link-doc=openssh-client
+       # Avoid breaking dh_installexamples later.
+       mkdir -p debian/openssh-server/usr/share/doc/openssh-client
+
+override_dh_installinit:
+       dh_installinit -n --name ssh
+
+override_dh_installpam:
+       dh_installpam --name sshd
+
+override_dh_fixperms:
+       dh_fixperms
+       chmod u+s debian/openssh-client/usr/lib/openssh/ssh-keysign
+
+override_dh_installdeb:
+       dh_installdeb
+       perl -i debian/substitute-conffile.pl \
+               ETC_SSH_MODULI debian/openssh-client/etc/ssh/moduli \
+               ETC_SSH_SSH_CONFIG debian/openssh-client/etc/ssh/ssh_config \
+               debian/openssh-client/DEBIAN/preinst
+       # Yes, ETC_PAM_D_SSH is meant to be spelled that way, to match the
+       # old configuration file name we need to transfer.
+       perl -i debian/substitute-conffile.pl \
+               ETC_DEFAULT_SSH debian/openssh-server/etc/default/ssh \
+               ETC_INIT_D_SSH debian/openssh-server/etc/init.d/ssh \
+               ETC_PAM_D_SSH debian/openssh-server/etc/pam.d/sshd \
+               debian/openssh-server/DEBIAN/preinst
+
+override_dh_gencontrol:
+       dh_gencontrol -- -V'openssh-server:Recommends=$(server_recommends)'
+
+debian/faq.html:
+       wget -O - http://www.openssh.org/faq.html | \
+               sed 's,\(href="\)\(txt/\|[^":]*\.html\),\1http://www.openssh.org/\2,g' \
+               > debian/faq.html
+
+# You only need to run this immediately after checking out the package from
+# revision control.
+quilt-setup:
+       [ ! -d .pc ]
+       set -e; for patch in $$(quilt series | tac); do \
+               patch -p1 -R --no-backup-if-mismatch <"debian/patches/$$patch"; \
+       done
+       quilt push -a
+
+.PHONY: quilt-setup
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/include-binaries b/debian/source/include-binaries
new file mode 100644 (file)
index 0000000..df5790e
--- /dev/null
@@ -0,0 +1 @@
+debian/ssh-askpass-gnome.png
diff --git a/debian/ssh-argv0 b/debian/ssh-argv0
new file mode 100644 (file)
index 0000000..67599ae
--- /dev/null
@@ -0,0 +1,30 @@
+#! /bin/sh -e
+
+# Copyright (c) 2001 Jonathan Amery.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+if [ "${0##*/}" = "ssh-argv0" ]
+then
+  echo 'ssh-argv0: This script should not be run like this, see ssh-argv0(1) for details' 1>&2
+  exit 1
+fi
+exec ssh "${0##*/}" "$@"
diff --git a/debian/ssh-argv0.1 b/debian/ssh-argv0.1
new file mode 100644 (file)
index 0000000..a36a63d
--- /dev/null
@@ -0,0 +1,64 @@
+.Dd September 7, 2001 
+.Dt SSH-ARGV0 1
+.Os Debian Project
+.Sh NAME
+.Nm ssh-argv0
+.Nd replaces the old ssh command-name as hostname handling
+.Sh SYNOPSIS
+.Ar hostname | user@hostname
+.Op Fl l Ar login_name
+.Op Ar command
+.Pp
+.Ar hostname | user@hostname
+.Op Fl afgknqstvxACNTX1246
+.Op Fl b Ar bind_address
+.Op Fl c Ar cipher_spec
+.Op Fl e Ar escape_char
+.Op Fl i Ar identity_file
+.Op Fl l Ar login_name
+.Op Fl m Ar mac_spec
+.Op Fl o Ar option
+.Op Fl p Ar port
+.Op Fl F Ar configfile
+.Oo Fl L Xo
+.Sm off
+.Ar port :
+.Ar host :
+.Ar hostport
+.Sm on
+.Xc
+.Oc
+.Oo Fl R Xo
+.Sm off
+.Ar port :
+.Ar host :
+.Ar hostport
+.Sm on
+.Xc
+.Oc
+.Op Fl D Ar port
+.Op Ar command
+.Sh DESCRIPTION
+.Nm
+replaces the old ssh command-name as hostname handling.
+If you link to this script with a hostname then executing the link is
+equivalent to having executed ssh with that hostname as an argument.
+All other arguments are passed to ssh and will be processed normally.
+.Sh OPTIONS
+See
+.Xr ssh 1 .
+.Sh FILES
+See
+.Xr ssh 1 .
+.Sh AUTHORS
+OpenSSH is a derivative of the original and free
+ssh 1.2.12 release by Tatu Ylonen.
+Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
+Theo de Raadt and Dug Song
+removed many bugs, re-added newer features and
+created OpenSSH.
+Markus Friedl contributed the support for SSH
+protocol versions 1.5 and 2.0.
+Jonathan Amery wrote this ssh-argv0 script and the associated documentation.
+.Sh SEE ALSO
+.Xr ssh 1
diff --git a/debian/ssh-askpass-gnome.copyright b/debian/ssh-askpass-gnome.copyright
new file mode 100644 (file)
index 0000000..4a71dda
--- /dev/null
@@ -0,0 +1,44 @@
+This package contains a Gnome based implementation of ssh-askpass
+written by Damien Miller.
+
+It is split out from the main package to isolate the dependency on the
+Gnome and X11 libraries.
+
+It was packaged for Debian by Philip Hands <phil@hands.com>.
+
+Copyright:
+
+/*
+**
+** GNOME ssh passphrase requestor
+**
+** Damien Miller <djm@ibs.com.au>
+** 
+** Copyright 1999 Internet Business Solutions
+**
+** Permission is hereby granted, free of charge, to any person
+** obtaining a copy of this software and associated documentation
+** files (the "Software"), to deal in the Software without
+** restriction, including without limitation the rights to use, copy,
+** modify, merge, publish, distribute, sublicense, and/or sell copies
+** of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+** AND NONINFRINGEMENT.  IN NO EVENT SHALL DAMIEN MILLER OR INTERNET
+** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+** OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** Except as contained in this notice, the name of Internet Business
+** Solutions shall not be used in advertising or otherwise to promote
+** the sale, use or other dealings in this Software without prior
+** written authorization from Internet Business Solutions.
+**
+*/
diff --git a/debian/ssh-askpass-gnome.desktop b/debian/ssh-askpass-gnome.desktop
new file mode 100644 (file)
index 0000000..eba7a67
--- /dev/null
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Version=1.0
+Encoding=UTF-8
+Name=SSH AskPass
+GenericName=ssh-add
+Comment=Enter passphrase to authenticate to the ssh agent
+Exec=/usr/bin/ssh-add
+TryExec=ssh-add
+Terminal=false
+Type=Application
+Icon=ssh-askpass-gnome
+Categories=Network;Security;
diff --git a/debian/ssh-askpass-gnome.dirs b/debian/ssh-askpass-gnome.dirs
new file mode 100644 (file)
index 0000000..0ffa450
--- /dev/null
@@ -0,0 +1,3 @@
+usr/lib/openssh
+usr/share/man/man1
+usr/share/pixmaps
diff --git a/debian/ssh-askpass-gnome.examples b/debian/ssh-askpass-gnome.examples
new file mode 100644 (file)
index 0000000..66fd8c0
--- /dev/null
@@ -0,0 +1 @@
+debian/ssh-askpass-gnome.desktop
diff --git a/debian/ssh-askpass-gnome.install b/debian/ssh-askpass-gnome.install
new file mode 100644 (file)
index 0000000..8b6b5f0
--- /dev/null
@@ -0,0 +1 @@
+debian/ssh-askpass-gnome.png usr/share/pixmaps
diff --git a/debian/ssh-askpass-gnome.manpages b/debian/ssh-askpass-gnome.manpages
new file mode 100644 (file)
index 0000000..7749f13
--- /dev/null
@@ -0,0 +1 @@
+debian/gnome-ssh-askpass.1
diff --git a/debian/ssh-askpass-gnome.png b/debian/ssh-askpass-gnome.png
new file mode 100644 (file)
index 0000000..06f7576
Binary files /dev/null and b/debian/ssh-askpass-gnome.png differ
diff --git a/debian/ssh-askpass-gnome.postinst b/debian/ssh-askpass-gnome.postinst
new file mode 100644 (file)
index 0000000..b6c56d4
--- /dev/null
@@ -0,0 +1,65 @@
+#! /bin/sh
+# postinst script for ssh-askpass-gnome
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see /usr/share/doc/packaging-manual/
+#
+# quoting from the policy:
+#     Any necessary prompting should almost always be confined to the
+#     post-installation script, and should be protected with a conditional
+#     so that unnecessary prompting doesn't happen if a package's
+#     installation fails and the `postinst' is called with `abort-upgrade',
+#     `abort-remove' or `abort-deconfigure'.
+
+case "$1" in
+    configure)
+        if dpkg --compare-versions "$2" lt-nl 1:4.1p1-1; then
+            # libexecdir changed, so remove the obsolete alternative.
+            update-alternatives --quiet --remove ssh-askpass \
+                /usr/lib/ssh/gnome-ssh-askpass
+        fi
+       if dpkg --compare-versions "$2" lt-nl 1:4.1p1-7 && \
+               [ -h /etc/alternatives/ssh-askpass ] && \
+               [ "$(readlink /etc/alternatives/ssh-askpass)" = /usr/lib/ssh/gnome-ssh-askpass ]; then
+           # Work around the ssh-askpass alternative somehow ending up in
+           # manual mode.
+           update-alternatives --auto ssh-askpass
+       fi
+        update-alternatives --quiet \
+           --install /usr/bin/ssh-askpass ssh-askpass \
+                     /usr/lib/openssh/gnome-ssh-askpass 30 \
+           --slave /usr/share/man/man1/ssh-askpass.1.gz \
+                   ssh-askpass.1.gz /usr/share/man/man1/gnome-ssh-askpass.1.gz
+
+
+    ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 0
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/ssh-askpass-gnome.prerm b/debian/ssh-askpass-gnome.prerm
new file mode 100644 (file)
index 0000000..e85f2d4
--- /dev/null
@@ -0,0 +1,41 @@
+#! /bin/sh
+# prerm script for ssh-askpass-gnome
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <prerm> `remove'
+#        * <old-prerm> `upgrade' <new-version>
+#        * <new-prerm> `failed-upgrade' <old-version>
+#        * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+#        * <deconfigured's-prerm> `deconfigure' `in-favour'
+#          <package-being-installed> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see /usr/share/doc/packaging-manual/
+
+case "$1" in
+    remove|deconfigure)
+       update-alternatives --quiet --remove ssh-askpass /usr/lib/openssh/gnome-ssh-askpass
+#       install-info --quiet --remove /usr/info/ssh-askpass.info.gz
+       ;;
+    upgrade)
+#       install-info --quiet --remove /usr/info/ssh-askpass.info.gz
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 0
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/ssh-krb5.NEWS b/debian/ssh-krb5.NEWS
new file mode 100644 (file)
index 0000000..5a6433a
--- /dev/null
@@ -0,0 +1,18 @@
+ssh-krb5 (1:4.3p2-7) unstable; urgency=low
+
+  The normal openssh-server and openssh-client packages in Debian now
+  include full GSSAPI support, including key exchange.  This package is
+  now only a transitional package that depends on openssh-server and
+  openssh-client and configures openssh-server for GSSAPI authentication
+  if it wasn't already.
+
+  You can now simply install openssh-server and openssh-client directly
+  and remove this package.  Just make sure that /etc/ssh/sshd_config
+  contains:
+
+    GSSAPIAuthentication yes
+    GSSAPIKeyExchange yes
+
+  if you want to support GSSAPI authentication to your ssh server.
+
+ -- Russ Allbery <rra@debian.org>  Tue, 03 Oct 2006 22:27:27 -0700
diff --git a/debian/ssh-krb5.postinst b/debian/ssh-krb5.postinst
new file mode 100644 (file)
index 0000000..4d943d8
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+set -e
+
+action="$1"
+oldversion="$2"
+
+if [ "$action" = configure ] ; then
+    if dpkg --compare-versions "$oldversion" lt-nl 1:4.3p2-7; then
+        # Replaced by /etc/init.d/ssh.
+        if [ -f /etc/init.d/ssh-krb5 ]; then
+            mv /etc/init.d/ssh-krb5 /etc/init.d/ssh-krb5.dpkg-old
+            update-rc.d ssh-krb5 remove || true
+        fi
+    fi
+
+    # Make sure that GSSAPI is enabled.  If there is no uncommented GSSAPI
+    # configuration, uncomment any commented-out configuration if present
+    # (this will catch the case of a fresh install of openssh-server).
+    # Otherwise, add configuration turning on GSSAPIAuthentication and
+    # GSSAPIKeyExchange.
+    #
+    # If there is some configuration, we may be upgrading from ssh-krb5.  It
+    # enabled GSSAPIKeyExchange without any configuration option.  Therefore,
+    # if it isn't explicitly set, always enable it for compatible behavior
+    # with ssh-krb5.
+    if dpkg --compare-versions "$oldversion" ge 1:4.3p2-9; then
+        :
+    else
+        changed=
+        if grep -qi '^[        ]*GSSAPI' /etc/ssh/sshd_config ; then
+            if grep -qi '^[    ]*GSSAPIKeyExchange' /etc/ssh/sshd_config ; then
+                :
+            else
+                changed=true
+                cat >> /etc/ssh/sshd_config <<EOF
+
+# GSSAPI key exchange (added by ssh-krb5 transitional package)
+GSSAPIKeyExchange yes
+EOF
+            fi
+        else
+            changed=true
+            if grep -qi '^#GSSAPI' /etc/ssh/sshd_config ; then
+                perl -pe 's/^\#(GSSAPI(Authentication|KeyExchange))\b.*/$1 yes/i' \
+                    < /etc/ssh/sshd_config > /etc/ssh/sshd_config.dpkg-new
+                chown --reference /etc/ssh/sshd_config \
+                    /etc/ssh/sshd_config.dpkg-new
+                chmod --reference /etc/ssh/sshd_config \
+                    /etc/ssh/sshd_config.dpkg-new
+                mv /etc/ssh/sshd_config.dpkg-new /etc/ssh/sshd_config
+            else
+                cat >> /etc/ssh/sshd_config <<EOF
+
+# GSSAPI authentication (added by ssh-krb5 transitional package)
+GSSAPIAuthentication yes
+GSSAPIKeyExchange yes
+EOF
+            fi
+        fi
+        if [ -n "$changed" ] && [ -x /etc/init.d/ssh ] ; then
+            if [ -x /usr/sbin/invoke-rc.d ] ; then
+                invoke-rc.d ssh restart
+            else
+                /etc/init.d/ssh restart
+            fi
+        fi
+    fi
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/ssh.dirs b/debian/ssh.dirs
new file mode 100644 (file)
index 0000000..1da8fba
--- /dev/null
@@ -0,0 +1 @@
+usr/share/lintian/overrides
diff --git a/debian/ssh.lintian-overrides b/debian/ssh.lintian-overrides
new file mode 100644 (file)
index 0000000..b9bf7ea
--- /dev/null
@@ -0,0 +1 @@
+ssh: package-contains-empty-directory usr/share/doc/openssh-client/
diff --git a/debian/ssh.postinst b/debian/ssh.postinst
new file mode 100644 (file)
index 0000000..cb12780
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh -e
+
+action="$1"
+oldversion="$2"
+
+if [ "$action" != configure ]; then
+       exit 0
+fi
+
+if [ ! -L /usr/share/doc/ssh ] && \
+   dpkg --compare-versions "$oldversion" lt-nl 1:4.1p1-5; then
+       rm -rf /usr/share/doc/ssh
+       ln -s openssh-client /usr/share/doc/ssh
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/ssh.prerm b/debian/ssh.prerm
new file mode 100644 (file)
index 0000000..400c92b
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh -e
+
+case $1 in
+       upgrade)
+               if [ -L /usr/share/doc/ssh ] && \
+                  dpkg --compare-versions "$2" lt-nl 1:4.1p1-5; then
+                       rm -f /usr/share/doc/ssh
+               fi
+               ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/substitute-conffile.pl b/debian/substitute-conffile.pl
new file mode 100644 (file)
index 0000000..7dd2336
--- /dev/null
@@ -0,0 +1,26 @@
+#! /usr/bin/perl -p
+
+# This is needed for a nasty preinst hack to work around a bug in sarge's
+# version of dpkg. It substitutes the literal text of conffiles into preinst
+# scripts so that they can be used when moving conffiles between packages.
+
+BEGIN {
+    %texts = ();
+    while (@ARGV > 1) {
+       my $name = $ARGV[0];
+       shift;
+       local *FILE;
+       open FILE, '<', $ARGV[0];
+       local $/ = undef;
+       my $text = <FILE>;
+       close FILE;
+       # Quote for the shell.
+       $text =~ s/'/'\\''/g;
+       shift;
+       $texts{$name} = $text;
+    }
+}
+
+for my $name (keys %texts) {
+    s/\@$name\@/'$texts{$name}'/g;
+}
diff --git a/debian/tests/Makefile b/debian/tests/Makefile
new file mode 100644 (file)
index 0000000..666ed82
--- /dev/null
@@ -0,0 +1,12 @@
+test: getpid.so
+       chmod +x keygen-test
+       ./keygen-test
+
+getpid.o: getpid.c
+       gcc -fPIC -c $< -o $@
+
+getpid.so: getpid.o
+       gcc -shared -o $@ $<
+
+clean:
+       rm -f getpid.o getpid.so key1 key1.pub key2 key2.pub
diff --git a/debian/tests/getpid.c b/debian/tests/getpid.c
new file mode 100644 (file)
index 0000000..c9e35b8
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Compile:
+
+gcc -fPIC -c getpid.c -o getpid.o
+gcc -shared -o getpid.so getpid.o
+
+ * Use:
+FORCE_PID=1234 LD_PRELOAD=./getpid.so bash
+
+#
+# Copyright (C) 2001-2008 Kees Cook
+# kees@outflux.net, http://outflux.net/
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+pid_t getpid(void)
+{
+    return atoi(getenv("FORCE_PID"));
+}
diff --git a/debian/tests/keygen-test b/debian/tests/keygen-test
new file mode 100755 (executable)
index 0000000..02b7c76
--- /dev/null
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+rm -f key1 key1.pub key2 key2.pub
+LD_PRELOAD="$(pwd)/getpid.so" FORCE_PID=1234 \
+       ../../build-deb/ssh-keygen -N '' -f key1 >/dev/null
+LD_PRELOAD="$(pwd)/getpid.so" FORCE_PID=1234 \
+       ../../build-deb/ssh-keygen -N '' -f key2 >/dev/null
+if cmp -s key1 key2; then
+       echo "Generated two identical keys!" >&2
+       exit 1
+fi
+exit 0
diff --git a/debian/watch b/debian/watch
new file mode 100644 (file)
index 0000000..6ffdc37
--- /dev/null
@@ -0,0 +1,3 @@
+version=2
+ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-(.*)\.tar\.gz \
+  debian uupdate
diff --git a/dns.c b/dns.c
index 131cb3d..dfa4c1e 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -177,6 +177,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
 {
        u_int counter;
        int result;
+       unsigned int rrset_flags = 0;
        struct rrsetinfo *fingerprints = NULL;
 
        u_int8_t hostkey_algorithm;
@@ -200,8 +201,19 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
                return -1;
        }
 
+       /*
+        * Original getrrsetbyname function, found on OpenBSD for example,
+        * doesn't accept any flag and prerequisite for obtaining AD bit in
+        * DNS response is set by "options edns0" in resolv.conf.
+        *
+        * Our version is more clever and use RRSET_FORCE_EDNS0 flag.
+        */
+#ifndef HAVE_GETRRSETBYNAME
+       rrset_flags |= RRSET_FORCE_EDNS0;
+#endif
        result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
-           DNS_RDATATYPE_SSHFP, 0, &fingerprints);
+           DNS_RDATATYPE_SSHFP, rrset_flags, &fingerprints);
+
        if (result) {
                verbose("DNS lookup error: %s", dns_result_totext(result));
                return -1;
index 842f385..f9b39cf 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */
 
 /*
- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "buffer.h"
 #include "log.h"
 #include "ssh2.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include <openssl/evp.h>
 
 #include "ssh-gss.h"
 
 extern u_char *session_id2;
 extern u_int session_id2_len;
 
+typedef struct {
+       char *encoded;
+       gss_OID oid;
+} ssh_gss_kex_mapping;
+
+/*
+ * XXX - It would be nice to find a more elegant way of handling the
+ * XXX   passing of the key exchange context to the userauth routines
+ */
+
+Gssctxt *gss_kex_context = NULL;
+
+static ssh_gss_kex_mapping *gss_enc2oid = NULL;
+
+int 
+ssh_gssapi_oid_table_ok() {
+       return (gss_enc2oid != NULL);
+}
+
+/*
+ * Return a list of the gss-group1-sha1 mechanisms supported by this program
+ *
+ * We test mechanisms to ensure that we can use them, to avoid starting
+ * a key exchange with a bad mechanism
+ */
+
+char *
+ssh_gssapi_client_mechanisms(const char *host, const char *client) {
+       gss_OID_set gss_supported;
+       OM_uint32 min_status;
+
+       if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
+               return NULL;
+
+       return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
+           host, client));
+}
+
+char *
+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
+    const char *host, const char *client) {
+       Buffer buf;
+       size_t i;
+       int oidpos, enclen;
+       char *mechs, *encoded;
+       u_char digest[EVP_MAX_MD_SIZE];
+       char deroid[2];
+       const EVP_MD *evp_md = EVP_md5();
+       EVP_MD_CTX md;
+
+       if (gss_enc2oid != NULL) {
+               for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
+                       xfree(gss_enc2oid[i].encoded);
+               xfree(gss_enc2oid);
+       }
+
+       gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
+           (gss_supported->count + 1));
+
+       buffer_init(&buf);
+
+       oidpos = 0;
+       for (i = 0; i < gss_supported->count; i++) {
+               if (gss_supported->elements[i].length < 128 &&
+                   (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
+
+                       deroid[0] = SSH_GSS_OIDTYPE;
+                       deroid[1] = gss_supported->elements[i].length;
+
+                       EVP_DigestInit(&md, evp_md);
+                       EVP_DigestUpdate(&md, deroid, 2);
+                       EVP_DigestUpdate(&md,
+                           gss_supported->elements[i].elements,
+                           gss_supported->elements[i].length);
+                       EVP_DigestFinal(&md, digest, NULL);
+
+                       encoded = xmalloc(EVP_MD_size(evp_md) * 2);
+                       enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
+                           encoded, EVP_MD_size(evp_md) * 2);
+
+                       if (oidpos != 0)
+                               buffer_put_char(&buf, ',');
+
+                       buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
+                           sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
+                       buffer_append(&buf, encoded, enclen);
+                       buffer_put_char(&buf, ',');
+                       buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
+                           sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
+                       buffer_append(&buf, encoded, enclen);
+                       buffer_put_char(&buf, ',');
+                       buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
+                           sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
+                       buffer_append(&buf, encoded, enclen);
+
+                       gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
+                       gss_enc2oid[oidpos].encoded = encoded;
+                       oidpos++;
+               }
+       }
+       gss_enc2oid[oidpos].oid = NULL;
+       gss_enc2oid[oidpos].encoded = NULL;
+
+       buffer_put_char(&buf, '\0');
+
+       mechs = xmalloc(buffer_len(&buf));
+       buffer_get(&buf, mechs, buffer_len(&buf));
+       buffer_free(&buf);
+
+       if (strlen(mechs) == 0) {
+               xfree(mechs);
+               mechs = NULL;
+       }
+       
+       return (mechs);
+}
+
+gss_OID
+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
+       int i = 0;
+       
+       switch (kex_type) {
+       case KEX_GSS_GRP1_SHA1:
+               if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
+                       return GSS_C_NO_OID;
+               name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
+               break;
+       case KEX_GSS_GRP14_SHA1:
+               if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
+                       return GSS_C_NO_OID;
+               name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
+               break;
+       case KEX_GSS_GEX_SHA1:
+               if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
+                       return GSS_C_NO_OID;
+               name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
+               break;
+       default:
+               return GSS_C_NO_OID;
+       }
+
+       while (gss_enc2oid[i].encoded != NULL &&
+           strcmp(name, gss_enc2oid[i].encoded) != 0)
+               i++;
+
+       if (gss_enc2oid[i].oid != NULL && ctx != NULL)
+               ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
+
+       return gss_enc2oid[i].oid;
+}
+
 /* Check that the OID in a data stream matches that in the context */
 int
 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
@@ -197,7 +352,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
        }
 
        ctx->major = gss_init_sec_context(&ctx->minor,
-           GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
+           ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
            GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
            0, NULL, recv_tok, NULL, send_tok, flags, NULL);
 
@@ -227,8 +382,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
 }
 
 OM_uint32
+ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
+{
+       gss_buffer_desc gssbuf;
+       gss_name_t gssname;
+       OM_uint32 status;
+       gss_OID_set oidset;
+
+       gssbuf.value = (void *) name;
+       gssbuf.length = strlen(gssbuf.value);
+
+       gss_create_empty_oid_set(&status, &oidset);
+       gss_add_oid_set_member(&status, ctx->oid, &oidset);
+
+       ctx->major = gss_import_name(&ctx->minor, &gssbuf,
+           GSS_C_NT_USER_NAME, &gssname);
+
+       if (!ctx->major)
+               ctx->major = gss_acquire_cred(&ctx->minor, 
+                   gssname, 0, oidset, GSS_C_INITIATE, 
+                   &ctx->client_creds, NULL, NULL);
+
+       gss_release_name(&status, &gssname);
+       gss_release_oid_set(&status, &oidset);
+
+       if (ctx->major)
+               ssh_gssapi_error(ctx);
+
+       return(ctx->major);
+}
+
+OM_uint32
 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
 {
+       if (ctx == NULL) 
+               return -1;
+
        if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
            GSS_C_QOP_DEFAULT, buffer, hash)))
                ssh_gssapi_error(ctx);
@@ -236,6 +425,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
        return (ctx->major);
 }
 
+/* Priviledged when used by server */
+OM_uint32
+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+       if (ctx == NULL)
+               return -1;
+
+       ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+           gssbuf, gssmic, NULL);
+
+       return (ctx->major);
+}
+
 void
 ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
     const char *context)
@@ -249,11 +451,16 @@ ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
 }
 
 int
-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 
+    const char *client)
 {
        gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
        OM_uint32 major, minor;
        gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
+       Gssctxt *intctx = NULL;
+
+       if (ctx == NULL)
+               ctx = &intctx;
 
        /* RFC 4462 says we MUST NOT do SPNEGO */
        if (oid->length == spnego_oid.length && 
@@ -263,6 +470,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
        ssh_gssapi_build_ctx(ctx);
        ssh_gssapi_set_oid(*ctx, oid);
        major = ssh_gssapi_import_name(*ctx, host);
+
+       if (!GSS_ERROR(major) && client)
+               major = ssh_gssapi_client_identity(*ctx, client);
+
        if (!GSS_ERROR(major)) {
                major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
                    NULL);
@@ -272,10 +483,67 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
                            GSS_C_NO_BUFFER);
        }
 
-       if (GSS_ERROR(major)) 
+       if (GSS_ERROR(major) || intctx != NULL
                ssh_gssapi_delete_ctx(ctx);
 
        return (!GSS_ERROR(major));
 }
 
+int
+ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
+       static gss_name_t saved_name = GSS_C_NO_NAME;
+       static OM_uint32 saved_lifetime = 0;
+       static gss_OID saved_mech = GSS_C_NO_OID;
+       static gss_name_t name;
+       static OM_uint32 last_call = 0;
+       OM_uint32 lifetime, now, major, minor;
+       int equal;
+       gss_cred_usage_t usage = GSS_C_INITIATE;
+       
+       now = time(NULL);
+
+       if (ctxt) {
+               debug("Rekey has happened - updating saved versions");
+
+               if (saved_name != GSS_C_NO_NAME)
+                       gss_release_name(&minor, &saved_name);
+
+               major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
+                   &saved_name, &saved_lifetime, NULL, NULL);
+
+               if (!GSS_ERROR(major)) {
+                       saved_mech = ctxt->oid;
+                       saved_lifetime+= now;
+               } else {
+                       /* Handle the error */
+               }
+               return 0;
+       }
+
+       if (now - last_call < 10)
+               return 0;
+
+       last_call = now;
+
+       if (saved_mech == GSS_C_NO_OID)
+               return 0;
+       
+       major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 
+           &name, &lifetime, NULL, NULL);
+       if (major == GSS_S_CREDENTIALS_EXPIRED)
+               return 0;
+       else if (GSS_ERROR(major))
+               return 0;
+
+       major = gss_compare_name(&minor, saved_name, name, &equal);
+       gss_release_name(&minor, &name);
+       if (GSS_ERROR(major))
+               return 0;
+
+       if (equal && (saved_lifetime < lifetime + now - 10))
+               return 1;
+
+       return 0;
+}
+
 #endif /* GSSAPI */
index 5a625ac..e7170ee 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -120,6 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
        krb5_principal princ;
        OM_uint32 maj_status, min_status;
        int len;
+       const char *new_ccname;
 
        if (client->creds == NULL) {
                debug("No credentials stored");
@@ -168,11 +169,16 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
                return;
        }
 
-       client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
+       new_ccname = krb5_cc_get_name(krb_context, ccache);
+
        client->store.envvar = "KRB5CCNAME";
-       len = strlen(client->store.filename) + 6;
-       client->store.envval = xmalloc(len);
-       snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
+#ifdef USE_CCAPI
+       xasprintf(&client->store.envval, "API:%s", new_ccname);
+       client->store.filename = NULL;
+#else
+       xasprintf(&client->store.envval, "FILE:%s", new_ccname);
+       client->store.filename = xstrdup(new_ccname);
+#endif
 
 #ifdef USE_PAM
        if (options.use_pam)
@@ -184,6 +190,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
        return;
 }
 
+int
+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 
+    ssh_gssapi_client *client)
+{
+       krb5_ccache ccache = NULL;
+       krb5_principal principal = NULL;
+       char *name = NULL;
+       krb5_error_code problem;
+       OM_uint32 maj_status, min_status;
+
+       if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
+                logit("krb5_cc_resolve(): %.100s",
+                    krb5_get_err_text(krb_context, problem));
+                return 0;
+               }
+       
+       /* Find out who the principal in this cache is */
+       if ((problem = krb5_cc_get_principal(krb_context, ccache, 
+           &principal))) {
+               logit("krb5_cc_get_principal(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+       if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
+               logit("krb5_unparse_name(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_free_principal(krb_context, principal);
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+
+       if (strcmp(name,client->exportedname.value)!=0) {
+               debug("Name in local credentials cache differs. Not storing");
+               krb5_free_principal(krb_context, principal);
+               krb5_cc_close(krb_context, ccache);
+               krb5_free_unparsed_name(krb_context, name);
+               return 0;
+       }
+       krb5_free_unparsed_name(krb_context, name);
+
+       /* Name matches, so lets get on with it! */
+
+       if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
+               logit("krb5_cc_initialize(): %.100s",
+                   krb5_get_err_text(krb_context, problem));
+               krb5_free_principal(krb_context, principal);
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+       krb5_free_principal(krb_context, principal);
+
+       if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
+           ccache))) {
+               logit("gss_krb5_copy_ccache() failed. Sorry!");
+               krb5_cc_close(krb_context, ccache);
+               return 0;
+       }
+
+       return 1;
+}
+
 ssh_gssapi_mech gssapi_kerberos_mech = {
        "toWM5Slw5Ew8Mqkay+al2g==",
        "Kerberos",
@@ -191,7 +262,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
        NULL,
        &ssh_gssapi_krb5_userok,
        NULL,
-       &ssh_gssapi_krb5_storecreds
+       &ssh_gssapi_krb5_storecreds,
+       &ssh_gssapi_krb5_updatecreds
 };
 
 #endif /* KRB5 */
index c719c13..380895e 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-serv.c,v 1.23 2011/08/01 19:18:15 markus Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "channels.h"
 #include "session.h"
 #include "misc.h"
+#include "servconf.h"
+#include "uidswap.h"
 
 #include "ssh-gss.h"
+#include "monitor_wrap.h"
+
+extern ServerOptions options;
 
 static ssh_gssapi_client gssapi_client =
     { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
-    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
+    GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,  NULL, {NULL, NULL, NULL}, 0, 0};
 
 ssh_gssapi_mech gssapi_null_mech =
-    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
+    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
 
 #ifdef KRB5
 extern ssh_gssapi_mech gssapi_kerberos_mech;
@@ -81,25 +86,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx)
        char lname[MAXHOSTNAMELEN];
        gss_OID_set oidset;
 
-       gss_create_empty_oid_set(&status, &oidset);
-       gss_add_oid_set_member(&status, ctx->oid, &oidset);
+       if (options.gss_strict_acceptor) {
+               gss_create_empty_oid_set(&status, &oidset);
+               gss_add_oid_set_member(&status, ctx->oid, &oidset);
 
-       if (gethostname(lname, MAXHOSTNAMELEN)) {
-               gss_release_oid_set(&status, &oidset);
-               return (-1);
-       }
+               if (gethostname(lname, MAXHOSTNAMELEN)) {
+                       gss_release_oid_set(&status, &oidset);
+                       return (-1);
+               }
+
+               if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
+                       gss_release_oid_set(&status, &oidset);
+                       return (ctx->major);
+               }
+
+               if ((ctx->major = gss_acquire_cred(&ctx->minor,
+                   ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, 
+                   NULL, NULL)))
+                       ssh_gssapi_error(ctx);
 
-       if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
                gss_release_oid_set(&status, &oidset);
                return (ctx->major);
+       } else {
+               ctx->name = GSS_C_NO_NAME;
+               ctx->creds = GSS_C_NO_CREDENTIAL;
        }
-
-       if ((ctx->major = gss_acquire_cred(&ctx->minor,
-           ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL)))
-               ssh_gssapi_error(ctx);
-
-       gss_release_oid_set(&status, &oidset);
-       return (ctx->major);
+       return GSS_S_COMPLETE;
 }
 
 /* Privileged */
@@ -114,6 +126,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
 }
 
 /* Unprivileged */
+char *
+ssh_gssapi_server_mechanisms() {
+       gss_OID_set     supported;
+
+       ssh_gssapi_supported_oids(&supported);
+       return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
+           NULL, NULL));
+}
+
+/* Unprivileged */
+int
+ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
+    const char *dummy) {
+       Gssctxt *ctx = NULL;
+       int res;
+       res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
+       ssh_gssapi_delete_ctx(&ctx);
+
+       return (res);
+}
+
+/* Unprivileged */
 void
 ssh_gssapi_supported_oids(gss_OID_set *oidset)
 {
@@ -123,7 +158,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset)
        gss_OID_set supported;
 
        gss_create_empty_oid_set(&min_status, oidset);
-       gss_indicate_mechs(&min_status, &supported);
+
+       if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
+               return;
 
        while (supported_mechs[i]->name != NULL) {
                if (GSS_ERROR(gss_test_oid_set_member(&min_status,
@@ -249,8 +286,48 @@ OM_uint32
 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
 {
        int i = 0;
+       int equal = 0;
+       gss_name_t new_name = GSS_C_NO_NAME;
+       gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
+
+       if (options.gss_store_rekey && client->used && ctx->client_creds) {
+               if (client->mech->oid.length != ctx->oid->length ||
+                   (memcmp(client->mech->oid.elements,
+                    ctx->oid->elements, ctx->oid->length) !=0)) {
+                       debug("Rekeyed credentials have different mechanism");
+                       return GSS_S_COMPLETE;
+               }
+
+               if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 
+                   ctx->client_creds, ctx->oid, &new_name, 
+                   NULL, NULL, NULL))) {
+                       ssh_gssapi_error(ctx);
+                       return (ctx->major);
+               }
+
+               ctx->major = gss_compare_name(&ctx->minor, client->name, 
+                   new_name, &equal);
 
-       gss_buffer_desc ename;
+               if (GSS_ERROR(ctx->major)) {
+                       ssh_gssapi_error(ctx);
+                       return (ctx->major);
+               }
+               if (!equal) {
+                       debug("Rekeyed credentials have different name");
+                       return GSS_S_COMPLETE;
+               }
+
+               debug("Marking rekeyed credentials for export");
+
+               gss_release_name(&ctx->minor, &client->name);
+               gss_release_cred(&ctx->minor, &client->creds);
+               client->name = new_name;
+               client->creds = ctx->client_creds;
+               ctx->client_creds = GSS_C_NO_CREDENTIAL;
+               client->updated = 1;
+               return GSS_S_COMPLETE;
+       }
 
        client->mech = NULL;
 
@@ -265,6 +342,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
        if (client->mech == NULL)
                return GSS_S_FAILURE;
 
+       if (ctx->client_creds &&
+           (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
+            ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
+               ssh_gssapi_error(ctx);
+               return (ctx->major);
+       }
+
        if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
            &client->displayname, NULL))) {
                ssh_gssapi_error(ctx);
@@ -282,6 +366,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
                return (ctx->major);
        }
 
+       gss_release_buffer(&ctx->minor, &ename);
+
        /* We can't copy this structure, so we just move the pointer to it */
        client->creds = ctx->client_creds;
        ctx->client_creds = GSS_C_NO_CREDENTIAL;
@@ -329,7 +415,7 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep)
 
 /* Privileged */
 int
-ssh_gssapi_userok(char *user)
+ssh_gssapi_userok(char *user, struct passwd *pw)
 {
        OM_uint32 lmin;
 
@@ -339,9 +425,11 @@ ssh_gssapi_userok(char *user)
                return 0;
        }
        if (gssapi_client.mech && gssapi_client.mech->userok)
-               if ((*gssapi_client.mech->userok)(&gssapi_client, user))
+               if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
+                       gssapi_client.used = 1;
+                       gssapi_client.store.owner = pw;
                        return 1;
-               else {
+               else {
                        /* Destroy delegated credentials if userok fails */
                        gss_release_buffer(&lmin, &gssapi_client.displayname);
                        gss_release_buffer(&lmin, &gssapi_client.exportedname);
@@ -354,14 +442,90 @@ ssh_gssapi_userok(char *user)
        return (0);
 }
 
-/* Privileged */
-OM_uint32
-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+/* These bits are only used for rekeying. The unpriviledged child is running 
+ * as the user, the monitor is root.
+ *
+ * In the child, we want to :
+ *    *) Ask the monitor to store our credentials into the store we specify
+ *    *) If it succeeds, maybe do a PAM update
+ */
+
+/* Stuff for PAM */
+
+#ifdef USE_PAM
+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 
+    struct pam_response **resp, void *data)
 {
-       ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
-           gssbuf, gssmic, NULL);
+       return (PAM_CONV_ERR);
+}
+#endif
 
-       return (ctx->major);
+void
+ssh_gssapi_rekey_creds() {
+       int ok;
+       int ret;
+#ifdef USE_PAM
+       pam_handle_t *pamh = NULL;
+       struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
+       char *envstr;
+#endif
+
+       if (gssapi_client.store.filename == NULL && 
+           gssapi_client.store.envval == NULL &&
+           gssapi_client.store.envvar == NULL)
+               return;
+       ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
+
+       if (!ok)
+               return;
+
+       debug("Rekeyed credentials stored successfully");
+
+       /* Actually managing to play with the ssh pam stack from here will
+        * be next to impossible. In any case, we may want different options
+        * for rekeying. So, use our own :)
+        */
+#ifdef USE_PAM 
+       if (!use_privsep) {
+               debug("Not even going to try and do PAM with privsep disabled");
+               return;
+       }
+
+       ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
+           &pamconv, &pamh);
+       if (ret)
+               return;
+
+       xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 
+           gssapi_client.store.envval);
+
+       ret = pam_putenv(pamh, envstr);
+       if (!ret)
+               pam_setcred(pamh, PAM_REINITIALIZE_CRED);
+       pam_end(pamh, PAM_SUCCESS);
+#endif
+}
+
+int 
+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
+       int ok = 0;
+
+       /* Check we've got credentials to store */
+       if (!gssapi_client.updated)
+               return 0;
+
+       gssapi_client.updated = 0;
+
+       temporarily_use_uid(gssapi_client.store.owner);
+       if (gssapi_client.mech && gssapi_client.mech->updatecreds)
+               ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
+       else
+               debug("No update function for this mechanism");
+
+       restore_uid();
+
+       return ok;
 }
 
 #endif
diff --git a/kex.c b/kex.c
index c65e28f..58349fc 100644 (file)
--- a/kex.c
+++ b/kex.c
 #include "monitor.h"
 #include "roaming.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
 # if defined(HAVE_EVP_SHA256)
 # define evp_ssh_sha256 EVP_sha256
@@ -358,6 +362,20 @@ choose_kex(Kex *k, char *client, char *server)
                k->kex_type = KEX_ECDH_SHA2;
                k->evp_md = kex_ecdh_name_to_evpmd(k->name);
 #endif
+#ifdef GSSAPI
+       } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
+           sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
+               k->kex_type = KEX_GSS_GEX_SHA1;
+               k->evp_md = EVP_sha1();
+       } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
+           sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
+               k->kex_type = KEX_GSS_GRP1_SHA1;
+               k->evp_md = EVP_sha1();
+       } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
+           sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
+               k->kex_type = KEX_GSS_GRP14_SHA1;
+               k->evp_md = EVP_sha1();
+#endif
        } else
                fatal("bad kex alg %s", k->name);
 }
diff --git a/kex.h b/kex.h
index 7373d3c..fa50b2c 100644 (file)
--- a/kex.h
+++ b/kex.h
@@ -73,6 +73,9 @@ enum kex_exchange {
        KEX_DH_GEX_SHA1,
        KEX_DH_GEX_SHA256,
        KEX_ECDH_SHA2,
+       KEX_GSS_GRP1_SHA1,
+       KEX_GSS_GRP14_SHA1,
+       KEX_GSS_GEX_SHA1,
        KEX_MAX
 };
 
@@ -129,6 +132,12 @@ struct Kex {
        sig_atomic_t done;
        int     flags;
        const EVP_MD *evp_md;
+#ifdef GSSAPI
+       int     gss_deleg_creds;
+       int     gss_trust_dns;
+       char    *gss_host;
+       char    *gss_client;
+#endif
        char    *client_version_string;
        char    *server_version_string;
        int     (*verify_host_key)(Key *);
@@ -156,6 +165,11 @@ void        kexgex_server(Kex *);
 void    kexecdh_client(Kex *);
 void    kexecdh_server(Kex *);
 
+#ifdef GSSAPI
+void   kexgss_client(Kex *);
+void   kexgss_server(Kex *);
+#endif
+
 void
 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
     BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
diff --git a/kexgssc.c b/kexgssc.c
new file mode 100644 (file)
index 0000000..39be405
--- /dev/null
+++ b/kexgssc.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#ifdef GSSAPI
+
+#include "includes.h"
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+
+#include <string.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "ssh2.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "dh.h"
+
+#include "ssh-gss.h"
+
+void
+kexgss_client(Kex *kex) {
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
+       Gssctxt *ctxt;
+       OM_uint32 maj_status, min_status, ret_flags;
+       u_int klen, kout, slen = 0, hashlen, strlen;
+       DH *dh; 
+       BIGNUM *dh_server_pub = NULL;
+       BIGNUM *shared_secret = NULL;
+       BIGNUM *p = NULL;
+       BIGNUM *g = NULL;       
+       u_char *kbuf, *hash;
+       u_char *serverhostkey = NULL;
+       u_char *empty = "";
+       char *msg;
+       char *lang;
+       int type = 0;
+       int first = 1;
+       int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
+
+       /* Initialise our GSSAPI world */       
+       ssh_gssapi_build_ctx(&ctxt);
+       if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) 
+           == GSS_C_NO_OID)
+               fatal("Couldn't identify host exchange");
+
+       if (ssh_gssapi_import_name(ctxt, kex->gss_host))
+               fatal("Couldn't import hostname");
+
+       if (kex->gss_client && 
+           ssh_gssapi_client_identity(ctxt, kex->gss_client))
+               fatal("Couldn't acquire client credentials");
+
+       switch (kex->kex_type) {
+       case KEX_GSS_GRP1_SHA1:
+               dh = dh_new_group1();
+               break;
+       case KEX_GSS_GRP14_SHA1:
+               dh = dh_new_group14();
+               break;
+       case KEX_GSS_GEX_SHA1:
+               debug("Doing group exchange\n");
+               nbits = dh_estimate(kex->we_need * 8);
+               packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
+               packet_put_int(min);
+               packet_put_int(nbits);
+               packet_put_int(max);
+
+               packet_send();
+
+               packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
+
+               if ((p = BN_new()) == NULL)
+                       fatal("BN_new() failed");
+               packet_get_bignum2(p);
+               if ((g = BN_new()) == NULL)
+                       fatal("BN_new() failed");
+               packet_get_bignum2(g);
+               packet_check_eom();
+
+               if (BN_num_bits(p) < min || BN_num_bits(p) > max)
+                       fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
+                           min, BN_num_bits(p), max);
+
+               dh = dh_new_group(g, p);
+               break;
+       default:
+               fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+       }
+       
+       /* Step 1 - e is dh->pub_key */
+       dh_gen_key(dh, kex->we_need * 8);
+
+       /* This is f, we initialise it now to make life easier */
+       dh_server_pub = BN_new();
+       if (dh_server_pub == NULL)
+               fatal("dh_server_pub == NULL");
+
+       token_ptr = GSS_C_NO_BUFFER;
+                        
+       do {
+               debug("Calling gss_init_sec_context");
+               
+               maj_status = ssh_gssapi_init_ctx(ctxt,
+                   kex->gss_deleg_creds, token_ptr, &send_tok,
+                   &ret_flags);
+
+               if (GSS_ERROR(maj_status)) {
+                       if (send_tok.length != 0) {
+                               packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                               packet_put_string(send_tok.value,
+                                   send_tok.length);
+                       }
+                       fatal("gss_init_context failed");
+               }
+
+               /* If we've got an old receive buffer get rid of it */
+               if (token_ptr != GSS_C_NO_BUFFER)
+                       xfree(recv_tok.value);
+
+               if (maj_status == GSS_S_COMPLETE) {
+                       /* If mutual state flag is not true, kex fails */
+                       if (!(ret_flags & GSS_C_MUTUAL_FLAG))
+                               fatal("Mutual authentication failed");
+
+                       /* If integ avail flag is not true kex fails */
+                       if (!(ret_flags & GSS_C_INTEG_FLAG))
+                               fatal("Integrity check failed");
+               }
+
+               /* 
+                * If we have data to send, then the last message that we
+                * received cannot have been a 'complete'. 
+                */
+               if (send_tok.length != 0) {
+                       if (first) {
+                               packet_start(SSH2_MSG_KEXGSS_INIT);
+                               packet_put_string(send_tok.value,
+                                   send_tok.length);
+                               packet_put_bignum2(dh->pub_key);
+                               first = 0;
+                       } else {
+                               packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                               packet_put_string(send_tok.value,
+                                   send_tok.length);
+                       }
+                       packet_send();
+                       gss_release_buffer(&min_status, &send_tok);
+
+                       /* If we've sent them data, they should reply */
+                       do {    
+                               type = packet_read();
+                               if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
+                                       debug("Received KEXGSS_HOSTKEY");
+                                       if (serverhostkey)
+                                               fatal("Server host key received more than once");
+                                       serverhostkey = 
+                                           packet_get_string(&slen);
+                               }
+                       } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
+
+                       switch (type) {
+                       case SSH2_MSG_KEXGSS_CONTINUE:
+                               debug("Received GSSAPI_CONTINUE");
+                               if (maj_status == GSS_S_COMPLETE) 
+                                       fatal("GSSAPI Continue received from server when complete");
+                               recv_tok.value = packet_get_string(&strlen);
+                               recv_tok.length = strlen; 
+                               break;
+                       case SSH2_MSG_KEXGSS_COMPLETE:
+                               debug("Received GSSAPI_COMPLETE");
+                               packet_get_bignum2(dh_server_pub);
+                               msg_tok.value =  packet_get_string(&strlen);
+                               msg_tok.length = strlen; 
+
+                               /* Is there a token included? */
+                               if (packet_get_char()) {
+                                       recv_tok.value=
+                                           packet_get_string(&strlen);
+                                       recv_tok.length = strlen;
+                                       /* If we're already complete - protocol error */
+                                       if (maj_status == GSS_S_COMPLETE)
+                                               packet_disconnect("Protocol error: received token when complete");
+                                       } else {
+                                               /* No token included */
+                                               if (maj_status != GSS_S_COMPLETE)
+                                                       packet_disconnect("Protocol error: did not receive final token");
+                               }
+                               break;
+                       case SSH2_MSG_KEXGSS_ERROR:
+                               debug("Received Error");
+                               maj_status = packet_get_int();
+                               min_status = packet_get_int();
+                               msg = packet_get_string(NULL);
+                               lang = packet_get_string(NULL);
+                               fatal("GSSAPI Error: \n%.400s",msg);
+                       default:
+                               packet_disconnect("Protocol error: didn't expect packet type %d",
+                               type);
+                       }
+                       token_ptr = &recv_tok;
+               } else {
+                       /* No data, and not complete */
+                       if (maj_status != GSS_S_COMPLETE)
+                               fatal("Not complete, and no token output");
+               }
+       } while (maj_status & GSS_S_CONTINUE_NEEDED);
+
+       /* 
+        * We _must_ have received a COMPLETE message in reply from the 
+        * server, which will have set dh_server_pub and msg_tok 
+        */
+
+       if (type != SSH2_MSG_KEXGSS_COMPLETE)
+               fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
+
+       /* Check f in range [1, p-1] */
+       if (!dh_pub_is_valid(dh, dh_server_pub))
+               packet_disconnect("bad server public DH value");
+
+       /* compute K=f^x mod p */
+       klen = DH_size(dh);
+       kbuf = xmalloc(klen);
+       kout = DH_compute_key(kbuf, dh_server_pub, dh);
+       if (kout < 0)
+               fatal("DH_compute_key: failed");
+
+       shared_secret = BN_new();
+       if (shared_secret == NULL)
+               fatal("kexgss_client: BN_new failed");
+
+       if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
+               fatal("kexdh_client: BN_bin2bn failed");
+
+       memset(kbuf, 0, klen);
+       xfree(kbuf);
+
+       switch (kex->kex_type) {
+       case KEX_GSS_GRP1_SHA1:
+       case KEX_GSS_GRP14_SHA1:
+               kex_dh_hash( kex->client_version_string, 
+                   kex->server_version_string,
+                   buffer_ptr(&kex->my), buffer_len(&kex->my),
+                   buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+                   (serverhostkey ? serverhostkey : empty), slen,
+                   dh->pub_key,        /* e */
+                   dh_server_pub,      /* f */
+                   shared_secret,      /* K */
+                   &hash, &hashlen
+               );
+               break;
+       case KEX_GSS_GEX_SHA1:
+               kexgex_hash(
+                   kex->evp_md,
+                   kex->client_version_string,
+                   kex->server_version_string,
+                   buffer_ptr(&kex->my), buffer_len(&kex->my),
+                   buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+                   (serverhostkey ? serverhostkey : empty), slen,
+                   min, nbits, max,
+                   dh->p, dh->g,
+                   dh->pub_key,
+                   dh_server_pub,
+                   shared_secret,
+                   &hash, &hashlen
+               );
+               break;
+       default:
+               fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+       }
+
+       gssbuf.value = hash;
+       gssbuf.length = hashlen;
+
+       /* Verify that the hash matches the MIC we just got. */
+       if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
+               packet_disconnect("Hash's MIC didn't verify");
+
+       xfree(msg_tok.value);
+
+       DH_free(dh);
+       if (serverhostkey)
+               xfree(serverhostkey);
+       BN_clear_free(dh_server_pub);
+
+       /* save session id */
+       if (kex->session_id == NULL) {
+               kex->session_id_len = hashlen;
+               kex->session_id = xmalloc(kex->session_id_len);
+               memcpy(kex->session_id, hash, kex->session_id_len);
+       }
+
+       if (kex->gss_deleg_creds)
+               ssh_gssapi_credentials_updated(ctxt);
+
+       if (gss_kex_context == NULL)
+               gss_kex_context = ctxt;
+       else
+               ssh_gssapi_delete_ctx(&ctxt);
+
+       kex_derive_keys(kex, hash, hashlen, shared_secret);
+       BN_clear_free(shared_secret);
+       kex_finish(kex);
+}
+
+#endif /* GSSAPI */
diff --git a/kexgsss.c b/kexgsss.c
new file mode 100644 (file)
index 0000000..0c3eeaa
--- /dev/null
+++ b/kexgsss.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#ifdef GSSAPI
+
+#include <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "ssh2.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "dh.h"
+#include "ssh-gss.h"
+#include "monitor_wrap.h"
+#include "servconf.h"
+
+extern ServerOptions options;
+
+void
+kexgss_server(Kex *kex)
+{
+       OM_uint32 maj_status, min_status;
+       
+       /* 
+        * Some GSSAPI implementations use the input value of ret_flags (an
+        * output variable) as a means of triggering mechanism specific 
+        * features. Initializing it to zero avoids inadvertently 
+        * activating this non-standard behaviour.
+        */
+
+       OM_uint32 ret_flags = 0;
+       gss_buffer_desc gssbuf, recv_tok, msg_tok;
+       gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+       Gssctxt *ctxt = NULL;
+       u_int slen, klen, kout, hashlen;
+       u_char *kbuf, *hash;
+       DH *dh;
+       int min = -1, max = -1, nbits = -1;
+       BIGNUM *shared_secret = NULL;
+       BIGNUM *dh_client_pub = NULL;
+       int type = 0;
+       gss_OID oid;
+       char *mechs;
+
+       /* Initialise GSSAPI */
+
+       /* If we're rekeying, privsep means that some of the private structures
+        * in the GSSAPI code are no longer available. This kludges them back
+        * into life
+        */
+       if (!ssh_gssapi_oid_table_ok()) 
+               if ((mechs = ssh_gssapi_server_mechanisms()))
+                       xfree(mechs);
+
+       debug2("%s: Identifying %s", __func__, kex->name);
+       oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
+       if (oid == GSS_C_NO_OID)
+          fatal("Unknown gssapi mechanism");
+
+       debug2("%s: Acquiring credentials", __func__);
+
+       if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
+               fatal("Unable to acquire credentials for the server");
+
+       switch (kex->kex_type) {
+       case KEX_GSS_GRP1_SHA1:
+               dh = dh_new_group1();
+               break;
+       case KEX_GSS_GRP14_SHA1:
+               dh = dh_new_group14();
+               break;
+       case KEX_GSS_GEX_SHA1:
+               debug("Doing group exchange");
+               packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
+               min = packet_get_int();
+               nbits = packet_get_int();
+               max = packet_get_int();
+               min = MAX(DH_GRP_MIN, min);
+               max = MIN(DH_GRP_MAX, max);
+               packet_check_eom();
+               if (max < min || nbits < min || max < nbits)
+                       fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
+                           min, nbits, max);
+               dh = PRIVSEP(choose_dh(min, nbits, max));
+               if (dh == NULL)
+                       packet_disconnect("Protocol error: no matching group found");
+
+               packet_start(SSH2_MSG_KEXGSS_GROUP);
+               packet_put_bignum2(dh->p);
+               packet_put_bignum2(dh->g);
+               packet_send();
+
+               packet_write_wait();
+               break;
+       default:
+               fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+       }
+
+       dh_gen_key(dh, kex->we_need * 8);
+
+       do {
+               debug("Wait SSH2_MSG_GSSAPI_INIT");
+               type = packet_read();
+               switch(type) {
+               case SSH2_MSG_KEXGSS_INIT:
+                       if (dh_client_pub != NULL) 
+                               fatal("Received KEXGSS_INIT after initialising");
+                       recv_tok.value = packet_get_string(&slen);
+                       recv_tok.length = slen; 
+
+                       if ((dh_client_pub = BN_new()) == NULL)
+                               fatal("dh_client_pub == NULL");
+
+                       packet_get_bignum2(dh_client_pub);
+
+                       /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
+                       break;
+               case SSH2_MSG_KEXGSS_CONTINUE:
+                       recv_tok.value = packet_get_string(&slen);
+                       recv_tok.length = slen; 
+                       break;
+               default:
+                       packet_disconnect(
+                           "Protocol error: didn't expect packet type %d",
+                           type);
+               }
+
+               maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
+                   &send_tok, &ret_flags));
+
+               xfree(recv_tok.value);
+
+               if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
+                       fatal("Zero length token output when incomplete");
+
+               if (dh_client_pub == NULL)
+                       fatal("No client public key");
+               
+               if (maj_status & GSS_S_CONTINUE_NEEDED) {
+                       debug("Sending GSSAPI_CONTINUE");
+                       packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                       packet_put_string(send_tok.value, send_tok.length);
+                       packet_send();
+                       gss_release_buffer(&min_status, &send_tok);
+               }
+       } while (maj_status & GSS_S_CONTINUE_NEEDED);
+
+       if (GSS_ERROR(maj_status)) {
+               if (send_tok.length > 0) {
+                       packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                       packet_put_string(send_tok.value, send_tok.length);
+                       packet_send();
+               }
+               fatal("accept_ctx died");
+       }
+
+       if (!(ret_flags & GSS_C_MUTUAL_FLAG))
+               fatal("Mutual Authentication flag wasn't set");
+
+       if (!(ret_flags & GSS_C_INTEG_FLAG))
+               fatal("Integrity flag wasn't set");
+       
+       if (!dh_pub_is_valid(dh, dh_client_pub))
+               packet_disconnect("bad client public DH value");
+
+       klen = DH_size(dh);
+       kbuf = xmalloc(klen); 
+       kout = DH_compute_key(kbuf, dh_client_pub, dh);
+       if (kout < 0)
+               fatal("DH_compute_key: failed");
+
+       shared_secret = BN_new();
+       if (shared_secret == NULL)
+               fatal("kexgss_server: BN_new failed");
+
+       if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
+               fatal("kexgss_server: BN_bin2bn failed");
+
+       memset(kbuf, 0, klen);
+       xfree(kbuf);
+
+       switch (kex->kex_type) {
+       case KEX_GSS_GRP1_SHA1:
+       case KEX_GSS_GRP14_SHA1:
+               kex_dh_hash(
+                   kex->client_version_string, kex->server_version_string,
+                   buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+                   buffer_ptr(&kex->my), buffer_len(&kex->my),
+                   NULL, 0, /* Change this if we start sending host keys */
+                   dh_client_pub, dh->pub_key, shared_secret,
+                   &hash, &hashlen
+               );
+               break;
+       case KEX_GSS_GEX_SHA1:
+               kexgex_hash(
+                   kex->evp_md,
+                   kex->client_version_string, kex->server_version_string,
+                   buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+                   buffer_ptr(&kex->my), buffer_len(&kex->my),
+                   NULL, 0,
+                   min, nbits, max,
+                   dh->p, dh->g,
+                   dh_client_pub,
+                   dh->pub_key,
+                   shared_secret,
+                   &hash, &hashlen
+               );
+               break;
+       default:
+               fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+       }
+
+       BN_clear_free(dh_client_pub);
+
+       if (kex->session_id == NULL) {
+               kex->session_id_len = hashlen;
+               kex->session_id = xmalloc(kex->session_id_len);
+               memcpy(kex->session_id, hash, kex->session_id_len);
+       }
+
+       gssbuf.value = hash;
+       gssbuf.length = hashlen;
+
+       if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
+               fatal("Couldn't get MIC");
+
+       packet_start(SSH2_MSG_KEXGSS_COMPLETE);
+       packet_put_bignum2(dh->pub_key);
+       packet_put_string(msg_tok.value,msg_tok.length);
+
+       if (send_tok.length != 0) {
+               packet_put_char(1); /* true */
+               packet_put_string(send_tok.value, send_tok.length);
+       } else {
+               packet_put_char(0); /* false */
+       }
+       packet_send();
+
+       gss_release_buffer(&min_status, &send_tok);
+       gss_release_buffer(&min_status, &msg_tok);
+
+       if (gss_kex_context == NULL)
+               gss_kex_context = ctxt;
+       else 
+               ssh_gssapi_delete_ctx(&ctxt);
+
+       DH_free(dh);
+
+       kex_derive_keys(kex, hash, hashlen, shared_secret);
+       BN_clear_free(shared_secret);
+       kex_finish(kex);
+
+       /* If this was a rekey, then save out any delegated credentials we
+        * just exchanged.  */
+       if (options.gss_store_rekey)
+               ssh_gssapi_rekey_creds();
+}
+#endif /* GSSAPI */
diff --git a/key.c b/key.c
index 498cf5a..fc65c29 100644 (file)
--- a/key.c
+++ b/key.c
@@ -971,6 +971,8 @@ key_ssh_name_from_type_nid(int type, int nid)
                }
                break;
 #endif /* OPENSSL_HAS_ECC */
+       case KEY_NULL:
+               return "null";
        }
        return "ssh-unknown";
 }
@@ -1276,6 +1278,8 @@ key_type_from_name(char *name)
            strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
                return KEY_ECDSA_CERT;
 #endif
+       } else if (strcmp(name, "null") == 0) {
+               return KEY_NULL;
        }
 
        debug2("key_type_from_name: unknown key type '%s'", name);
diff --git a/key.h b/key.h
index ec5ac5e..8b5c565 100644 (file)
--- a/key.h
+++ b/key.h
@@ -44,6 +44,7 @@ enum types {
        KEY_ECDSA_CERT,
        KEY_RSA_CERT_V00,
        KEY_DSA_CERT_V00,
+       KEY_NULL,
        KEY_UNSPEC
 };
 enum fp_type {
diff --git a/log.c b/log.c
index ad5a10b..2017408 100644 (file)
--- a/log.c
+++ b/log.c
@@ -92,6 +92,7 @@ static struct {
        LogLevel val;
 } log_levels[] =
 {
+       { "SILENT",     SYSLOG_LEVEL_QUIET }, /* compatibility */
        { "QUIET",      SYSLOG_LEVEL_QUIET },
        { "FATAL",      SYSLOG_LEVEL_FATAL },
        { "ERROR",      SYSLOG_LEVEL_ERROR },
diff --git a/misc.c b/misc.c
index 5f63090..1814ae3 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -48,8 +48,9 @@
 #include <netdb.h>
 #ifdef HAVE_PATHS_H
 # include <paths.h>
-#include <pwd.h>
 #endif
+#include <pwd.h>
+#include <grp.h>
 #ifdef SSH_TUN_OPENBSD
 #include <net/if.h>
 #endif
@@ -642,6 +643,55 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
 }
 
 int
+secure_permissions(struct stat *st, uid_t uid)
+{
+       if (st->st_uid != 0 && st->st_uid != uid)
+               return 0;
+       if ((st->st_mode & 002) != 0)
+               return 0;
+       if ((st->st_mode & 020) != 0) {
+               /* If the file is group-writable, the group in question must
+                * have exactly one member, namely the file's owner.
+                * (Zero-member groups are typically used by setgid
+                * binaries, and are unlikely to be suitable.)
+                */
+               struct passwd *pw;
+               struct group *gr;
+               int members = 0;
+
+               gr = getgrgid(st->st_gid);
+               if (!gr)
+                       return 0;
+
+               /* Check primary group memberships. */
+               while ((pw = getpwent()) != NULL) {
+                       if (pw->pw_gid == gr->gr_gid) {
+                               ++members;
+                               if (pw->pw_uid != uid)
+                                       return 0;
+                       }
+               }
+               endpwent();
+
+               pw = getpwuid(st->st_uid);
+               if (!pw)
+                       return 0;
+
+               /* Check supplementary group memberships. */
+               if (gr->gr_mem[0]) {
+                       ++members;
+                       if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
+                           gr->gr_mem[1])
+                               return 0;
+               }
+
+               if (!members)
+                       return 0;
+       }
+       return 1;
+}
+
+int
 tun_open(int tun, int mode)
 {
 #if defined(CUSTOM_SYS_TUN_OPEN)
diff --git a/misc.h b/misc.h
index f3142a9..904edc7 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -103,4 +103,6 @@ char        *read_passphrase(const char *, int);
 int     ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
 int     read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
 
+int     secure_permissions(struct stat *st, uid_t uid);
+
 #endif /* _MISC_H */
index 0e01b94..097abc1 100644 (file)
--- a/moduli.5
+++ b/moduli.5
@@ -21,7 +21,7 @@
 .Nd Diffie-Hellman moduli
 .Sh DESCRIPTION
 The
-.Pa /etc/moduli
+.Pa /etc/ssh/moduli
 file contains prime numbers and generators for use by
 .Xr sshd 8
 in the Diffie-Hellman Group Exchange key exchange method.
@@ -110,7 +110,7 @@ first estimates the size of the modulus required to produce enough
 Diffie-Hellman output to sufficiently key the selected symmetric cipher.
 .Xr sshd 8
 then randomly selects a modulus from
-.Fa /etc/moduli
+.Fa /etc/ssh/moduli
 that best meets the size requirement.
 .Sh SEE ALSO
 .Xr ssh-keygen 1 ,
index a166fed..985916b 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -145,6 +145,7 @@ int mm_answer_sign(int, Buffer *);
 int mm_answer_pwnamallow(int, Buffer *);
 int mm_answer_auth2_read_banner(int, Buffer *);
 int mm_answer_authserv(int, Buffer *);
+int mm_answer_authrole(int, Buffer *);
 int mm_answer_authpassword(int, Buffer *);
 int mm_answer_bsdauthquery(int, Buffer *);
 int mm_answer_bsdauthrespond(int, Buffer *);
@@ -180,6 +181,8 @@ int mm_answer_gss_setup_ctx(int, Buffer *);
 int mm_answer_gss_accept_ctx(int, Buffer *);
 int mm_answer_gss_userok(int, Buffer *);
 int mm_answer_gss_checkmic(int, Buffer *);
+int mm_answer_gss_sign(int, Buffer *);
+int mm_answer_gss_updatecreds(int, Buffer *);
 #endif
 
 #ifdef SSH_AUDIT_EVENTS
@@ -223,6 +226,7 @@ struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+    {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
 #ifdef USE_PAM
@@ -251,6 +255,7 @@ struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
     {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
     {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
 #endif
 #ifdef JPAKE
     {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
@@ -263,6 +268,12 @@ struct mon_table mon_dispatch_proto20[] = {
 };
 
 struct mon_table mon_dispatch_postauth20[] = {
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
+#endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
@@ -371,6 +382,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
                /* Permit requests for moduli and signatures */
                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+#ifdef GSSAPI
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+#endif
        } else {
                mon_dispatch = mon_dispatch_proto15;
 
@@ -468,6 +483,10 @@ monitor_child_postauth(struct monitor *pmonitor)
                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+#ifdef GSSAPI
+               /* and for the GSSAPI key exchange */
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+#endif         
        } else {
                mon_dispatch = mon_dispatch_postauth15;
                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
@@ -793,6 +812,7 @@ mm_answer_pwnamallow(int sock, Buffer *m)
        else {
                /* Allow service/style information on the auth context */
                monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
        }
 #ifdef USE_PAM
@@ -825,14 +845,37 @@ mm_answer_authserv(int sock, Buffer *m)
 
        authctxt->service = buffer_get_string(m, NULL);
        authctxt->style = buffer_get_string(m, NULL);
-       debug3("%s: service=%s, style=%s",
-           __func__, authctxt->service, authctxt->style);
+       authctxt->role = buffer_get_string(m, NULL);
+       debug3("%s: service=%s, style=%s, role=%s",
+           __func__, authctxt->service, authctxt->style, authctxt->role);
 
        if (strlen(authctxt->style) == 0) {
                xfree(authctxt->style);
                authctxt->style = NULL;
        }
 
+       if (strlen(authctxt->role) == 0) {
+               xfree(authctxt->role);
+               authctxt->role = NULL;
+       }
+
+       return (0);
+}
+
+int
+mm_answer_authrole(int sock, Buffer *m)
+{
+       monitor_permit_authentications(1);
+
+       authctxt->role = buffer_get_string(m, NULL);
+       debug3("%s: role=%s",
+           __func__, authctxt->role);
+
+       if (strlen(authctxt->role) == 0) {
+               xfree(authctxt->role);
+               authctxt->role = NULL;
+       }
+
        return (0);
 }
 
@@ -1420,7 +1463,7 @@ mm_answer_pty(int sock, Buffer *m)
        res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
        if (res == 0)
                goto error;
-       pty_setowner(authctxt->pw, s->tty);
+       pty_setowner(authctxt->pw, s->tty, authctxt->role);
 
        buffer_put_int(m, 1);
        buffer_put_cstring(m, s->tty);
@@ -1802,6 +1845,13 @@ mm_get_kex(Buffer *m)
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
        kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
+#endif
        kex->server = 1;
        kex->hostkey_type = buffer_get_int(m);
        kex->kex_type = buffer_get_int(m);
@@ -2008,6 +2058,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m)
        OM_uint32 major;
        u_int len;
 
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
        goid.elements = buffer_get_string(m, &len);
        goid.length = len;
 
@@ -2035,6 +2088,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
        OM_uint32 flags = 0; /* GSI needs this */
        u_int len;
 
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
        in.value = buffer_get_string(m, &len);
        in.length = len;
        major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
@@ -2052,6 +2108,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
+               monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
        }
        return (0);
 }
@@ -2063,6 +2120,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m)
        OM_uint32 ret;
        u_int len;
 
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
        gssbuf.value = buffer_get_string(m, &len);
        gssbuf.length = len;
        mic.value = buffer_get_string(m, &len);
@@ -2089,7 +2149,11 @@ mm_answer_gss_userok(int sock, Buffer *m)
 {
        int authenticated;
 
-       authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       authenticated = authctxt->valid && 
+           ssh_gssapi_userok(authctxt->user, authctxt->pw);
 
        buffer_clear(m);
        buffer_put_int(m, authenticated);
@@ -2102,6 +2166,74 @@ mm_answer_gss_userok(int sock, Buffer *m)
        /* Monitor loop will terminate if authenticated */
        return (authenticated);
 }
+
+int 
+mm_answer_gss_sign(int socket, Buffer *m)
+{
+       gss_buffer_desc data;
+       gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
+       OM_uint32 major, minor;
+       u_int len;
+
+       if (!options.gss_authentication && !options.gss_keyex)
+               fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+       data.value = buffer_get_string(m, &len);
+       data.length = len;
+       if (data.length != 20) 
+               fatal("%s: data length incorrect: %d", __func__, 
+                   (int) data.length);
+
+       /* Save the session ID on the first time around */
+       if (session_id2_len == 0) {
+               session_id2_len = data.length;
+               session_id2 = xmalloc(session_id2_len);
+               memcpy(session_id2, data.value, session_id2_len);
+       }
+       major = ssh_gssapi_sign(gsscontext, &data, &hash);
+
+       xfree(data.value);
+
+       buffer_clear(m);
+       buffer_put_int(m, major);
+       buffer_put_string(m, hash.value, hash.length);
+
+       mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
+
+       gss_release_buffer(&minor, &hash);
+
+       /* Turn on getpwnam permissions */
+       monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+       
+       /* And credential updating, for when rekeying */
+       monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
+
+       return (0);
+}
+
+int
+mm_answer_gss_updatecreds(int socket, Buffer *m) {
+       ssh_gssapi_ccache store;
+       int ok;
+
+       store.filename = buffer_get_string(m, NULL);
+       store.envvar   = buffer_get_string(m, NULL);
+       store.envval   = buffer_get_string(m, NULL);
+
+       ok = ssh_gssapi_update_creds(&store);
+
+       xfree(store.filename);
+       xfree(store.envvar);
+       xfree(store.envval);
+
+       buffer_clear(m);
+       buffer_put_int(m, ok);
+
+       mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
+
+       return(0);
+}
+
 #endif /* GSSAPI */
 
 #ifdef JPAKE
index 5e7d552..42887eb 100644 (file)
--- a/monitor.h
+++ b/monitor.h
@@ -30,7 +30,7 @@
 
 enum monitor_reqtype {
        MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
-       MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
+       MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, MONITOR_REQ_AUTHROLE,
        MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
        MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
        MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
@@ -53,6 +53,8 @@ enum monitor_reqtype {
        MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
        MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
        MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
+       MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
+       MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS,
        MONITOR_REQ_PAM_START,
        MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
        MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
index 1f60658..f46be66 100644 (file)
@@ -318,10 +318,10 @@ mm_auth2_read_banner(void)
        return (banner);
 }
 
-/* Inform the privileged process about service and style */
+/* Inform the privileged process about service, style, and role */
 
 void
-mm_inform_authserv(char *service, char *style)
+mm_inform_authserv(char *service, char *style, char *role)
 {
        Buffer m;
 
@@ -330,12 +330,30 @@ mm_inform_authserv(char *service, char *style)
        buffer_init(&m);
        buffer_put_cstring(&m, service);
        buffer_put_cstring(&m, style ? style : "");
+       buffer_put_cstring(&m, role ? role : "");
 
        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
 
        buffer_free(&m);
 }
 
+/* Inform the privileged process about role */
+
+void
+mm_inform_authrole(char *role)
+{
+       Buffer m;
+
+       debug3("%s entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_cstring(&m, role ? role : "");
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
+
+       buffer_free(&m);
+}
+
 /* Do the password authentication */
 int
 mm_auth_password(Authctxt *authctxt, char *password)
@@ -1270,7 +1288,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
 }
 
 int
-mm_ssh_gssapi_userok(char *user)
+mm_ssh_gssapi_userok(char *user, struct passwd *pw)
 {
        Buffer m;
        int authenticated = 0;
@@ -1287,6 +1305,51 @@ mm_ssh_gssapi_userok(char *user)
        debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
        return (authenticated);
 }
+
+OM_uint32
+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
+{
+       Buffer m;
+       OM_uint32 major;
+       u_int len;
+
+       buffer_init(&m);
+       buffer_put_string(&m, data->value, data->length);
+
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
+
+       major = buffer_get_int(&m);
+       hash->value = buffer_get_string(&m, &len);
+       hash->length = len;
+
+       buffer_free(&m);
+
+       return(major);
+}
+
+int
+mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
+{
+       Buffer m;
+       int ok;
+
+       buffer_init(&m);
+
+       buffer_put_cstring(&m, store->filename ? store->filename : "");
+       buffer_put_cstring(&m, store->envvar ? store->envvar : "");
+       buffer_put_cstring(&m, store->envval ? store->envval : "");
+       
+       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
+       mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
+
+       ok = buffer_get_int(&m);
+
+       buffer_free(&m);
+       
+       return (ok);
+}
+
 #endif /* GSSAPI */
 
 #ifdef JPAKE
index 0c7f2e3..4d12e29 100644 (file)
@@ -41,7 +41,8 @@ void mm_log_handler(LogLevel, const char *, void *);
 int mm_is_monitor(void);
 DH *mm_choose_dh(int, int, int);
 int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
-void mm_inform_authserv(char *, char *);
+void mm_inform_authserv(char *, char *, char *);
+void mm_inform_authrole(char *);
 struct passwd *mm_getpwnamallow(const char *);
 char *mm_auth2_read_banner(void);
 int mm_auth_password(struct Authctxt *, char *);
@@ -58,8 +59,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(Key *);
 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
 OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
-int mm_ssh_gssapi_userok(char *user);
+int mm_ssh_gssapi_userok(char *user, struct passwd *);
 OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
 #endif
 
 #ifdef USE_PAM
index 9887667..0118211 100644 (file)
@@ -209,8 +209,8 @@ getrrsetbyname(const char *hostname, unsigned int rdclass,
                goto fail;
        }
 
-       /* don't allow flags yet, unimplemented */
-       if (flags) {
+       /* Allow RRSET_FORCE_EDNS0 flag only. */
+       if ((flags & !RRSET_FORCE_EDNS0) != 0) {
                result = ERRSET_INVAL;
                goto fail;
        }
@@ -226,9 +226,9 @@ getrrsetbyname(const char *hostname, unsigned int rdclass,
 #endif /* DEBUG */
 
 #ifdef RES_USE_DNSSEC
-       /* turn on DNSSEC if EDNS0 is configured */
-       if (_resp->options & RES_USE_EDNS0)
-               _resp->options |= RES_USE_DNSSEC;
+       /* turn on DNSSEC if required  */
+       if (flags & RRSET_FORCE_EDNS0)
+               _resp->options |= (RES_USE_EDNS0|RES_USE_DNSSEC);
 #endif /* RES_USE_DNSEC */
 
        /* make query */
index 1283f55..dbbc85a 100644 (file)
@@ -72,6 +72,9 @@
 #ifndef RRSET_VALIDATED
 # define RRSET_VALIDATED       1
 #endif
+#ifndef RRSET_FORCE_EDNS0
+# define RRSET_FORCE_EDNS0     0x0001
+#endif
 
 /*
  * Return codes for getrrsetbyname()
index ea8dff4..ef91e44 100644 (file)
 #include <string.h>
 #include <stdio.h>
 
+#ifdef WITH_SELINUX
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#endif
+
 #include "log.h"
 #include "xmalloc.h"
 #include "port-linux.h"
@@ -58,9 +64,9 @@ ssh_selinux_enabled(void)
 
 /* Return the default security context for the given username */
 static security_context_t
-ssh_selinux_getctxbyname(char *pwname)
+ssh_selinux_getctxbyname(char *pwname, const char *role)
 {
-       security_context_t sc;
+       security_context_t sc = NULL;
        char *sename = NULL, *lvl = NULL;
        int r;
 
@@ -73,9 +79,16 @@ ssh_selinux_getctxbyname(char *pwname)
 #endif
 
 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
-       r = get_default_context_with_level(sename, lvl, NULL, &sc);
+       if (role != NULL && role[0])
+               r = get_default_context_with_rolelevel(sename, role, lvl, NULL,
+                                                      &sc);
+       else
+               r = get_default_context_with_level(sename, lvl, NULL, &sc);
 #else
-       r = get_default_context(sename, NULL, &sc);
+       if (role != NULL && role[0])
+               r = get_default_context_with_role(sename, role, NULL, &sc);
+       else
+               r = get_default_context(sename, NULL, &sc);
 #endif
 
        if (r != 0) {
@@ -106,7 +119,7 @@ ssh_selinux_getctxbyname(char *pwname)
 
 /* Set the execution context to the default for the specified user */
 void
-ssh_selinux_setup_exec_context(char *pwname)
+ssh_selinux_setup_exec_context(char *pwname, const char *role)
 {
        security_context_t user_ctx = NULL;
 
@@ -115,7 +128,7 @@ ssh_selinux_setup_exec_context(char *pwname)
 
        debug3("%s: setting execution context", __func__);
 
-       user_ctx = ssh_selinux_getctxbyname(pwname);
+       user_ctx = ssh_selinux_getctxbyname(pwname, role);
        if (setexeccon(user_ctx) != 0) {
                switch (security_getenforce()) {
                case -1:
@@ -137,7 +150,7 @@ ssh_selinux_setup_exec_context(char *pwname)
 
 /* Set the TTY context for the specified user */
 void
-ssh_selinux_setup_pty(char *pwname, const char *tty)
+ssh_selinux_setup_pty(char *pwname, const char *tty, const char *role)
 {
        security_context_t new_tty_ctx = NULL;
        security_context_t user_ctx = NULL;
@@ -148,7 +161,7 @@ ssh_selinux_setup_pty(char *pwname, const char *tty)
 
        debug3("%s: setting TTY context on %s", __func__, tty);
 
-       user_ctx = ssh_selinux_getctxbyname(pwname);
+       user_ctx = ssh_selinux_getctxbyname(pwname, role);
 
        /* XXX: should these calls fatal() upon failure in enforcing mode? */
 
index e3d1004..80ce13a 100644 (file)
@@ -21,8 +21,8 @@
 
 #ifdef WITH_SELINUX
 int ssh_selinux_enabled(void);
-void ssh_selinux_setup_pty(char *, const char *);
-void ssh_selinux_setup_exec_context(char *);
+void ssh_selinux_setup_pty(char *, const char *, const char *);
+void ssh_selinux_setup_exec_context(char *, const char *);
 void ssh_selinux_change_context(const char *);
 void ssh_selinux_setfscreatecon(const char *);
 #endif
index c3d9abf..0cdfcef 100644 (file)
 #define SSHDIR                         ETCDIR "/ssh"
 #endif
 
+#ifndef _PATH_SSH_DATADIR
+#define _PATH_SSH_DATADIR              "/usr/share/ssh"
+#endif
+
 #ifndef _PATH_SSH_PIDDIR
 #define _PATH_SSH_PIDDIR               "/var/run"
 #endif
@@ -44,6 +48,9 @@
 /* Backwards compatibility */
 #define _PATH_DH_PRIMES                        SSHDIR "/primes"
 
+#define _PATH_BLACKLIST                        _PATH_SSH_DATADIR "/blacklist"
+#define _PATH_BLACKLIST_CONFIG         SSHDIR "/blacklist"
+
 #ifndef _PATH_SSH_PROGRAM
 #define _PATH_SSH_PROGRAM              "/usr/bin/ssh"
 #endif
index a455472..e707aa4 100644 (file)
@@ -134,7 +134,7 @@ platform_setusercontext(struct passwd *pw)
  * called if sshd is running as root.
  */
 void
-platform_setusercontext_post_groups(struct passwd *pw)
+platform_setusercontext_post_groups(struct passwd *pw, const char *role)
 {
 #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
        /*
@@ -181,7 +181,7 @@ platform_setusercontext_post_groups(struct passwd *pw)
        }
 #endif /* HAVE_SETPCRED */
 #ifdef WITH_SELINUX
-       ssh_selinux_setup_exec_context(pw->pw_name);
+       ssh_selinux_setup_exec_context(pw->pw_name, role);
 #endif
 }
 
index 944d2c3..7b2d481 100644 (file)
@@ -26,7 +26,7 @@ void platform_post_fork_parent(pid_t child_pid);
 void platform_post_fork_child(void);
 int  platform_privileged_uidswap(void);
 void platform_setusercontext(struct passwd *);
-void platform_setusercontext_post_groups(struct passwd *);
+void platform_setusercontext_post_groups(struct passwd *, const char *);
 char *platform_get_krb5_client(const char *);
 char *platform_krb5_get_principal_name(const char *);
 
index 91dfa56..7a26e92 100644 (file)
@@ -30,6 +30,8 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
 
 #include "xmalloc.h"
 #include "ssh.h"
@@ -125,16 +127,20 @@ typedef enum {
        oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
        oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
        oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
+       oUseBlacklistedKeys,
        oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
        oClearAllForwardings, oNoHostAuthenticationForLocalhost,
        oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
        oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+       oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
+       oGssServerIdentity, 
        oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
        oSendEnv, oControlPath, oControlMaster, oControlPersist,
        oHashKnownHosts,
        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
        oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
        oKexAlgorithms, oIPQoS, oRequestTTY,
+       oProtocolKeepAlives, oSetupTimeOut,
        oDeprecated, oUnsupported
 } OpCodes;
 
@@ -156,6 +162,7 @@ static struct {
        { "passwordauthentication", oPasswordAuthentication },
        { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
        { "kbdinteractivedevices", oKbdInteractiveDevices },
+       { "useblacklistedkeys", oUseBlacklistedKeys },
        { "rsaauthentication", oRSAAuthentication },
        { "pubkeyauthentication", oPubkeyAuthentication },
        { "dsaauthentication", oPubkeyAuthentication },             /* alias */
@@ -169,10 +176,19 @@ static struct {
        { "afstokenpassing", oUnsupported },
 #if defined(GSSAPI)
        { "gssapiauthentication", oGssAuthentication },
+       { "gssapikeyexchange", oGssKeyEx },
        { "gssapidelegatecredentials", oGssDelegateCreds },
+       { "gssapitrustdns", oGssTrustDns },
+       { "gssapiclientidentity", oGssClientIdentity },
+       { "gssapiserveridentity", oGssServerIdentity },
+       { "gssapirenewalforcesrekey", oGssRenewalRekey },
 #else
        { "gssapiauthentication", oUnsupported },
+       { "gssapikeyexchange", oUnsupported },
        { "gssapidelegatecredentials", oUnsupported },
+       { "gssapitrustdns", oUnsupported },
+       { "gssapiclientidentity", oUnsupported },
+       { "gssapirenewalforcesrekey", oUnsupported },
 #endif
        { "fallbacktorsh", oDeprecated },
        { "usersh", oDeprecated },
@@ -246,6 +262,8 @@ static struct {
        { "kexalgorithms", oKexAlgorithms },
        { "ipqos", oIPQoS },
        { "requesttty", oRequestTTY },
+       { "protocolkeepalives", oProtocolKeepAlives },
+       { "setuptimeout", oSetupTimeOut },
 
        { NULL, oBadOption }
 };
@@ -478,14 +496,38 @@ parse_flag:
                intptr = &options->challenge_response_authentication;
                goto parse_flag;
 
+       case oUseBlacklistedKeys:
+               intptr = &options->use_blacklisted_keys;
+               goto parse_flag;
+
        case oGssAuthentication:
                intptr = &options->gss_authentication;
                goto parse_flag;
 
+       case oGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
        case oGssDelegateCreds:
                intptr = &options->gss_deleg_creds;
                goto parse_flag;
 
+       case oGssTrustDns:
+               intptr = &options->gss_trust_dns;
+               goto parse_flag;
+
+       case oGssClientIdentity:
+               charptr = &options->gss_client_identity;
+               goto parse_string;
+
+       case oGssServerIdentity:
+               charptr = &options->gss_server_identity;
+               goto parse_string;
+
+       case oGssRenewalRekey:
+               intptr = &options->gss_renewal_rekey;
+               goto parse_flag;
+
        case oBatchMode:
                intptr = &options->batch_mode;
                goto parse_flag;
@@ -877,6 +919,8 @@ parse_int:
                goto parse_flag;
 
        case oServerAliveInterval:
+       case oProtocolKeepAlives: /* Debian-specific compatibility alias */
+       case oSetupTimeOut:       /* Debian-specific compatibility alias */
                intptr = &options->server_alive_interval;
                goto parse_time;
 
@@ -1089,8 +1133,7 @@ read_config_file(const char *filename, const char *host, Options *options,
 
                if (fstat(fileno(f), &sb) == -1)
                        fatal("fstat %s: %s", filename, strerror(errno));
-               if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
-                   (sb.st_mode & 022) != 0))
+               if (!secure_permissions(&sb, getuid()))
                        fatal("Bad owner or permissions on %s", filename);
        }
 
@@ -1138,12 +1181,18 @@ initialize_options(Options * options)
        options->pubkey_authentication = -1;
        options->challenge_response_authentication = -1;
        options->gss_authentication = -1;
+       options->gss_keyex = -1;
        options->gss_deleg_creds = -1;
+       options->gss_trust_dns = -1;
+       options->gss_renewal_rekey = -1;
+       options->gss_client_identity = NULL;
+       options->gss_server_identity = NULL;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
        options->kbd_interactive_devices = NULL;
        options->rhosts_rsa_authentication = -1;
        options->hostbased_authentication = -1;
+       options->use_blacklisted_keys = -1;
        options->batch_mode = -1;
        options->check_host_ip = -1;
        options->strict_host_key_checking = -1;
@@ -1219,7 +1268,7 @@ fill_default_options(Options * options)
        if (options->forward_x11 == -1)
                options->forward_x11 = 0;
        if (options->forward_x11_trusted == -1)
-               options->forward_x11_trusted = 0;
+               options->forward_x11_trusted = 1;
        if (options->forward_x11_timeout == -1)
                options->forward_x11_timeout = 1200;
        if (options->exit_on_forward_failure == -1)
@@ -1238,8 +1287,14 @@ fill_default_options(Options * options)
                options->challenge_response_authentication = 1;
        if (options->gss_authentication == -1)
                options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
        if (options->gss_deleg_creds == -1)
                options->gss_deleg_creds = 0;
+       if (options->gss_trust_dns == -1)
+               options->gss_trust_dns = 0;
+       if (options->gss_renewal_rekey == -1)
+               options->gss_renewal_rekey = 0;
        if (options->password_authentication == -1)
                options->password_authentication = 1;
        if (options->kbd_interactive_authentication == -1)
@@ -1248,6 +1303,8 @@ fill_default_options(Options * options)
                options->rhosts_rsa_authentication = 0;
        if (options->hostbased_authentication == -1)
                options->hostbased_authentication = 0;
+       if (options->use_blacklisted_keys == -1)
+               options->use_blacklisted_keys = 0;
        if (options->batch_mode == -1)
                options->batch_mode = 0;
        if (options->check_host_ip == -1)
@@ -1334,8 +1391,13 @@ fill_default_options(Options * options)
                options->rekey_limit = 0;
        if (options->verify_host_key_dns == -1)
                options->verify_host_key_dns = 0;
-       if (options->server_alive_interval == -1)
-               options->server_alive_interval = 0;
+       if (options->server_alive_interval == -1) {
+               /* in batch mode, default is 5mins */
+               if (options->batch_mode == 1)
+                       options->server_alive_interval = 300;
+               else
+                       options->server_alive_interval = 0;
+       }
        if (options->server_alive_count_max == -1)
                options->server_alive_count_max = 3;
        if (options->control_master == -1)
index 5944cff..2d9005f 100644 (file)
@@ -47,12 +47,18 @@ typedef struct {
        int     challenge_response_authentication;
                                        /* Try S/Key or TIS, authentication. */
        int     gss_authentication;     /* Try GSS authentication */
+       int     gss_keyex;              /* Try GSS key exchange */
        int     gss_deleg_creds;        /* Delegate GSS credentials */
+       int     gss_trust_dns;          /* Trust DNS for GSS canonicalization */
+       int     gss_renewal_rekey;      /* Credential renewal forces rekey */
+       char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
+       char    *gss_server_identity;   /* GSSAPI target principal */
        int     password_authentication;        /* Try password
                                                 * authentication. */
        int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
        char    *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
        int     zero_knowledge_password_authentication; /* Try jpake */
+       int     use_blacklisted_keys;   /* If true, send */
        int     batch_mode;     /* Batch mode: do not ask for passwords. */
        int     check_host_ip;  /* Also keep track of keys for IP address */
        int     strict_host_key_checking;       /* Strict host key checking. */
diff --git a/scp.c b/scp.c
index 18b2597..69344b8 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -189,8 +189,16 @@ do_local_cmd(arglist *a)
 
        if (verbose_mode) {
                fprintf(stderr, "Executing:");
-               for (i = 0; i < a->num; i++)
-                       fprintf(stderr, " %s", a->list[i]);
+               for (i = 0; i < a->num; i++) {
+                       if (i == 0)
+                               fprintf(stderr, " %s", a->list[i]);
+                       else
+                               /*
+                                * TODO: misbehaves if a->list[i] contains a
+                                * single quote
+                                */
+                               fprintf(stderr, " '%s'", a->list[i]);
+               }
                fprintf(stderr, "\n");
        }
        if ((pid = fork()) == -1)
index 91986e5..1911ac5 100644 (file)
@@ -97,10 +97,14 @@ initialize_server_options(ServerOptions *options)
        options->kerberos_ticket_cleanup = -1;
        options->kerberos_get_afs_token = -1;
        options->gss_authentication=-1;
+       options->gss_keyex = -1;
        options->gss_cleanup_creds = -1;
+       options->gss_strict_acceptor = -1;
+       options->gss_store_rekey = -1;
        options->password_authentication = -1;
        options->kbd_interactive_authentication = -1;
        options->challenge_response_authentication = -1;
+       options->permit_blacklisted_keys = -1;
        options->permit_empty_passwd = -1;
        options->permit_user_env = -1;
        options->use_login = -1;
@@ -138,6 +142,7 @@ initialize_server_options(ServerOptions *options)
        options->authorized_principals_file = NULL;
        options->ip_qos_interactive = -1;
        options->ip_qos_bulk = -1;
+       options->debian_banner = -1;
 }
 
 void
@@ -225,14 +230,22 @@ fill_default_server_options(ServerOptions *options)
                options->kerberos_get_afs_token = 0;
        if (options->gss_authentication == -1)
                options->gss_authentication = 0;
+       if (options->gss_keyex == -1)
+               options->gss_keyex = 0;
        if (options->gss_cleanup_creds == -1)
                options->gss_cleanup_creds = 1;
+       if (options->gss_strict_acceptor == -1)
+               options->gss_strict_acceptor = 1;
+       if (options->gss_store_rekey == -1)
+               options->gss_store_rekey = 0;
        if (options->password_authentication == -1)
                options->password_authentication = 1;
        if (options->kbd_interactive_authentication == -1)
                options->kbd_interactive_authentication = 0;
        if (options->challenge_response_authentication == -1)
                options->challenge_response_authentication = 1;
+       if (options->permit_blacklisted_keys == -1)
+               options->permit_blacklisted_keys = 0;
        if (options->permit_empty_passwd == -1)
                options->permit_empty_passwd = 0;
        if (options->permit_user_env == -1)
@@ -277,6 +290,8 @@ fill_default_server_options(ServerOptions *options)
                options->ip_qos_interactive = IPTOS_LOWDELAY;
        if (options->ip_qos_bulk == -1)
                options->ip_qos_bulk = IPTOS_THROUGHPUT;
+       if (options->debian_banner == -1)
+               options->debian_banner = 1;
 
        /* Turn privilege separation on by default */
        if (use_privsep == -1)
@@ -309,7 +324,7 @@ typedef enum {
        sListenAddress, sAddressFamily,
        sPrintMotd, sPrintLastLog, sIgnoreRhosts,
        sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
-       sStrictModes, sEmptyPasswd, sTCPKeepAlive,
+       sStrictModes, sPermitBlacklistedKeys, sEmptyPasswd, sTCPKeepAlive,
        sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
        sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
        sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
@@ -318,12 +333,15 @@ typedef enum {
        sBanner, sUseDNS, sHostbasedAuthentication,
        sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
        sClientAliveCountMax, sAuthorizedKeysFile,
-       sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+       sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+       sGssKeyEx, sGssStoreRekey,
+       sAcceptEnv, sPermitTunnel,
        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
        sUsePrivilegeSeparation, sAllowAgentForwarding,
        sZeroKnowledgePasswordAuthentication, sHostCertificate,
        sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
        sKexAlgorithms, sIPQoS,
+       sDebianBanner,
        sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -382,10 +400,20 @@ static struct {
 #ifdef GSSAPI
        { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
        { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+       { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL },
+       { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
 #else
        { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
        { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
 #endif
+       { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
+       { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
        { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
        { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
        { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
@@ -407,6 +435,7 @@ static struct {
        { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
        { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
        { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
+       { "permitblacklistedkeys", sPermitBlacklistedKeys, SSHCFG_GLOBAL },
        { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
        { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
        { "uselogin", sUseLogin, SSHCFG_GLOBAL },
@@ -448,6 +477,7 @@ static struct {
        { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
        { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
        { "ipqos", sIPQoS, SSHCFG_ALL },
+       { "debianbanner", sDebianBanner, SSHCFG_GLOBAL },
        { NULL, sBadOption, 0 }
 };
 
@@ -962,10 +992,22 @@ process_server_config_line(ServerOptions *options, char *line,
                intptr = &options->gss_authentication;
                goto parse_flag;
 
+       case sGssKeyEx:
+               intptr = &options->gss_keyex;
+               goto parse_flag;
+
        case sGssCleanupCreds:
                intptr = &options->gss_cleanup_creds;
                goto parse_flag;
 
+       case sGssStrictAcceptor:
+               intptr = &options->gss_strict_acceptor;
+               goto parse_flag;
+
+       case sGssStoreRekey:
+               intptr = &options->gss_store_rekey;
+               goto parse_flag;
+
        case sPasswordAuthentication:
                intptr = &options->password_authentication;
                goto parse_flag;
@@ -1014,6 +1056,10 @@ process_server_config_line(ServerOptions *options, char *line,
                intptr = &options->tcp_keep_alive;
                goto parse_flag;
 
+       case sPermitBlacklistedKeys:
+               intptr = &options->permit_blacklisted_keys;
+               goto parse_flag;
+
        case sEmptyPasswd:
                intptr = &options->permit_empty_passwd;
                goto parse_flag;
@@ -1395,6 +1441,10 @@ process_server_config_line(ServerOptions *options, char *line,
                }
                break;
 
+       case sDebianBanner:
+               intptr = &options->debian_banner;
+               goto parse_int;
+
        case sDeprecated:
                logit("%s line %d: Deprecated option %s",
                    filename, linenum, arg);
@@ -1720,7 +1770,10 @@ dump_config(ServerOptions *o)
 #endif
 #ifdef GSSAPI
        dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+       dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
        dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
+       dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
+       dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
 #endif
 #ifdef JPAKE
        dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
@@ -1737,6 +1790,7 @@ dump_config(ServerOptions *o)
        dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
        dump_cfg_fmtint(sStrictModes, o->strict_modes);
        dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
+       dump_cfg_fmtint(sPermitBlacklistedKeys, o->permit_blacklisted_keys);
        dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
        dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
        dump_cfg_fmtint(sUseLogin, o->use_login);
index 89f38e2..0be15f0 100644 (file)
@@ -103,13 +103,17 @@ typedef struct {
        int     kerberos_get_afs_token;         /* If true, try to get AFS token if
                                                 * authenticated with Kerberos. */
        int     gss_authentication;     /* If true, permit GSSAPI authentication */
+       int     gss_keyex;              /* If true, permit GSSAPI key exchange */
        int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
+       int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
+       int     gss_store_rekey;
        int     password_authentication;        /* If true, permit password
                                                 * authentication. */
        int     kbd_interactive_authentication; /* If true, permit */
        int     challenge_response_authentication;
        int     zero_knowledge_password_authentication;
                                        /* If true, permit jpake auth */
+       int     permit_blacklisted_keys;        /* If true, permit */
        int     permit_empty_passwd;    /* If false, do not permit empty
                                         * passwords. */
        int     permit_user_env;        /* If true, read ~/.ssh/environment */
@@ -162,6 +166,8 @@ typedef struct {
 
        int     num_permitted_opens;
 
+       int     debian_banner;
+
        char   *chroot_directory;
        char   *revoked_keys_file;
        char   *trusted_user_ca_keys;
index 19b84ff..f7bbdad 100644 (file)
@@ -680,7 +680,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
                        if (!channel_still_open())
                                break;
                        if (!waiting_termination) {
-                               const char *s = "Waiting for forwarded connections to terminate...\r\n";
+                               const char *s = "Waiting for forwarded connections to terminate... (press ~& to background)\r\n";
                                char *cp;
                                waiting_termination = 1;
                                buffer_append(&stderr_buffer, s, strlen(s));
index 6a70400..5b34aa2 100644 (file)
--- a/session.c
+++ b/session.c
@@ -1471,7 +1471,7 @@ safely_chroot(const char *path, uid_t uid)
 
 /* Set login name, uid, gid, and groups. */
 void
-do_setusercontext(struct passwd *pw)
+do_setusercontext(struct passwd *pw, const char *role)
 {
        char *chroot_path, *tmp;
 
@@ -1499,7 +1499,7 @@ do_setusercontext(struct passwd *pw)
                endgrent();
 #endif
 
-               platform_setusercontext_post_groups(pw);
+               platform_setusercontext_post_groups(pw, role);
 
                if (options.chroot_directory != NULL &&
                    strcasecmp(options.chroot_directory, "none") != 0) {
@@ -1625,7 +1625,7 @@ do_child(Session *s, const char *command)
 
        /* Force a password change */
        if (s->authctxt->force_pwchange) {
-               do_setusercontext(pw);
+               do_setusercontext(pw, s->authctxt->role);
                child_close_fds();
                do_pwchange(s);
                exit(1);
@@ -1652,7 +1652,7 @@ do_child(Session *s, const char *command)
                /* When PAM is enabled we rely on it to do the nologin check */
                if (!options.use_pam)
                        do_nologin(pw);
-               do_setusercontext(pw);
+               do_setusercontext(pw, s->authctxt->role);
                /*
                 * PAM session modules in do_setusercontext may have
                 * generated messages, so if this in an interactive
@@ -2064,7 +2064,7 @@ session_pty_req(Session *s)
        tty_parse_modes(s->ttyfd, &n_bytes);
 
        if (!use_privsep)
-               pty_setowner(s->pw, s->tty);
+               pty_setowner(s->pw, s->tty, s->authctxt->role);
 
        /* Set window size from the packet. */
        pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
index cbb8e3a..cb4f196 100644 (file)
--- a/session.h
+++ b/session.h
@@ -76,7 +76,7 @@ void   session_pty_cleanup2(Session *);
 Session        *session_new(void);
 Session        *session_by_tty(char *);
 void    session_close(Session *);
-void    do_setusercontext(struct passwd *);
+void    do_setusercontext(struct passwd *, const char *);
 void    child_set_env(char ***envp, u_int *envsizep, const char *name,
                       const char *value);
 
index fd48ff9..64c277f 100644 (file)
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -81,6 +81,10 @@ environment variable must contain the name of its socket for
 .Nm
 to work.
 .Pp
+Any keys recorded in the blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 )
+will be refused.
+.Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl c
@@ -183,6 +187,7 @@ is unable to contact the authentication agent.
 .Xr ssh 1 ,
 .Xr ssh-agent 1 ,
 .Xr ssh-keygen 1 ,
+.Xr ssh-vulnkey 1 ,
 .Xr sshd 8
 .Sh AUTHORS
 OpenSSH is a derivative of the original and free
index 6d5e2a9..3e2f9f6 100644 (file)
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -142,7 +142,7 @@ static int
 add_file(AuthenticationConnection *ac, const char *filename)
 {
        Key *private, *cert;
-       char *comment = NULL;
+       char *comment = NULL, *fp;
        char msg[1024], *certpath;
        int fd, perms_ok, ret = -1;
        Buffer keyblob;
@@ -218,6 +218,14 @@ add_file(AuthenticationConnection *ac, const char *filename)
        } else {
                fprintf(stderr, "Could not add identity: %s\n", filename);
        }
+       if (blacklisted_key(private, &fp) == 1) {
+               fprintf(stderr, "Public key %s blacklisted (see "
+                   "ssh-vulnkey(1)); refusing to add it\n", fp);
+               xfree(fp);
+               key_free(private);
+               xfree(comment);
+               return -1;
+       }
 
 
        /* Now try to add the certificate flavour too */
index c29a1b7..31d5a08 100644 (file)
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -1,6 +1,6 @@
 /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #define SSH_GSS_OIDTYPE 0x06
 
+#define SSH2_MSG_KEXGSS_INIT                            30
+#define SSH2_MSG_KEXGSS_CONTINUE                        31
+#define SSH2_MSG_KEXGSS_COMPLETE                        32
+#define SSH2_MSG_KEXGSS_HOSTKEY                         33
+#define SSH2_MSG_KEXGSS_ERROR                           34
+#define SSH2_MSG_KEXGSS_GROUPREQ                       40
+#define SSH2_MSG_KEXGSS_GROUP                          41
+#define KEX_GSS_GRP1_SHA1_ID                           "gss-group1-sha1-"
+#define KEX_GSS_GRP14_SHA1_ID                          "gss-group14-sha1-"
+#define KEX_GSS_GEX_SHA1_ID                            "gss-gex-sha1-"
+
 typedef struct {
        char *filename;
        char *envvar;
        char *envval;
+       struct passwd *owner;
        void *data;
 } ssh_gssapi_ccache;
 
@@ -71,8 +83,11 @@ typedef struct {
        gss_buffer_desc displayname;
        gss_buffer_desc exportedname;
        gss_cred_id_t creds;
+       gss_name_t name;
        struct ssh_gssapi_mech_struct *mech;
        ssh_gssapi_ccache store;
+       int used;
+       int updated;
 } ssh_gssapi_client;
 
 typedef struct ssh_gssapi_mech_struct {
@@ -83,6 +98,7 @@ typedef struct ssh_gssapi_mech_struct {
        int (*userok) (ssh_gssapi_client *, char *);
        int (*localname) (ssh_gssapi_client *, char **);
        void (*storecreds) (ssh_gssapi_client *);
+       int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
 } ssh_gssapi_mech;
 
 typedef struct {
@@ -93,10 +109,11 @@ typedef struct {
        gss_OID         oid; /* client */
        gss_cred_id_t   creds; /* server */
        gss_name_t      client; /* server */
-       gss_cred_id_t   client_creds; /* server */
+       gss_cred_id_t   client_creds; /* both */
 } Gssctxt;
 
 extern ssh_gssapi_mech *supported_mechs[];
+extern Gssctxt *gss_kex_context;
 
 int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
@@ -116,16 +133,30 @@ void ssh_gssapi_build_ctx(Gssctxt **);
 void ssh_gssapi_delete_ctx(Gssctxt **);
 OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
 void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
+int ssh_gssapi_credentials_updated(Gssctxt *);
 
 /* In the server */
+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 
+    const char *);
+char *ssh_gssapi_client_mechanisms(const char *, const char *);
+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
+    const char *);
+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 
+    const char *);
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
-int ssh_gssapi_userok(char *name);
+int ssh_gssapi_userok(char *name, struct passwd *);
 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
 void ssh_gssapi_do_child(char ***, u_int *);
 void ssh_gssapi_cleanup_creds(void);
 void ssh_gssapi_storecreds(void);
 
+char *ssh_gssapi_server_mechanisms(void);
+int ssh_gssapi_oid_table_ok();
+
+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
 #endif /* GSSAPI */
 
 #endif /* _SSH_GSS_H */
index ede3792..7c8b1f2 100644 (file)
@@ -149,9 +149,7 @@ key in
 .Pa ~/.ssh/id_dsa
 or
 .Pa ~/.ssh/id_rsa .
-Additionally, the system administrator may use this to generate host keys,
-as seen in
-.Pa /etc/rc .
+Additionally, the system administrator may use this to generate host keys.
 .Pp
 Normally this program generates the key and asks for a file in which
 to store the private key.
@@ -197,9 +195,7 @@ The options are as follows:
 For each of the key types (rsa1, rsa, dsa and ecdsa) for which host keys
 do not exist, generate the host keys with the default key file path,
 an empty passphrase, default bits for the key type, and default comment.
-This is used by
-.Pa /etc/rc
-to generate new host keys.
+This is used by system administration scripts to generate new host keys.
 .It Fl a Ar trials
 Specifies the number of primality tests to perform when screening DH-GEX
 candidates using the
@@ -535,7 +531,7 @@ option.
 Valid generator values are 2, 3, and 5.
 .Pp
 Screened DH groups may be installed in
-.Pa /etc/moduli .
+.Pa /etc/ssh/moduli .
 It is important that this file contains moduli of a range of bit lengths and
 that both ends of a connection share common moduli.
 .Sh CERTIFICATES
@@ -661,7 +657,7 @@ on all machines
 where the user wishes to log in using public key authentication.
 There is no need to keep the contents of this file secret.
 .Pp
-.It Pa /etc/moduli
+.It Pa /etc/ssh/moduli
 Contains Diffie-Hellman groups used for DH-GEX.
 The file format is described in
 .Xr moduli 5 .
@@ -670,6 +666,7 @@ The file format is described in
 .Xr ssh 1 ,
 .Xr ssh-add 1 ,
 .Xr ssh-agent 1 ,
+.Xr ssh-vulnkey 1 ,
 .Xr moduli 5 ,
 .Xr sshd 8
 .Rs
diff --git a/ssh-vulnkey.1 b/ssh-vulnkey.1
new file mode 100644 (file)
index 0000000..bcb9d31
--- /dev/null
@@ -0,0 +1,242 @@
+.\" Copyright (c) 2008 Canonical Ltd.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd $Mdocdate: May 12 2008 $
+.Dt SSH-VULNKEY 1
+.Os
+.Sh NAME
+.Nm ssh-vulnkey
+.Nd check blacklist of compromised keys
+.Sh SYNOPSIS
+.Nm
+.Op Fl q | Fl v
+.Ar file ...
+.Nm
+.Fl a
+.Sh DESCRIPTION
+.Nm
+checks a key against a blacklist of compromised keys.
+.Pp
+A substantial number of keys are known to have been generated using a broken
+version of OpenSSL distributed by Debian which failed to seed its random
+number generator correctly.
+Keys generated using these OpenSSL versions should be assumed to be
+compromised.
+This tool may be useful in checking for such keys.
+.Pp
+Keys that are compromised cannot be repaired; replacements must be generated
+using
+.Xr ssh-keygen 1 .
+Make sure to update
+.Pa authorized_keys
+files on all systems where compromised keys were permitted to authenticate.
+.Pp
+The argument list will be interpreted as a list of paths to public key files
+or
+.Pa authorized_keys
+files.
+If no suitable file is found at a given path,
+.Nm
+will append
+.Pa .pub
+and retry, in case it was given a private key file.
+If no files are given as arguments,
+.Nm
+will check
+.Pa ~/.ssh/id_rsa ,
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/identity ,
+.Pa ~/.ssh/authorized_keys
+and
+.Pa ~/.ssh/authorized_keys2 ,
+as well as the system's host keys if readable.
+.Pp
+If
+.Dq -
+is given as an argument,
+.Nm
+will read from standard input.
+This can be used to process output from
+.Xr ssh-keyscan 1 ,
+for example:
+.Pp
+.Dl $ ssh-keyscan -t rsa remote.example.org | ssh-vulnkey -
+.Pp
+Unless the
+.Cm PermitBlacklistedKeys
+option is used,
+.Xr sshd 8
+will reject attempts to authenticate with keys in the compromised list.
+.Pp
+The output from
+.Nm
+looks like this:
+.Pp
+.Bd -literal -offset indent
+/etc/ssh/ssh_host_key:1: COMPROMISED: RSA1 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx root@host
+/home/user/.ssh/id_dsa:1: Not blacklisted: DSA 1024 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /home/user/.ssh/id_dsa.pub
+/home/user/.ssh/authorized_keys:3: Unknown (blacklist file not installed): RSA 1024 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx user@host
+.Ed
+.Pp
+Each line is of the following format (any lines beginning with
+.Dq #
+should be ignored by scripts):
+.Pp
+.Dl Ar filename : Ns Ar line : Ar status : Ar type Ar size Ar fingerprint Ar comment
+.Pp
+It is important to distinguish between the possible values of
+.Ar status :
+.Pp
+.Bl -tag -width Ds
+.It COMPROMISED
+These keys are listed in a blacklist file, normally because their
+corresponding private keys are well-known.
+Replacements must be generated using
+.Xr ssh-keygen 1 .
+.It Not blacklisted
+A blacklist file exists for this key type and size, but this key is not
+listed in it.
+Unless there is some particular reason to believe otherwise, this key
+may be used safely.
+(Note that DSA keys used with the broken version of OpenSSL distributed
+by Debian may be compromised in the event that anyone captured a network
+trace, even if they were generated with a secure version of OpenSSL.)
+.It Unknown (blacklist file not installed)
+No blacklist file exists for this key type and size.
+You should find a suitable published blacklist and install it before
+deciding whether this key is safe to use.
+.El
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Check keys of all users on the system.
+You will typically need to run
+.Nm
+as root to use this option.
+For each user,
+.Nm
+will check
+.Pa ~/.ssh/id_rsa ,
+.Pa ~/.ssh/id_dsa ,
+.Pa ~/.ssh/identity ,
+.Pa ~/.ssh/authorized_keys
+and
+.Pa ~/.ssh/authorized_keys2 .
+It will also check the system's host keys.
+.It Fl q
+Quiet mode.
+Normally,
+.Nm
+outputs the fingerprint of each key scanned, with a description of its
+status.
+This option suppresses that output.
+.It Fl v
+Verbose mode.
+Normally,
+.Nm
+does not output anything for keys that are not listed in their corresponding
+blacklist file (although it still produces output for keys for which there
+is no blacklist file, since their status is unknown).
+This option causes
+.Nm
+to produce output for all keys.
+.El
+.Sh EXIT STATUS
+.Nm
+will exit zero if any of the given keys were in the compromised list,
+otherwise non-zero.
+.Sh BLACKLIST FILE FORMAT
+The blacklist file may start with comments, on lines starting with
+.Dq # .
+After these initial comments, it must follow a strict format:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+All the lines must be exactly the same length (20 characters followed by a
+newline) and must be in sorted order.
+.It
+Each line must consist of the lower-case hexadecimal MD5 key fingerprint,
+without colons, and with the first 12 characters removed (that is, the least
+significant 80 bits of the fingerprint).
+.El
+.Pp
+The key fingerprint may be generated using
+.Xr ssh-keygen 1 :
+.Pp
+.Dl $ ssh-keygen -l -f /path/to/key
+.Pp
+This strict format is necessary to allow the blacklist file to be checked
+quickly, using a binary-search algorithm.
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.ssh/id_rsa
+If present, contains the protocol version 2 RSA authentication identity of
+the user.
+.It Pa ~/.ssh/id_dsa
+If present, contains the protocol version 2 DSA authentication identity of
+the user.
+.It Pa ~/.ssh/identity
+If present, contains the protocol version 1 RSA authentication identity of
+the user.
+.It Pa ~/.ssh/authorized_keys
+If present, lists the public keys (RSA/DSA) that can be used for logging in
+as this user.
+.It Pa ~/.ssh/authorized_keys2
+Obsolete name for
+.Pa ~/.ssh/authorized_keys .
+This file may still be present on some old systems, but should not be
+created if it is missing.
+.It Pa /etc/ssh/ssh_host_rsa_key
+If present, contains the protocol version 2 RSA identity of the system.
+.It Pa /etc/ssh/ssh_host_dsa_key
+If present, contains the protocol version 2 DSA identity of the system.
+.It Pa /etc/ssh/ssh_host_key
+If present, contains the protocol version 1 RSA identity of the system.
+.It Pa /usr/share/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH
+If present, lists the blacklisted keys of type
+.Ar TYPE
+.Pf ( Dq RSA
+or
+.Dq DSA )
+and bit length
+.Ar LENGTH .
+The format of this file is described above.
+RSA1 keys are converted to RSA before being checked in the blacklist.
+Note that the fingerprints of RSA1 keys are computed differently, so you
+will not be able to find them in the blacklist by hand.
+.It Pa /etc/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH
+Same as
+.Pa /usr/share/ssh/blacklist. Ns Ar TYPE Ns Pa - Ns Ar LENGTH ,
+but may be edited by the system administrator to add new blacklist entries.
+.El
+.Sh SEE ALSO
+.Xr ssh-keygen 1 ,
+.Xr sshd 8
+.Sh AUTHORS
+.An -nosplit
+.An Colin Watson Aq cjwatson@ubuntu.com
+.Pp
+Florian Weimer suggested the option to check keys of all users, and the idea
+of processing
+.Xr ssh-keyscan 1
+output.
diff --git a/ssh-vulnkey.c b/ssh-vulnkey.c
new file mode 100644 (file)
index 0000000..f8125e0
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2008 Canonical Ltd.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <openssl/evp.h>
+
+#include "xmalloc.h"
+#include "ssh.h"
+#include "log.h"
+#include "key.h"
+#include "authfile.h"
+#include "pathnames.h"
+#include "uidswap.h"
+#include "misc.h"
+
+extern char *__progname;
+
+/* Default files to check */
+static char *default_host_files[] = {
+       _PATH_HOST_RSA_KEY_FILE,
+       _PATH_HOST_DSA_KEY_FILE,
+       _PATH_HOST_KEY_FILE,
+       NULL
+};
+static char *default_files[] = {
+       _PATH_SSH_CLIENT_ID_RSA,
+       _PATH_SSH_CLIENT_ID_DSA,
+       _PATH_SSH_CLIENT_IDENTITY,
+       _PATH_SSH_USER_PERMITTED_KEYS,
+       _PATH_SSH_USER_PERMITTED_KEYS2,
+       NULL
+};
+
+static int verbosity = 0;
+
+static int some_keys = 0;
+static int some_unknown = 0;
+static int some_compromised = 0;
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage: %s [-aqv] [file ...]\n", __progname);
+       fprintf(stderr, "Options:\n");
+       fprintf(stderr, "  -a          Check keys of all users.\n");
+       fprintf(stderr, "  -q          Quiet mode.\n");
+       fprintf(stderr, "  -v          Verbose mode.\n");
+       exit(1);
+}
+
+static void
+describe_key(const char *filename, u_long linenum, const char *msg,
+    Key *key, const char *comment, int min_verbosity)
+{
+       char *fp;
+
+       fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+       if (verbosity >= min_verbosity) {
+               if (strchr(filename, ':'))
+                       printf("\"%s\"", filename);
+               else
+                       printf("%s", filename);
+               printf(":%lu: %s: %s %u %s %s\n", linenum, msg,
+                   key_type(key), key_size(key), fp, comment);
+       }
+       xfree(fp);
+}
+
+static int
+do_key(const char *filename, u_long linenum,
+    Key *key, const char *comment)
+{
+       Key *public;
+       int blacklist_status;
+       int ret = 1;
+
+       some_keys = 1;
+
+       public = key_demote(key);
+       if (public->type == KEY_RSA1)
+               public->type = KEY_RSA;
+
+       blacklist_status = blacklisted_key(public, NULL);
+       if (blacklist_status == -1) {
+               describe_key(filename, linenum,
+                   "Unknown (blacklist file not installed)", key, comment, 0);
+               some_unknown = 1;
+       } else if (blacklist_status == 1) {
+               describe_key(filename, linenum,
+                   "COMPROMISED", key, comment, 0);
+               some_compromised = 1;
+               ret = 0;
+       } else
+               describe_key(filename, linenum,
+                   "Not blacklisted", key, comment, 1);
+
+       key_free(public);
+
+       return ret;
+}
+
+static int
+do_filename(const char *filename, int quiet_open)
+{
+       FILE *f;
+       char line[SSH_MAX_PUBKEY_BYTES];
+       char *cp;
+       u_long linenum = 0;
+       Key *key;
+       char *comment = NULL;
+       int found = 0, ret = 1;
+
+       /* Copy much of key_load_public's logic here so that we can read
+        * several keys from a single file (e.g. authorized_keys).
+        */
+
+       if (strcmp(filename, "-") != 0) {
+               int save_errno;
+               f = fopen(filename, "r");
+               save_errno = errno;
+               if (!f) {
+                       char pubfile[MAXPATHLEN];
+                       if (strlcpy(pubfile, filename, sizeof pubfile) <
+                           sizeof(pubfile) &&
+                           strlcat(pubfile, ".pub", sizeof pubfile) <
+                           sizeof(pubfile))
+                               f = fopen(pubfile, "r");
+               }
+               errno = save_errno; /* earlier errno is more useful */
+               if (!f) {
+                       if (!quiet_open)
+                               perror(filename);
+                       return -1;
+               }
+               if (verbosity > 0)
+                       printf("# %s\n", filename);
+       } else
+               f = stdin;
+       while (read_keyfile_line(f, filename, line, sizeof(line),
+                   &linenum) != -1) {
+               int i;
+               char *space;
+               int type;
+               char *end;
+
+               /* Chop trailing newline. */
+               i = strlen(line) - 1;
+               if (line[i] == '\n')
+                       line[i] = '\0';
+
+               /* Skip leading whitespace, empty and comment lines. */
+               for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+                       ;
+               if (!*cp || *cp == '\n' || *cp == '#')
+                       continue;
+
+               /* Cope with ssh-keyscan output and options in
+                * authorized_keys files.
+                */
+               space = strchr(cp, ' ');
+               if (!space)
+                       continue;
+               *space = '\0';
+               type = key_type_from_name(cp);
+               *space = ' ';
+               /* Leading number (RSA1) or valid type (RSA/DSA) indicates
+                * that we have no host name or options to skip.
+                */
+               if ((strtol(cp, &end, 10) == 0 || *end != ' ') &&
+                   type == KEY_UNSPEC) {
+                       int quoted = 0;
+
+                       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 (!*cp)
+                               continue;
+               }
+
+               /* Read and process the key itself. */
+               key = key_new(KEY_RSA1);
+               if (key_read(key, &cp) == 1) {
+                       while (*cp == ' ' || *cp == '\t')
+                               cp++;
+                       if (!do_key(filename, linenum,
+                           key, *cp ? cp : filename))
+                               ret = 0;
+                       found = 1;
+               } else {
+                       key_free(key);
+                       key = key_new(KEY_UNSPEC);
+                       if (key_read(key, &cp) == 1) {
+                               while (*cp == ' ' || *cp == '\t')
+                                       cp++;
+                               if (!do_key(filename, linenum,
+                                   key, *cp ? cp : filename))
+                                       ret = 0;
+                               found = 1;
+                       }
+               }
+               key_free(key);
+       }
+       if (f != stdin)
+               fclose(f);
+
+       if (!found && filename) {
+               key = key_load_public(filename, &comment);
+               if (key) {
+                       if (!do_key(filename, 1, key, comment))
+                               ret = 0;
+                       found = 1;
+               }
+               if (comment)
+                       xfree(comment);
+       }
+
+       return ret;
+}
+
+static int
+do_host(int quiet_open)
+{
+       int i;
+       struct stat st;
+       int ret = 1;
+
+       for (i = 0; default_host_files[i]; i++) {
+               if (stat(default_host_files[i], &st) < 0 && errno == ENOENT)
+                       continue;
+               if (!do_filename(default_host_files[i], quiet_open))
+                       ret = 0;
+       }
+
+       return ret;
+}
+
+static int
+do_user(const char *dir)
+{
+       int i;
+       char *file;
+       struct stat st;
+       int ret = 1;
+
+       for (i = 0; default_files[i]; i++) {
+               xasprintf(&file, "%s/%s", dir, default_files[i]);
+               if (stat(file, &st) < 0 && errno == ENOENT) {
+                       xfree(file);
+                       continue;
+               }
+               if (!do_filename(file, 0))
+                       ret = 0;
+               xfree(file);
+       }
+
+       return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+       int opt, all_users = 0;
+       int ret = 1;
+       extern int optind;
+
+       /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+       sanitise_stdfd();
+
+       __progname = ssh_get_progname(argv[0]);
+
+       SSLeay_add_all_algorithms();
+       log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
+
+       /* We don't need the RNG ourselves, but symbol references here allow
+        * ld to link us properly.
+        */
+       seed_rng();
+
+       while ((opt = getopt(argc, argv, "ahqv")) != -1) {
+               switch (opt) {
+               case 'a':
+                       all_users = 1;
+                       break;
+               case 'q':
+                       verbosity--;
+                       break;
+               case 'v':
+                       verbosity++;
+                       break;
+               case 'h':
+               default:
+                       usage();
+               }
+       }
+
+       if (all_users) {
+               struct passwd *pw;
+
+               if (!do_host(0))
+                       ret = 0;
+
+               while ((pw = getpwent()) != NULL) {
+                       if (pw->pw_dir) {
+                               temporarily_use_uid(pw);
+                               if (!do_user(pw->pw_dir))
+                                       ret = 0;
+                               restore_uid();
+                       }
+               }
+       } else if (optind == argc) {
+               struct passwd *pw;
+
+               if (!do_host(1))
+                       ret = 0;
+
+               if ((pw = getpwuid(geteuid())) == NULL)
+                       fprintf(stderr, "No user found with uid %u\n",
+                           (u_int)geteuid());
+               else {
+                       if (!do_user(pw->pw_dir))
+                               ret = 0;
+               }
+       } else {
+               while (optind < argc)
+                       if (!do_filename(argv[optind++], 0))
+                               ret = 0;
+       }
+
+       if (verbosity >= 0) {
+               if (some_unknown) {
+                       printf("#\n");
+                       printf("# The status of some keys on your system is unknown.\n");
+                       printf("# You may need to install additional blacklist files.\n");
+               }
+               if (some_compromised) {
+                       printf("#\n");
+                       printf("# Some keys on your system have been compromised!\n");
+                       printf("# You must replace them using ssh-keygen(1).\n");
+               }
+               if (some_unknown || some_compromised) {
+                       printf("#\n");
+                       printf("# See the ssh-vulnkey(1) manual page for further advice.\n");
+               } else if (some_keys && verbosity > 0) {
+                       printf("#\n");
+                       printf("# No blacklisted keys!\n");
+               }
+       }
+
+       return ret;
+}
diff --git a/ssh.1 b/ssh.1
index 9c1ca4b..d20a567 100644 (file)
--- a/ssh.1
+++ b/ssh.1
@@ -731,6 +731,10 @@ The
 .Sx HISTORY
 section of
 .Xr ssl 8
+(on non-OpenBSD systems, see
+.nh
+http://www.openbsd.org/cgi\-bin/man.cgi?query=ssl&sektion=8#HISTORY)
+.hy
 contains a brief discussion of the DSA and RSA algorithms.
 .Pp
 The file
@@ -1298,6 +1302,8 @@ The file format and configuration options are described in
 .Xr ssh_config 5 .
 Because of the potential for abuse, this file must have strict permissions:
 read/write for the user, and not accessible by others.
+It may be group-writable provided that the group in question contains only
+the user.
 .Pp
 .It Pa ~/.ssh/environment
 Contains additional definitions for environment variables; see
@@ -1405,8 +1411,10 @@ if an error occurred.
 .Xr sftp 1 ,
 .Xr ssh-add 1 ,
 .Xr ssh-agent 1 ,
+.Xr ssh-argv0 1 ,
 .Xr ssh-keygen 1 ,
 .Xr ssh-keyscan 1 ,
+.Xr ssh-vulnkey 1 ,
 .Xr tun 4 ,
 .Xr hosts.equiv 5 ,
 .Xr ssh_config 5 ,
diff --git a/ssh.c b/ssh.c
index c717dcf..44b0056 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -678,7 +678,7 @@ main(int ac, char **av)
        /* Do not allocate a tty if stdin is not a tty. */
        if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
            options.request_tty != REQUEST_TTY_FORCE) {
-               if (tty_flag)
+               if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
                        logit("Pseudo-terminal will not be allocated because "
                            "stdin is not a terminal.");
                tty_flag = 0;
@@ -1476,7 +1476,7 @@ ssh_session2(void)
 static void
 load_public_identity_files(void)
 {
-       char *filename, *cp, thishost[NI_MAXHOST];
+       char *filename, *cp, thishost[NI_MAXHOST], *fp;
        char *pwdir = NULL, *pwname = NULL;
        int i = 0;
        Key *public;
@@ -1533,6 +1533,22 @@ load_public_identity_files(void)
                public = key_load_public(filename, NULL);
                debug("identity file %s type %d", filename,
                    public ? public->type : -1);
+               if (public && blacklisted_key(public, &fp) == 1) {
+                       if (options.use_blacklisted_keys)
+                               logit("Public key %s blacklisted (see "
+                                   "ssh-vulnkey(1)); continuing anyway", fp);
+                       else
+                               logit("Public key %s blacklisted (see "
+                                   "ssh-vulnkey(1)); refusing to send it",
+                                   fp);
+                       xfree(fp);
+                       if (!options.use_blacklisted_keys) {
+                               key_free(public);
+                               xfree(filename);
+                               filename = NULL;
+                               public = NULL;
+                       }
+               }
                xfree(options.identity_files[i]);
                identity_files[n_ids] = filename;
                identity_keys[n_ids] = public;
index 1893674..4281e73 100644 (file)
 # list of available options, their meanings and defaults, please see the
 # ssh_config(5) man page.
 
-Host *
+Host *
 #   ForwardAgent no
 #   ForwardX11 no
+#   ForwardX11Trusted yes
 #   RhostsRSAAuthentication no
 #   RSAAuthentication yes
 #   PasswordAuthentication yes
 #   HostbasedAuthentication no
 #   GSSAPIAuthentication no
 #   GSSAPIDelegateCredentials no
+#   GSSAPIKeyExchange no
+#   GSSAPITrustDNS no
 #   BatchMode no
 #   CheckHostIP yes
 #   AddressFamily any
@@ -45,3 +48,7 @@
 #   PermitLocalCommand no
 #   VisualHostKey no
 #   ProxyCommand ssh -q -W %h:%p gateway.example.com
+    SendEnv LANG LC_*
+    HashKnownHosts yes
+    GSSAPIAuthentication yes
+    GSSAPIDelegateCredentials no
index a782d6f..19bff6d 100644 (file)
@@ -71,6 +71,22 @@ Since the first obtained value for each parameter is used, more
 host-specific declarations should be given near the beginning of the
 file, and general defaults at the end.
 .Pp
+Note that the Debian
+.Ic openssh-client
+package sets several options as standard in
+.Pa /etc/ssh/ssh_config
+which are not the default in
+.Xr ssh 1 :
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+.Cm SendEnv No LANG LC_*
+.It
+.Cm HashKnownHosts No yes
+.It
+.Cm GSSAPIAuthentication No yes
+.El
+.Pp
 The configuration file has the following format:
 .Pp
 Empty lines and lines starting with
@@ -136,8 +152,12 @@ Valid arguments are
 If set to
 .Dq yes ,
 passphrase/password querying will be disabled.
+In addition, the
+.Cm ServerAliveInterval
+option will be set to 300 seconds by default.
 This option is useful in scripts and other batch jobs where no user
-is present to supply the password.
+is present to supply the password,
+and where it is desirable to detect a broken network swiftly.
 The argument must be
 .Dq yes
 or
@@ -495,7 +515,8 @@ token used for the session will be set to expire after 20 minutes.
 Remote clients will be refused access after this time.
 .Pp
 The default is
-.Dq no .
+.Dq yes
+(Debian-specific).
 .Pp
 See the X11 SECURITY extension specification for full details on
 the restrictions imposed on untrusted clients.
@@ -527,11 +548,43 @@ Specifies whether user authentication based on GSSAPI is allowed.
 The default is
 .Dq no .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
+.It Cm GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when 
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
 .It Cm GSSAPIDelegateCredentials
 Forward (delegate) credentials to the server.
 The default is
 .Dq no .
-Note that this option applies to protocol version 2 only.
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq no .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq no .
+This option only applies to protocol version 2 connections using GSSAPI.
 .It Cm HashKnownHosts
 Indicates that
 .Xr ssh 1
@@ -549,6 +602,9 @@ Note that existing names and addresses in known hosts files
 will not be converted automatically,
 but may be manually hashed using
 .Xr ssh-keygen 1 .
+Use of this option may break facilities such as tab-completion that rely
+on being able to read unhashed host names from
+.Pa ~/.ssh/known_hosts .
 .It Cm HostbasedAuthentication
 Specifies whether to try rhosts based authentication with public key
 authentication.
@@ -1057,7 +1113,10 @@ If, for example,
 .Cm ServerAliveCountMax
 is left at the default, if the server becomes unresponsive,
 ssh will disconnect after approximately 45 seconds.
-This option applies to protocol version 2 only.
+This option applies to protocol version 2 only; in protocol version
+1 there is no mechanism to request a response from the server to the
+server alive messages, so disconnection is the responsibility of the TCP
+stack.
 .It Cm ServerAliveInterval
 Sets a timeout interval in seconds after which if no data has been received
 from the server,
@@ -1065,8 +1124,15 @@ from the server,
 will send a message through the encrypted
 channel to request a response from the server.
 The default
-is 0, indicating that these messages will not be sent to the server.
+is 0, indicating that these messages will not be sent to the server,
+or 300 if the
+.Cm BatchMode
+option is set.
 This option applies to protocol version 2 only.
+.Cm ProtocolKeepAlives
+and
+.Cm SetupTimeOut
+are Debian-specific compatibility aliases for this option.
 .It Cm StrictHostKeyChecking
 If this flag is set to
 .Dq yes ,
@@ -1105,6 +1171,12 @@ Specifies whether the system should send TCP keepalive messages to the
 other side.
 If they are sent, death of the connection or crash of one
 of the machines will be properly noticed.
+This option only uses TCP keepalives (as opposed to using ssh level
+keepalives), so takes a long time to notice when the connection dies.
+As such, you probably want
+the
+.Cm ServerAliveInterval
+option as well.
 However, this means that
 connections will die if the route is down temporarily, and some people
 find it annoying.
@@ -1156,6 +1228,23 @@ is not specified, it defaults to
 .Dq any .
 The default is
 .Dq any:any .
+.It Cm UseBlacklistedKeys
+Specifies whether
+.Xr ssh 1
+should use keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 )
+for authentication.
+If
+.Dq yes ,
+then attempts to use compromised keys for authentication will be logged but
+accepted.
+It is strongly recommended that this be used only to install new authorized
+keys on the remote system, and even then only with the utmost care.
+If
+.Dq no ,
+then attempts to use compromised keys for authentication will be prevented.
+The default is
+.Dq no .
 .It Cm UsePrivilegedPort
 Specifies whether to use a privileged port for outgoing connections.
 The argument must be
@@ -1274,6 +1363,8 @@ The format of this file is described above.
 This file is used by the SSH client.
 Because of the potential for abuse, this file must have strict permissions:
 read/write for the user, and not accessible by others.
+It may be group-writable provided that the group in question contains only
+the user.
 .It Pa /etc/ssh/ssh_config
 Systemwide configuration file.
 This file provides defaults for those
index 0ee7266..aed4c0b 100644 (file)
@@ -144,7 +144,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
                /* Execute the proxy command.  Note that we gave up any
                   extra privileges above. */
                signal(SIGPIPE, SIG_DFL);
-               execv(argv[0], argv);
+               execvp(argv[0], argv);
                perror(argv[0]);
                exit(1);
        }
@@ -556,7 +556,7 @@ ssh_exchange_identification(int timeout_ms)
        snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
            compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
            compat20 ? PROTOCOL_MINOR_2 : minor1,
-           SSH_VERSION, compat20 ? "\r\n" : "\n");
+           SSH_RELEASE, compat20 ? "\r\n" : "\n");
        if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
            != strlen(buf))
                fatal("write: %.100s", strerror(errno));
@@ -1273,7 +1273,7 @@ ssh_local_cmd(const char *args)
        if (pid == 0) {
                signal(SIGPIPE, SIG_DFL);
                debug3("Executing %s -c \"%s\"", shell, args);
-               execl(shell, shell, "-c", args, (char *)NULL);
+               execlp(shell, shell, "-c", args, (char *)NULL);
                error("Couldn't execute %s -c \"%s\": %s",
                    shell, args, strerror(errno));
                _exit(1);
index c24b202..8346372 100644 (file)
@@ -160,9 +160,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
 {
        Kex *kex;
 
+#ifdef GSSAPI
+       char *orig = NULL, *gss = NULL;
+       char *gss_host = NULL;
+#endif
+
        xxx_host = host;
        xxx_hostaddr = hostaddr;
 
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               /* Add the GSSAPI mechanisms currently supported on this 
+                * client to the key exchange algorithm proposal */
+               orig = myproposal[PROPOSAL_KEX_ALGS];
+
+               if (options.gss_trust_dns)
+                       gss_host = (char *)get_canonical_hostname(1);
+               else
+                       gss_host = host;
+
+               gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
+               if (gss) {
+                       debug("Offering GSSAPI proposal: %s", gss);
+                       xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
+                           "%s,%s", gss, orig);
+               }
+       }
+#endif
+
        if (options.ciphers == (char *)-1) {
                logit("No valid ciphers for protocol version 2 given, using defaults.");
                options.ciphers = NULL;
@@ -197,6 +222,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
        if (options.kex_algorithms != NULL)
                myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
 
+#ifdef GSSAPI
+       /* If we've got GSSAPI algorithms, then we also support the
+        * 'null' hostkey, as a last resort */
+       if (options.gss_keyex && gss) {
+               orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+               xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 
+                   "%s,null", orig);
+               xfree(gss);
+       }
+#endif
+
        if (options.rekey_limit)
                packet_set_rekey_limit((u_int32_t)options.rekey_limit);
 
@@ -207,10 +243,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
        kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
        kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
+       }
+#endif
        kex->client_version_string=client_version_string;
        kex->server_version_string=server_version_string;
        kex->verify_host_key=&verify_host_key_callback;
 
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->gss_deleg_creds = options.gss_deleg_creds;
+               kex->gss_trust_dns = options.gss_trust_dns;
+               kex->gss_client = options.gss_client_identity;
+               if (options.gss_server_identity) {
+                       kex->gss_host = options.gss_server_identity;
+               } else {
+                       kex->gss_host = gss_host;
+        }
+       }
+#endif
+
        xxx_kex = kex;
 
        dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -305,6 +361,7 @@ void        input_gssapi_token(int type, u_int32_t, void *);
 void   input_gssapi_hash(int type, u_int32_t, void *);
 void   input_gssapi_error(int, u_int32_t, void *);
 void   input_gssapi_errtok(int, u_int32_t, void *);
+int    userauth_gsskeyex(Authctxt *authctxt);
 #endif
 
 void   userauth(Authctxt *, char *);
@@ -320,6 +377,11 @@ static char *authmethods_get(void);
 
 Authmethod authmethods[] = {
 #ifdef GSSAPI
+       {"gssapi-keyex",
+               userauth_gsskeyex,
+               NULL,
+               &options.gss_authentication,
+               NULL},
        {"gssapi-with-mic",
                userauth_gssapi,
                NULL,
@@ -626,19 +688,31 @@ userauth_gssapi(Authctxt *authctxt)
        static u_int mech = 0;
        OM_uint32 min;
        int ok = 0;
+       const char *gss_host;
+
+       if (options.gss_server_identity)
+               gss_host = options.gss_server_identity;
+       else if (options.gss_trust_dns)
+               gss_host = get_canonical_hostname(1);
+       else
+               gss_host = authctxt->host;
 
        /* Try one GSSAPI method at a time, rather than sending them all at
         * once. */
 
        if (gss_supported == NULL)
-               gss_indicate_mechs(&min, &gss_supported);
+               if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
+                       gss_supported = NULL;
+                       return 0;
+               }
 
        /* Check to see if the mechanism is usable before we offer it */
        while (mech < gss_supported->count && !ok) {
                /* My DER encoding requires length<128 */
                if (gss_supported->elements[mech].length < 128 &&
                    ssh_gssapi_check_mechanism(&gssctxt, 
-                   &gss_supported->elements[mech], authctxt->host)) {
+                   &gss_supported->elements[mech], gss_host, 
+                    options.gss_client_identity)) {
                        ok = 1; /* Mechanism works */
                } else {
                        mech++;
@@ -735,8 +809,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
 {
        Authctxt *authctxt = ctxt;
        Gssctxt *gssctxt;
-       int oidlen;
-       char *oidv;
+       u_int oidlen;
+       u_char *oidv;
 
        if (authctxt == NULL)
                fatal("input_gssapi_response: no authentication context");
@@ -846,6 +920,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
        xfree(msg);
        xfree(lang);
 }
+
+int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+       Buffer b;
+       gss_buffer_desc gssbuf;
+       gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
+       OM_uint32 ms;
+
+       static int attempt = 0;
+       if (attempt++ >= 1)
+               return (0);
+
+       if (gss_kex_context == NULL) {
+               debug("No valid Key exchange context"); 
+               return (0);
+       }
+
+       ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
+           "gssapi-keyex");
+
+       gssbuf.value = buffer_ptr(&b);
+       gssbuf.length = buffer_len(&b);
+
+       if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
+               buffer_free(&b);
+               return (0);
+       }
+
+       packet_start(SSH2_MSG_USERAUTH_REQUEST);
+       packet_put_cstring(authctxt->server_user);
+       packet_put_cstring(authctxt->service);
+       packet_put_cstring(authctxt->method->name);
+       packet_put_string(mic.value, mic.length);
+       packet_send();
+
+       buffer_free(&b);
+       gss_release_buffer(&ms, &mic);
+
+       return (1);
+}
+
 #endif /* GSSAPI */
 
 int
@@ -1373,6 +1489,8 @@ pubkey_prepare(Authctxt *authctxt)
 
        /* list of keys stored in the filesystem */
        for (i = 0; i < options.num_identity_files; i++) {
+               if (options.identity_files[i] == NULL)
+                       continue;
                key = options.identity_keys[i];
                if (key && key->type == KEY_RSA1)
                        continue;
@@ -1466,7 +1584,7 @@ userauth_pubkey(Authctxt *authctxt)
                        debug("Offering %s public key: %s", key_type(id->key),
                            id->filename);
                        sent = send_pubkey_test(authctxt, id);
-               } else if (id->key == NULL) {
+               } else if (id->key == NULL && id->filename) {
                        debug("Trying private key: %s", id->filename);
                        id->key = load_identity_file(id->filename);
                        if (id->key != NULL) {
diff --git a/sshd.8 b/sshd.8
index a91be0f..80b3a1e 100644 (file)
--- a/sshd.8
+++ b/sshd.8
@@ -69,7 +69,7 @@ over an insecure network.
 .Nm
 listens for connections from clients.
 It is normally started at boot from
-.Pa /etc/rc .
+.Pa /etc/init.d/ssh .
 It forks a new
 daemon for each incoming connection.
 The forked daemons handle
@@ -853,7 +853,7 @@ This file is for host-based authentication (see
 .Xr ssh 1 ) .
 It should only be writable by root.
 .Pp
-.It Pa /etc/moduli
+.It Pa /etc/ssh/moduli
 Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange".
 The file format is described in
 .Xr moduli 5 .
@@ -948,9 +948,9 @@ The content of this file is not sensitive; it can be world-readable.
 .Xr ssh-agent 1 ,
 .Xr ssh-keygen 1 ,
 .Xr ssh-keyscan 1 ,
+.Xr ssh-vulnkey 1 ,
 .Xr chroot 2 ,
 .Xr hosts_access 5 ,
-.Xr login.conf 5 ,
 .Xr moduli 5 ,
 .Xr sshd_config 5 ,
 .Xr inetd 8 ,
diff --git a/sshd.c b/sshd.c
index cc10395..9b32cb4 100644 (file)
--- a/sshd.c
+++ b/sshd.c
 #include "ssh-sandbox.h"
 #include "version.h"
 
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
+
 #ifdef LIBWRAP
 #include <tcpd.h>
 #include <syslog.h>
@@ -419,7 +423,8 @@ sshd_exchange_identification(int sock_in, int sock_out)
                minor = PROTOCOL_MINOR_1;
        }
        snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
-           SSH_VERSION, newline);
+           options.debian_banner ? SSH_RELEASE : SSH_RELEASE_MINIMUM,
+           newline);
        server_version_string = xstrdup(buf);
 
        /* Send our protocol version identification. */
@@ -726,7 +731,7 @@ privsep_postauth(Authctxt *authctxt)
        RAND_seed(rnd, sizeof(rnd));
 
        /* Drop privileges */
-       do_setusercontext(authctxt->pw);
+       do_setusercontext(authctxt->pw, authctxt->role);
 
  skip:
        /* It is safe now to apply the key state */
@@ -1594,6 +1599,11 @@ main(int ac, char **av)
                        sensitive_data.host_keys[i] = NULL;
                        continue;
                }
+               if (auth_key_is_revoked(key, 1)) {
+                       key_free(key);
+                       sensitive_data.host_keys[i] = NULL;
+                       continue;
+               }
                switch (key->type) {
                case KEY_RSA1:
                        sensitive_data.ssh1_host_key = key;
@@ -1612,10 +1622,13 @@ main(int ac, char **av)
                logit("Disabling protocol version 1. Could not load host key");
                options.protocol &= ~SSH_PROTO_1;
        }
+#ifndef GSSAPI
+       /* The GSSAPI key exchange can run without a host key */
        if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
                logit("Disabling protocol version 2. Could not load host key");
                options.protocol &= ~SSH_PROTO_2;
        }
+#endif
        if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
                logit("sshd: no hostkeys available -- exiting.");
                exit(1);
@@ -1944,6 +1957,60 @@ main(int ac, char **av)
        /* Log the connection. */
        verbose("Connection from %.500s port %d", remote_ip, remote_port);
 
+#ifdef USE_SECURITY_SESSION_API
+       /*
+        * Create a new security session for use by the new user login if
+        * the current session is the root session or we are not launched
+        * by inetd (eg: debugging mode or server mode).  We do not
+        * necessarily need to create a session if we are launched from
+        * inetd because Panther xinetd will create a session for us.
+        *
+        * The only case where this logic will fail is if there is an
+        * inetd running in a non-root session which is not creating
+        * new sessions for us.  Then all the users will end up in the
+        * same session (bad).
+        *
+        * When the client exits, the session will be destroyed for us
+        * automatically.
+        *
+        * We must create the session before any credentials are stored
+        * (including AFS pags, which happens a few lines below).
+        */
+       {
+               OSStatus err = 0;
+               SecuritySessionId sid = 0;
+               SessionAttributeBits sattrs = 0;
+
+               err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+               if (err)
+                       error("SessionGetInfo() failed with error %.8X",
+                           (unsigned) err);
+               else
+                       debug("Current Session ID is %.8X / Session Attributes are %.8X",
+                           (unsigned) sid, (unsigned) sattrs);
+
+               if (inetd_flag && !(sattrs & sessionIsRoot))
+                       debug("Running in inetd mode in a non-root session... "
+                           "assuming inetd created the session for us.");
+               else {
+                       debug("Creating new security session...");
+                       err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+                       if (err)
+                               error("SessionCreate() failed with error %.8X",
+                                   (unsigned) err);
+
+                       err = SessionGetInfo(callerSecuritySession, &sid, 
+                           &sattrs);
+                       if (err)
+                               error("SessionGetInfo() failed with error %.8X",
+                                   (unsigned) err);
+                       else
+                               debug("New Session ID is %.8X / Session Attributes are %.8X",
+                                   (unsigned) sid, (unsigned) sattrs);
+               }
+       }
+#endif
+
        /*
         * We don't want to listen forever unless the other side
         * successfully authenticates itself.  So we set up an alarm which is
@@ -2325,6 +2392,48 @@ do_ssh2_kex(void)
 
        myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
 
+#ifdef GSSAPI
+       {
+       char *orig;
+       char *gss = NULL;
+       char *newstr = NULL;
+       orig = myproposal[PROPOSAL_KEX_ALGS];
+
+       /* 
+        * If we don't have a host key, then there's no point advertising
+        * the other key exchange algorithms
+        */
+
+       if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+               orig = NULL;
+
+       if (options.gss_keyex)
+               gss = ssh_gssapi_server_mechanisms();
+       else
+               gss = NULL;
+
+       if (gss && orig)
+               xasprintf(&newstr, "%s,%s", gss, orig);
+       else if (gss)
+               newstr = gss;
+       else if (orig)
+               newstr = orig;
+
+       /* 
+        * If we've got GSSAPI mechanisms, then we've got the 'null' host
+        * key alg, but we can't tell people about it unless its the only
+        * host key algorithm we support
+        */
+       if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+               myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+       if (newstr)
+               myproposal[PROPOSAL_KEX_ALGS] = newstr;
+       else
+               fatal("No supported key exchange algorithms");
+       }
+#endif
+
        /* start key exchange */
        kex = kex_setup(myproposal);
        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
@@ -2332,6 +2441,13 @@ do_ssh2_kex(void)
        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
        kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#ifdef GSSAPI
+       if (options.gss_keyex) {
+               kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+               kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+       }
+#endif
        kex->server = 1;
        kex->client_version_string=client_version_string;
        kex->server_version_string=server_version_string;
index 473e866..e7a3339 100644 (file)
@@ -37,6 +37,7 @@
 # Authentication:
 
 #LoginGraceTime 2m
+# See /usr/share/doc/openssh-server/README.Debian.gz.
 #PermitRootLogin yes
 #StrictModes yes
 #MaxAuthTries 6
@@ -75,6 +76,8 @@ AuthorizedKeysFile    .ssh/authorized_keys
 # GSSAPI options
 #GSSAPIAuthentication no
 #GSSAPICleanupCredentials yes
+#GSSAPIStrictAcceptorCheck yes
+#GSSAPIKeyExchange no
 
 # Set this to 'yes' to enable PAM authentication, account processing, 
 # and session processing. If this is enabled, PAM authentication will 
index a6c3787..e736241 100644 (file)
@@ -57,6 +57,33 @@ Arguments may optionally be enclosed in double quotes
 .Pq \&"
 in order to represent arguments containing spaces.
 .Pp
+Note that the Debian
+.Ic openssh-server
+package sets several options as standard in
+.Pa /etc/ssh/sshd_config
+which are not the default in
+.Xr sshd 8 .
+The exact list depends on whether the package was installed fresh or
+upgraded from various possible previous versions, but includes at least the
+following:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+.Cm Protocol No 2
+.It
+.Cm ChallengeResponseAuthentication No no
+.It
+.Cm X11Forwarding No yes
+.It
+.Cm PrintMotd No no
+.It
+.Cm AcceptEnv No LANG LC_*
+.It
+.Cm Subsystem No sftp /usr/lib/openssh/sftp-server
+.It
+.Cm UsePAM No yes
+.El
+.Pp
 The possible
 keywords and their meanings are as follows (note that
 keywords are case-insensitive and arguments are case-sensitive):
@@ -222,8 +249,7 @@ This option is only available for protocol version 2.
 By default, no banner is displayed.
 .It Cm ChallengeResponseAuthentication
 Specifies whether challenge-response authentication is allowed (e.g. via
-PAM or though authentication styles supported in
-.Xr login.conf 5 )
+PAM).
 The default is
 .Dq yes .
 .It Cm ChrootDirectory
@@ -340,6 +366,11 @@ or
 .Dq no .
 The default is
 .Dq delayed .
+.It Cm DebianBanner
+Specifies whether the distribution-specified extra version suffix is
+included during initial protocol handshake.
+The default is
+.Dq yes .
 .It Cm DenyGroups
 This keyword can be followed by a list of group name patterns, separated
 by spaces.
@@ -424,12 +455,40 @@ Specifies whether user authentication based on GSSAPI is allowed.
 The default is
 .Dq no .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq no .
+Note that this option applies to protocol version 2 only.
 .It Cm GSSAPICleanupCredentials
 Specifies whether to automatically destroy the user's credentials cache
 on logout.
 The default is
 .Dq yes .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor 
+a client authenticates against. If
+.Dq yes
+then the client must authenticate against the
+.Pa host
+service on the current hostname. If 
+.Dq no
+then the client may authenticate against any service key stored in the 
+machine's default store. This facility is provided to assist with operation 
+on multi homed machines. 
+The default is
+.Dq yes .
+Note that this option applies only to protocol version 2 GSSAPI connections,
+and setting it to 
+.Dq no
+may only work with recent Kerberos GSSAPI libraries.
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
+.Dq no .
 .It Cm HostbasedAuthentication
 Specifies whether rhosts or /etc/hosts.equiv authentication together
 with successful public key client host authentication is allowed
@@ -767,6 +826,20 @@ are refused if the number of unauthenticated connections reaches
 Specifies whether password authentication is allowed.
 The default is
 .Dq yes .
+.It Cm PermitBlacklistedKeys
+Specifies whether
+.Xr sshd 8
+should allow keys recorded in its blacklist of known-compromised keys (see
+.Xr ssh-vulnkey 1 ) .
+If
+.Dq yes ,
+then attempts to authenticate with compromised keys will be logged but
+accepted.
+If
+.Dq no ,
+then attempts to authenticate with compromised keys will be rejected.
+The default is
+.Dq no .
 .It Cm PermitEmptyPasswords
 When password authentication is allowed, it specifies whether the
 server allows login to accounts with empty password strings.
@@ -995,6 +1068,9 @@ This avoids infinitely hanging sessions.
 .Pp
 To disable TCP keepalive messages, the value should be set to
 .Dq no .
+.Pp
+This option was formerly called
+.Cm KeepAlive .
 .It Cm TrustedUserCAKeys
 Specifies a file containing public keys of certificate authorities that are
 trusted to sign user certificates for authentication.
index bbbc0fe..8cc26a2 100644 (file)
--- a/sshpty.c
+++ b/sshpty.c
@@ -200,7 +200,7 @@ pty_change_window_size(int ptyfd, u_int row, u_int col,
 }
 
 void
-pty_setowner(struct passwd *pw, const char *tty)
+pty_setowner(struct passwd *pw, const char *tty, const char *role)
 {
        struct group *grp;
        gid_t gid;
@@ -227,7 +227,7 @@ pty_setowner(struct passwd *pw, const char *tty)
                    strerror(errno));
 
 #ifdef WITH_SELINUX
-       ssh_selinux_setup_pty(pw->pw_name, tty);
+       ssh_selinux_setup_pty(pw->pw_name, tty, role);
 #endif
 
        if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
index cfa3224..edf2436 100644 (file)
--- a/sshpty.h
+++ b/sshpty.h
@@ -24,4 +24,4 @@ int    pty_allocate(int *, int *, char *, size_t);
 void    pty_release(const char *);
 void    pty_make_controlling_tty(int *, const char *);
 void    pty_change_window_size(int, u_int, u_int, u_int, u_int);
-void    pty_setowner(struct passwd *, const char *);
+void    pty_setowner(struct passwd *, const char *, const char *);
index 6a1acb3..b731237 100644 (file)
--- a/version.h
+++ b/version.h
@@ -3,4 +3,9 @@
 #define SSH_VERSION    "OpenSSH_5.9"
 
 #define SSH_PORTABLE   "p1"
-#define SSH_RELEASE    SSH_VERSION SSH_PORTABLE
+#define SSH_RELEASE_MINIMUM    SSH_VERSION SSH_PORTABLE
+#ifdef SSH_EXTRAVERSION
+#define SSH_RELEASE    SSH_RELEASE_MINIMUM " " SSH_EXTRAVERSION
+#else
+#define SSH_RELEASE    SSH_RELEASE_MINIMUM
+#endif