summaryrefslogtreecommitdiff
path: root/security/openssh
diff options
context:
space:
mode:
authorDirk Meyer <dinoex@FreeBSD.org>2002-06-24 21:13:06 +0000
committerDirk Meyer <dinoex@FreeBSD.org>2002-06-24 21:13:06 +0000
commit499707792a06b5da6a172581a313c3a0ef69806b (patch)
treef60b30dcf7200e30ccb95bca2e280b78e0e243c8 /security/openssh
parentPERL -> REINPLACE_CMD. (diff)
Merge PAM-changes from openssh currrent
Fix build with SKEY=yes, pr# 36119 Cleanup pw_expire handling. Add missing includes Changes defaults to: PermitRootLogin=no, UsePrivilegeSeparation=no Use $PREFIX/etc/ssh for config, updating manpages too.
Notes
Notes: svn path=/head/; revision=61893
Diffstat (limited to 'security/openssh')
-rw-r--r--security/openssh/Makefile61
-rw-r--r--security/openssh/files/patch-Makefile8
-rw-r--r--security/openssh/files/patch-Makefile.inc9
-rw-r--r--security/openssh/files/patch-auth-pam.c826
-rw-r--r--security/openssh/files/patch-auth-pam.h42
-rw-r--r--security/openssh/files/patch-auth-skey.c36
-rw-r--r--security/openssh/files/patch-auth.c23
-rw-r--r--security/openssh/files/patch-auth.h9
-rw-r--r--security/openssh/files/patch-auth1.c116
-rw-r--r--security/openssh/files/patch-auth2-chall.c28
-rw-r--r--security/openssh/files/patch-auth2-pam.c336
-rw-r--r--security/openssh/files/patch-auth2-passwd.c14
-rw-r--r--security/openssh/files/patch-auth2.c13
-rw-r--r--security/openssh/files/patch-key.c11
-rw-r--r--security/openssh/files/patch-misc.c13
-rw-r--r--security/openssh/files/patch-monitor.c36
-rw-r--r--security/openssh/files/patch-pathnames.h17
-rw-r--r--security/openssh/files/patch-sshd_config21
-rw-r--r--security/openssh/pkg-plist32
19 files changed, 1525 insertions, 126 deletions
diff --git a/security/openssh/Makefile b/security/openssh/Makefile
index c6040f36f702..1243e9ef86ce 100644
--- a/security/openssh/Makefile
+++ b/security/openssh/Makefile
@@ -7,6 +7,7 @@
PORTNAME= openssh
PORTVERSION= 3.3
+PORTREVISION= 1
CATEGORIES= security
MASTER_SITES= ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/ \
ftp://ftp.usa.openbsd.org/pub/OpenBSD/OpenSSH/ \
@@ -28,6 +29,10 @@ MODIFY= ssh.h sshd_config sshd.sh pathnames.h
FIXME= lib/Makefile scp/Makefile sftp/Makefile sftp-server/Makefile \
ssh/Makefile ssh-add/Makefile ssh-agent/Makefile \
ssh-keygen/Makefile ssh-keyscan/Makefile sshd/Makefile
+PRECIOUS= ssh_config sshd_config \
+ ssh_host_key ssh_host_key.pub \
+ ssh_host_rsa_key ssh_host_rsa_key.pub \
+ ssh_host_dsa_key ssh_host_dsa_key.pub
.include <bsd.port.pre.mk>
@@ -59,6 +64,8 @@ MAKE_ENV+= PAM=${PAM}
.if defined(SKEY) && ${SKEY} == YES
MAKE_ENV+= SKEY=yes
.endif
+ETCOLD= ${PREFIX}/etc
+ETCSSH= ${PREFIX}/etc/ssh
WRKSRC= ${WRKDIR}/ssh
post-extract:
@@ -72,17 +79,18 @@ post-extract:
.endif
post-patch:
- @${MV} ${WRKSRC}/sshd_config ${WRKSRC}/sshd_config.sed
- ${SED} -e "s=/etc/ssh=${PREFIX}/etc/ssh=" \
+.for i in ${MODIFY:S/pathnames.h//} ${MAN1:S/slogin.1//} ${MAN5} ${MAN8}
+ @${MV} ${WRKSRC}/${i} ${WRKSRC}/${i}.sed
+ ${SED} -e "s=/etc/ssh=${ETCSSH}/ssh=" \
-e "s=/usr/libex=${PREFIX}/libex=" \
- ${WRKSRC}/sshd_config.sed > ${WRKSRC}/sshd_config
-.for i in ${MODIFY}
+ -e 's:__PREFIX__:${PREFIX}:g' \
+ ${WRKSRC}/${i}.sed >${WRKSRC}/${i}
+.endfor
+.for i in pathnames.h
@${MV} ${WRKSRC}/${i} ${WRKSRC}/${i}.sed
- ${SED} -e 's:__PREFIX__:${PREFIX}:g' ${WRKSRC}/${i}.sed >${WRKSRC}/${i}
+ ${SED} -e 's:__PREFIX__:${PREFIX}:g' \
+ ${WRKSRC}/${i}.sed >${WRKSRC}/${i}
.endfor
- @${PERL5} -pi -e 's:__PREFIX__:${PREFIX}:g' ${WRKSRC}/ssh.h \
- ${WRKSRC}/sshd_config ${WRKSRC}/sshd.sh \
- ${WRKSRC}/pathnames.h
.if ${OSVERSION} < 430000
post-configure:
@@ -99,34 +107,43 @@ post-configure:
pre-install:
${MKDIR} ${PREFIX}/libdata/ssh
+ ${MKDIR} ${PREFIX}/empty
+ ${MKDIR} ${ETCSSH}
+.for i in ${PRECIOUS}
+.if exists(${PREFIX}/etc/${i})
+ @${ECHO_MSG} ">> Linking ${ETCSSH}/${i} from old layout."
+ @${LN} ${ETCOLD}/${i} ${ETCSSH}/${i}
+.endif
+.endfor
post-install:
.if !defined(BATCH)
-.if !exists(${PREFIX}/etc/ssh_host_key)
+.if !exists(${ETCSSH}/ssh_host_key) && !exists(${ETCOLD}/ssh_host_key)
@${ECHO_MSG} ">> Generating an RSA1 secret host key."
- ${PREFIX}/bin/ssh-keygen -t rsa1 -N "" -f ${PREFIX}/etc/ssh_host_key
+ ${PREFIX}/bin/ssh-keygen -t rsa1 -N "" -f ${ETCSSH}/ssh_host_key
.endif
-.if !exists(${PREFIX}/etc/ssh_host_rsa_key)
+.if !exists(${ETCSSH}/ssh_host_rsa_key) && !exists(${ETCOLD}/ssh_host_rsa_key)
@${ECHO_MSG} ">> Generating a RSA secret host key."
- ${PREFIX}/bin/ssh-keygen -t rsa -N "" -f ${PREFIX}/etc/ssh_host_rsa_key
+ ${PREFIX}/bin/ssh-keygen -t rsa -N "" -f ${ETCSSH}/ssh_host_rsa_key
.endif
-.if !exists(${PREFIX}/etc/ssh_host_dsa_key)
+.if !exists(${ETCSSH}/ssh_host_dsa_key) && !exists(${ETCOLD}/ssh_host_dsa_key)
@${ECHO_MSG} ">> Generating a DSA secret host key."
- ${PREFIX}/bin/ssh-keygen -t dsa -N "" -f ${PREFIX}/etc/ssh_host_dsa_key
+ ${PREFIX}/bin/ssh-keygen -t dsa -N "" -f ${ETCSSH}/ssh_host_dsa_key
.endif
.endif
-.if !exists(${PREFIX}/etc/moduli)
+.if !exists(${ETCSSH}/moduli) && !exists(${ETCOLD}/moduli)
@${ECHO_MSG} ">> Installing moduli."
- ${INSTALL_DATA} -c ${FILESDIR}/moduli ${PREFIX}/etc/moduli
+ ${INSTALL_DATA} -c ${FILESDIR}/moduli ${ETCSSH}/moduli
.endif
${INSTALL_SCRIPT} ${WRKSRC}/sshd.sh ${PREFIX}/etc/rc.d/sshd.sh.sample
- ${INSTALL_DATA} -c ${WRKSRC}/ssh_config ${PREFIX}/etc/ssh_config-dist
- ${INSTALL_DATA} -c ${WRKSRC}/sshd_config ${PREFIX}/etc/sshd_config-dist
-.if !exists(${PREFIX}/etc/ssh_config) && !exists(${PREFIX}/etc/sshd_config)
- ${INSTALL_DATA} -c ${WRKSRC}/ssh_config ${PREFIX}/etc/ssh_config
- ${INSTALL_DATA} -c ${WRKSRC}/sshd_config ${PREFIX}/etc/sshd_config
+ ${INSTALL_DATA} -c ${WRKSRC}/ssh_config ${ETCSSH}/ssh_config-dist
+ ${INSTALL_DATA} -c ${WRKSRC}/sshd_config ${ETCSSH}/sshd_config-dist
+.if !exists(${ETCSSH}/ssh_config) && !exists(${ETCSSH}/sshd_config) \
+ && !exists(${ETCOLD}/ssh_config) && !exists(${ETCOLD}/sshd_config)
+ ${INSTALL_DATA} -c ${WRKSRC}/ssh_config ${ETCSSH}/ssh_config
+ ${INSTALL_DATA} -c ${WRKSRC}/sshd_config ${ETCSSH}/sshd_config
.else
- @${ECHO_MSG} ">> ${PREFIX}/etc/ssh{,d}_config exists, not being replaced!"
+ @${ECHO_MSG} ">> ${ETCSSH}/ssh{,d}_config exists, not being replaced!"
@${ECHO_MSG} ">> If this is left over from another version of SSH, you will"
@${ECHO_MSG} ">> need to update it to work with OpenSSH."
.endif
diff --git a/security/openssh/files/patch-Makefile b/security/openssh/files/patch-Makefile
index 9eb818815b35..f5a2dbfd5b91 100644
--- a/security/openssh/files/patch-Makefile
+++ b/security/openssh/files/patch-Makefile
@@ -1,10 +1,10 @@
---- Makefile.orig Tue Mar 12 08:36:18 2002
-+++ Makefile Tue Mar 12 08:52:48 2002
+--- Makefile.orig Sat Jun 22 12:40:30 2002
++++ Makefile Sat Jun 22 12:40:31 2002
@@ -1,6 +1,7 @@
- # $OpenBSD: Makefile,v 1.10 2002/02/09 17:37:34 deraadt Exp $
+ # $OpenBSD: Makefile,v 1.11 2002/05/23 19:24:30 markus Exp $
.include <bsd.own.mk>
+.include "Makefile.inc"
SUBDIR= lib ssh sshd ssh-add ssh-keygen ssh-agent scp sftp-server \
- ssh-keyscan sftp scard
+ ssh-keysign ssh-keyscan sftp scard
diff --git a/security/openssh/files/patch-Makefile.inc b/security/openssh/files/patch-Makefile.inc
index d4874c8b85c7..1a2997645cdd 100644
--- a/security/openssh/files/patch-Makefile.inc
+++ b/security/openssh/files/patch-Makefile.inc
@@ -1,6 +1,6 @@
---- Makefile.inc.orig Sun Jul 29 16:00:07 2001
-+++ Makefile.inc Wed Oct 3 13:49:31 2001
-@@ -17,10 +17,16 @@
+--- Makefile.inc.orig Wed Mar 6 01:23:27 2002
++++ Makefile.inc Mon Jun 24 20:28:00 2002
+@@ -17,10 +17,19 @@
.include <bsd.obj.mk>
@@ -20,4 +20,7 @@
+.if !defined(IGNORE_LIBSSH)
LDADD+= -L${.CURDIR}/../lib -lssh
DPADD+= ${.CURDIR}/../lib/libssh.a
++.if (${SKEY} == "yes")
++LDADD+= -lopie
++.endif
.endif
diff --git a/security/openssh/files/patch-auth-pam.c b/security/openssh/files/patch-auth-pam.c
new file mode 100644
index 000000000000..9f9bea9c4eaa
--- /dev/null
+++ b/security/openssh/files/patch-auth-pam.c
@@ -0,0 +1,826 @@
+--- auth-pam.c.orig Mon Jun 24 06:55:51 2002
++++ auth-pam.c Thu Mar 21 13:55:21 2002
+@@ -0,0 +1,823 @@
++/*
++ * Copyright (c) 2000 Damien Miller. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include "includes.h"
++
++#ifdef USE_PAM
++#include <security/pam_appl.h>
++#include "ssh.h"
++#include "xmalloc.h"
++#include "log.h"
++#include "servconf.h"
++#include "readpass.h"
++#include "canohost.h"
++
++RCSID("$FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/patch-auth-pam.c,v 1.1 2002-06-24 21:13:06 dinoex Exp $");
++
++#define NEW_AUTHTOK_MSG \
++ "Warning: Your password has expired, please change it now"
++
++#define SSHD_PAM_SERVICE "sshd"
++#define PAM_STRERROR(a, b) pam_strerror((a), (b))
++
++/* Callbacks */
++static int do_pam_conversation(int num_msg, const struct pam_message **msg,
++ struct pam_response **resp, void *appdata_ptr);
++void do_pam_cleanup_proc(void *context);
++void pam_msg_cat(const char *msg);
++
++/* module-local variables */
++static struct pam_conv conv = {
++ do_pam_conversation,
++ NULL
++};
++static pam_handle_t *pamh = NULL;
++static const char *pampasswd = NULL;
++static char *pam_msg = NULL;
++extern ServerOptions options;
++
++/* states for do_pam_conversation() */
++typedef enum { INITIAL_LOGIN, OTHER } pamstates;
++static pamstates pamstate = INITIAL_LOGIN;
++/* remember whether pam_acct_mgmt() returned PAM_NEWAUTHTOK_REQD */
++static int password_change_required = 0;
++/* remember whether the last pam_authenticate() succeeded or not */
++static int was_authenticated = 0;
++
++/* Remember what has been initialised */
++static int session_opened = 0;
++static int creds_set = 0;
++
++/*
++ * accessor which allows us to switch conversation structs according to
++ * the authentication method being used
++ */
++void do_pam_set_conv(struct pam_conv *conv)
++{
++ pam_set_item(pamh, PAM_CONV, conv);
++}
++
++/*
++ * PAM conversation function.
++ * There are two states this can run in.
++ *
++ * INITIAL_LOGIN mode simply feeds the password from the client into
++ * PAM in response to PAM_PROMPT_ECHO_OFF, and collects output
++ * messages with pam_msg_cat(). This is used during initial
++ * authentication to bypass the normal PAM password prompt.
++ *
++ * OTHER mode handles PAM_PROMPT_ECHO_OFF with read_passphrase(prompt, 1)
++ * and outputs messages to stderr. This mode is used if pam_chauthtok()
++ * is called to update expired passwords.
++ */
++static int do_pam_conversation(int num_msg, const struct pam_message **msg,
++ struct pam_response **resp, void *appdata_ptr)
++{
++ struct pam_response *reply;
++ int count;
++ char buf[1024];
++
++ /* PAM will free this later */
++ reply = malloc(num_msg * sizeof(*reply));
++ if (reply == NULL)
++ return PAM_CONV_ERR;
++
++ for (count = 0; count < num_msg; count++) {
++ switch ((*msg)[count].msg_style) {
++ case PAM_PROMPT_ECHO_ON:
++ if (pamstate == INITIAL_LOGIN) {
++ free(reply);
++ return PAM_CONV_ERR;
++ } else {
++ fputs((*msg)[count].msg, stderr);
++ fgets(buf, sizeof(buf), stdin);
++ reply[count].resp = xstrdup(buf);
++ reply[count].resp_retcode = PAM_SUCCESS;
++ break;
++ }
++ case PAM_PROMPT_ECHO_OFF:
++ if (pamstate == INITIAL_LOGIN) {
++ if (pampasswd == NULL) {
++ free(reply);
++ return PAM_CONV_ERR;
++ }
++ reply[count].resp = xstrdup(pampasswd);
++ } else {
++ reply[count].resp =
++ xstrdup(read_passphrase((*msg)[count].msg, 1));
++ }
++ reply[count].resp_retcode = PAM_SUCCESS;
++ break;
++ case PAM_ERROR_MSG:
++ case PAM_TEXT_INFO:
++ if ((*msg)[count].msg != NULL) {
++ if (pamstate == INITIAL_LOGIN)
++ pam_msg_cat((*msg)[count].msg);
++ else {
++ fputs((*msg)[count].msg, stderr);
++ fputs("\n", stderr);
++ }
++ }
++ reply[count].resp = xstrdup("");
++ reply[count].resp_retcode = PAM_SUCCESS;
++ break;
++ default:
++ free(reply);
++ return PAM_CONV_ERR;
++ }
++ }
++
++ *resp = reply;
++
++ return PAM_SUCCESS;
++}
++
++/* Called at exit to cleanly shutdown PAM */
++void do_pam_cleanup_proc(void *context)
++{
++ int pam_retval;
++
++ if (pamh != NULL && session_opened) {
++ pam_retval = pam_close_session(pamh, 0);
++ if (pam_retval != PAM_SUCCESS) {
++ log("Cannot close PAM session[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++ }
++
++ if (pamh != NULL && creds_set) {
++ pam_retval = pam_setcred(pamh, PAM_DELETE_CRED);
++ if (pam_retval != PAM_SUCCESS) {
++ debug("Cannot delete credentials[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++ }
++
++ if (pamh != NULL) {
++ pam_retval = pam_end(pamh, pam_retval);
++ if (pam_retval != PAM_SUCCESS) {
++ log("Cannot release PAM authentication[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++ }
++}
++
++/* Attempt password authentation using PAM */
++int auth_pam_password(Authctxt *authctxt, const char *password)
++{
++ struct passwd *pw = authctxt->pw;
++ int pam_retval;
++
++ do_pam_set_conv(&conv);
++
++ /* deny if no user. */
++ if (pw == NULL)
++ return 0;
++ if (pw->pw_uid == 0 && options.permit_root_login == 2)
++ return 0;
++ if (*password == '\0' && options.permit_empty_passwd == 0)
++ return 0;
++
++ pampasswd = password;
++
++ pamstate = INITIAL_LOGIN;
++ pam_retval = pam_authenticate(pamh, 0);
++ was_authenticated = (pam_retval == PAM_SUCCESS);
++ if (pam_retval == PAM_SUCCESS) {
++ debug("PAM Password authentication accepted for user \"%.100s\"",
++ pw->pw_name);
++ return 1;
++ } else {
++ debug("PAM Password authentication for \"%.100s\" failed[%d]: %s",
++ pw->pw_name, pam_retval, PAM_STRERROR(pamh, pam_retval));
++ return 0;
++ }
++}
++
++/* Do account management using PAM */
++int do_pam_account(char *username, char *remote_user)
++{
++ int pam_retval;
++
++ do_pam_set_conv(&conv);
++
++ debug("PAM setting rhost to \"%.200s\"",
++ get_canonical_hostname(options.verify_reverse_mapping));
++ pam_retval = pam_set_item(pamh, PAM_RHOST,
++ get_canonical_hostname(options.verify_reverse_mapping));
++ if (pam_retval != PAM_SUCCESS) {
++ fatal("PAM set rhost failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++
++ if (remote_user != NULL) {
++ debug("PAM setting ruser to \"%.200s\"", remote_user);
++ pam_retval = pam_set_item(pamh, PAM_RUSER, remote_user);
++ if (pam_retval != PAM_SUCCESS) {
++ fatal("PAM set ruser failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++ }
++
++ pam_retval = pam_acct_mgmt(pamh, 0);
++ switch (pam_retval) {
++ case PAM_SUCCESS:
++ /* This is what we want */
++ break;
++ case PAM_NEW_AUTHTOK_REQD:
++ pam_msg_cat(NEW_AUTHTOK_MSG);
++ /* flag that password change is necessary */
++ password_change_required = 1;
++ break;
++ default:
++ log("PAM rejected by account configuration[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ return(0);
++ }
++
++ return(1);
++}
++
++/* Do PAM-specific session initialisation */
++void do_pam_session(char *username, const char *ttyname)
++{
++ int pam_retval;
++
++ do_pam_set_conv(&conv);
++
++ if (ttyname != NULL) {
++ debug("PAM setting tty to \"%.200s\"", ttyname);
++ pam_retval = pam_set_item(pamh, PAM_TTY, ttyname);
++ if (pam_retval != PAM_SUCCESS) {
++ fatal("PAM set tty failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++ }
++
++ debug("do_pam_session: euid %u, uid %u", geteuid(), getuid());
++ pam_retval = pam_open_session(pamh, 0);
++ if (pam_retval != PAM_SUCCESS) {
++ fatal("PAM session setup failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++
++ session_opened = 1;
++}
++
++/* Set PAM credentials */
++void do_pam_setcred(void)
++{
++ int pam_retval;
++
++ do_pam_set_conv(&conv);
++
++ debug("PAM establishing creds");
++ pam_retval = pam_setcred(pamh, PAM_ESTABLISH_CRED);
++ if (pam_retval != PAM_SUCCESS) {
++ if (was_authenticated)
++ fatal("PAM setcred failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ else
++ debug("PAM setcred failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ } else
++ creds_set = 1;
++}
++
++/* accessor function for file scope static variable */
++int pam_password_change_required(void)
++{
++ return password_change_required;
++}
++
++/*
++ * Have user change authentication token if pam_acct_mgmt() indicated
++ * it was expired. This needs to be called after an interactive
++ * session is established and the user's pty is connected to
++ * stdin/stout/stderr.
++ */
++void do_pam_chauthtok(void)
++{
++ int pam_retval;
++
++ do_pam_set_conv(&conv);
++
++ if (password_change_required) {
++ pamstate = OTHER;
++ /*
++ * XXX: should we really loop forever?
++ */
++ do {
++ pam_retval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
++ if (pam_retval != PAM_SUCCESS) {
++ log("PAM pam_chauthtok failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++ } while (pam_retval != PAM_SUCCESS);
++ }
++}
++
++/* Cleanly shutdown PAM */
++void finish_pam(void)
++{
++ do_pam_cleanup_proc(NULL);
++ fatal_remove_cleanup(&do_pam_cleanup_proc, NULL);
++}
++
++/* Start PAM authentication for specified account */
++void start_pam(struct passwd *pw)
++{
++ int pam_retval;
++
++ debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
++
++ pam_retval = pam_start(SSHD_PAM_SERVICE, pw->pw_name, &conv, &pamh);
++
++ if (pam_retval != PAM_SUCCESS) {
++ fatal("PAM initialisation failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++
++#ifdef PAM_TTY_KLUDGE
++ /*
++ * Some PAM modules (e.g. pam_time) require a TTY to operate,
++ * and will fail in various stupid ways if they don't get one.
++ * sshd doesn't set the tty until too late in the auth process and may
++ * not even need one (for tty-less connections)
++ * Kludge: Set a fake PAM_TTY
++ */
++ pam_retval = pam_set_item(pamh, PAM_TTY, "ssh");
++ if (pam_retval != PAM_SUCCESS) {
++ fatal("PAM set tty failed[%d]: %.200s",
++ pam_retval, PAM_STRERROR(pamh, pam_retval));
++ }
++#endif /* PAM_TTY_KLUDGE */
++
++ fatal_add_cleanup(&do_pam_cleanup_proc, NULL);
++}
++
++/* Return list of PAM enviornment strings */
++char **fetch_pam_environment(void)
++{
++#ifdef HAVE_PAM_GETENVLIST
++ return(pam_getenvlist(pamh));
++#else /* HAVE_PAM_GETENVLIST */
++ return(NULL);
++#endif /* HAVE_PAM_GETENVLIST */
++}
++
++/* Print any messages that have been generated during authentication */
++/* or account checking to stderr */
++void print_pam_messages(void)
++{
++ if (pam_msg != NULL)
++ fputs(pam_msg, stderr);
++}
++
++/* Append a message to the PAM message buffer */
++void pam_msg_cat(const char *msg)
++{
++ char *p;
++ size_t new_msg_len;
++ size_t pam_msg_len;
++
++ new_msg_len = strlen(msg);
++
++ if (pam_msg) {
++ pam_msg_len = strlen(pam_msg);
++ pam_msg = xrealloc(pam_msg, new_msg_len + pam_msg_len + 2);
++ p = pam_msg + pam_msg_len;
++ } else {
++ pam_msg = p = xmalloc(new_msg_len + 2);
++ }
++
++ memcpy(p, msg, new_msg_len);
++ p[new_msg_len] = '\n';
++ p[new_msg_len + 1] = '\0';
++}
++
++struct inverted_pam_userdata {
++ /*
++ * Pipe for telling whether we are doing conversation or sending
++ * authentication results.
++ */
++ int statefd[2];
++ int challengefd[2];
++ int responsefd[2];
++
++ /* Whether we have sent off our challenge */
++ int state;
++};
++
++#define STATE_CONV 1
++#define STATE_AUTH_OK 2
++#define STATE_AUTH_FAIL 3
++
++int
++ssh_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp,
++ void *userdata) {
++ int i;
++ FILE *reader;
++ char buf[1024];
++ struct pam_response *reply = NULL;
++ char state_to_write = STATE_CONV; /* One char to write */
++ struct inverted_pam_userdata *ud = userdata;
++ char *response = NULL;
++
++ /* The stdio functions are more convenient for the read half */
++ reader = fdopen(ud->responsefd[0], "rb");
++ if (reader == NULL)
++ goto protocol_failure;
++
++ reply = malloc(num_msg * sizeof(struct pam_response));
++ if (reply == NULL)
++ return PAM_CONV_ERR;
++
++ if (write(ud->statefd[1], &state_to_write, 1) != 1)
++ goto protocol_failure;
++
++ /*
++ * Re-package our data and send it off to our better half (the actual SSH
++ * process)
++ */
++ if (write(ud->challengefd[1], buf,
++ sprintf(buf, "%d\n", num_msg)) == -1)
++ goto protocol_failure;
++ for (i = 0; i < num_msg; i++) {
++ if (write(ud->challengefd[1], buf,
++ sprintf(buf, "%d\n", msg[i]->msg_style)) == -1)
++ goto protocol_failure;
++ if (write(ud->challengefd[1], buf,
++ sprintf(buf, "%d\n", strlen(msg[i]->msg))) == -1)
++ goto protocol_failure;
++ if (write(ud->challengefd[1], msg[i]->msg,
++ strlen(msg[i]->msg)) == -1)
++ goto protocol_failure;
++ }
++ /*
++ * Read back responses. These may not be as nice as we want, as the SSH
++ * protocol isn't exactly a perfect fit with PAM.
++ */
++
++ for (i = 0; i < num_msg; i++) {
++ char buf[1024];
++ char *endptr;
++ size_t len; /* Length of the response */
++
++ switch (msg[i]->msg_style) {
++ case PAM_PROMPT_ECHO_OFF:
++ case PAM_PROMPT_ECHO_ON:
++ if (fgets(buf, sizeof(buf), reader) == NULL)
++ goto protocol_failure;
++ len = (size_t)strtoul(buf, &endptr, 10);
++ /* The length is supposed to stand on a line by itself */
++ if (endptr == NULL || *endptr != '\n')
++ goto protocol_failure;
++ response = malloc(len+1);
++ if (response == NULL)
++ goto protocol_failure;
++ if (fread(response, len, 1, reader) != 1)
++ goto protocol_failure;
++ response[len] = '\0';
++ reply[i].resp = response;
++ response = NULL;
++ break;
++ default:
++ reply[i].resp = NULL;
++ break;
++ }
++ }
++ *resp = reply;
++ return PAM_SUCCESS;
++ protocol_failure:
++ free(reply);
++ return PAM_CONV_ERR;
++}
++
++void
++ipam_free_cookie(struct inverted_pam_cookie *cookie) {
++ struct inverted_pam_userdata *ud;
++ int i;
++
++ if (cookie == NULL)
++ return;
++ ud = cookie->userdata;
++ cookie->userdata = NULL;
++ /* Free userdata if allocated */
++ if (ud) {
++ /* Close any opened file descriptors */
++ if (ud->statefd[0] != -1)
++ close(ud->statefd[0]);
++ if (ud->statefd[1] != -1)
++ close(ud->statefd[1]);
++ if (ud->challengefd[0] != -1)
++ close(ud->challengefd[0]);
++ if (ud->challengefd[1] != -1)
++ close(ud->challengefd[1]);
++ if (ud->responsefd[0] != -1)
++ close(ud->responsefd[0]);
++ if (ud->responsefd[1] != -1)
++ close(ud->responsefd[1]);
++ free(ud);
++ ud = NULL;
++ }
++ /* Now free the normal cookie */
++ if (cookie->pid != 0 && cookie->pid != -1) {
++ int status;
++
++ /* XXX Use different signal? */
++ kill(cookie->pid, SIGKILL);
++ waitpid(cookie->pid, &status, 0);
++ }
++ for (i = 0; i < cookie->num_msg; i++) {
++ if (cookie->resp && cookie->resp[i]) {
++ free(cookie->resp[i]->resp);
++ free(cookie->resp[i]);
++ }
++ if (cookie->msg && cookie->msg[i]) {
++ free((void *)cookie->msg[i]->msg);
++ free(cookie->msg[i]);
++ }
++ }
++ free(cookie->msg);
++ free(cookie->resp);
++ free(cookie);
++}
++
++/*
++ * Do first half of PAM authentication - this comes to the point where
++ * you get a message to send to the user.
++ */
++struct inverted_pam_cookie *
++ipam_start_auth(const char *service, const char *username) {
++ struct inverted_pam_cookie *cookie;
++ struct inverted_pam_userdata *ud;
++ static struct pam_conv conv = {
++ ssh_conv,
++ NULL
++ };
++ const char *rhost;
++
++ cookie = malloc(sizeof(*cookie));
++ if (cookie == NULL)
++ return NULL;
++ cookie->state = 0;
++ /* Set up the cookie so ipam_freecookie can be used on it */
++ cookie->num_msg = 0;
++ cookie->msg = NULL;
++ cookie->resp = NULL;
++ cookie->pid = -1;
++
++ ud = calloc(sizeof(*ud), 1);
++ if (ud == NULL) {
++ free(cookie);
++ return NULL;
++ }
++ cookie->userdata = ud;
++ ud->statefd[0] = ud->statefd[1] = -1;
++ ud->challengefd[0] = ud->challengefd[1] = -1;
++ ud->responsefd[0] = ud->responsefd[1] = -1;
++
++ if (pipe(ud->statefd) != 0) {
++ ud->statefd[0] = ud->statefd[1] = -1;
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ if (pipe(ud->challengefd) != 0) {
++ ud->challengefd[0] = ud->challengefd[1] = -1;
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ if (pipe(ud->responsefd) != 0) {
++ ud->responsefd[0] = ud->responsefd[1] = -1;
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ rhost = get_canonical_hostname(options.verify_reverse_mapping);
++ cookie->pid = fork();
++ if (cookie->pid == -1) {
++ ipam_free_cookie(cookie);
++ return NULL;
++ } else if (cookie->pid != 0) {
++ int num_msgs; /* Number of messages from PAM */
++ char *endptr;
++ char buf[1024];
++ FILE *reader;
++ size_t num_msg;
++ int i;
++ char state; /* Which state did the connection just enter? */
++
++ /* We are the parent - wait for a call to the communications
++ function to turn up, or the challenge to be finished */
++ if (read(ud->statefd[0], &state, 1) != 1) {
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ cookie->state = state;
++ switch (state) {
++ case STATE_CONV:
++ /* We are running the conversation function */
++ /* The stdio functions are more convenient for read */
++ reader = fdopen(ud->challengefd[0], "r");
++ if (reader == NULL) {
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ if (fgets(buf, 4, reader) == NULL) {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ num_msg = (size_t)strtoul(buf, &endptr, 10);
++ /* The length is supposed to stand on a line by itself */
++ if (endptr == NULL || *endptr != '\n') {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ cookie->msg =
++ malloc(sizeof(struct pam_message *) * num_msg);
++ cookie->resp =
++ malloc(sizeof(struct pam_response *) * num_msg);
++ if (cookie->msg == NULL || cookie->resp == NULL) {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ for (i = 0; i < num_msg; i++) {
++ cookie->msg[i] =
++ malloc(sizeof(struct pam_message));
++ cookie->resp[i] =
++ malloc(sizeof(struct pam_response));
++ if (cookie->msg[i] == NULL ||
++ cookie->resp[i] == NULL) {
++ for (;;) {
++ free(cookie->msg[i]);
++ free(cookie->resp[i]);
++ if (i == 0)
++ break;
++ i--;
++ }
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ cookie->msg[i]->msg = NULL;
++ cookie->resp[i]->resp = NULL;
++ cookie->resp[i]->resp_retcode = 0;
++ }
++ /* Set up so the above will be freed on failure */
++ cookie->num_msg = num_msg;
++ /*
++ * We have a an allocated response and message for
++ * each of the entries in the PAM structure - transfer
++ * the data sent to the conversation function over.
++ */
++ for (i = 0; i < num_msg; i++) {
++ size_t len;
++
++ if (fgets(buf, sizeof(buf), reader) == NULL) {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ cookie->msg[i]->msg_style =
++ (size_t)strtoul(buf, &endptr, 10);
++ if (endptr == NULL || *endptr != '\n') {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ if (fgets(buf, sizeof(buf), reader) == NULL) {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ len = (size_t)strtoul(buf, &endptr, 10);
++ if (endptr == NULL || *endptr != '\n') {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ cookie->msg[i]->msg = malloc(len + 1);
++ if (cookie->msg[i]->msg == NULL) {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ if (fread((char *)cookie->msg[i]->msg, len, 1, reader) !=
++ 1) {
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ *(char *)&(cookie->msg[i]->msg[len]) = '\0';
++ }
++ break;
++ case STATE_AUTH_OK:
++ case STATE_AUTH_FAIL:
++ break;
++ default:
++ /* Internal failure, somehow */
++ fclose(reader);
++ ipam_free_cookie(cookie);
++ return NULL;
++ }
++ return cookie;
++ } else {
++ /* We are the child */
++ pam_handle_t *pamh=NULL;
++ int retval;
++ char state;
++
++ conv.appdata_ptr = ud;
++ retval = pam_start(service, username, &conv, &pamh);
++ fprintf(stderr, "pam_start returned %d\n", retval);
++ if (retval == PAM_SUCCESS)
++ retval = pam_set_item(pamh, PAM_RHOST, rhost);
++ /* Is user really user? */
++ if (retval == PAM_SUCCESS)
++ retval = pam_authenticate(pamh, 0);
++ /* permitted access? */
++ if (retval == PAM_SUCCESS)
++ retval = pam_acct_mgmt(pamh, 0);
++ /* This is where we have been authorized or not. */
++
++ /* Be conservative - flag as auth failure if we can't close */
++ /*
++ * XXX This is based on example code from Linux-PAM -
++ * but can it really be correct to pam_end if
++ * pam_start failed?
++ */
++ if (pam_end(pamh, retval) != PAM_SUCCESS)
++ retval = PAM_AUTH_ERR;
++
++ /* Message to parent */
++ state = retval == PAM_SUCCESS ? STATE_AUTH_OK : STATE_AUTH_FAIL;
++ if (write(ud->statefd[1], &state, 1) != 1) {
++ _exit(1);
++ }
++ /* FDs will be closed, so further communication will stop */
++ _exit(0);
++ }
++}
++
++/*
++ * Do second half of PAM authentication - cookie should now be filled
++ * in with the response to the challenge.
++ */
++
++int
++ipam_complete_auth(struct inverted_pam_cookie *cookie) {
++ int i;
++ char buf[1024];
++ struct inverted_pam_userdata *ud = cookie->userdata;
++ char state;
++
++ /* Send over our responses */
++ for (i = 0; i < cookie->num_msg; i++) {
++ if (cookie->msg[i]->msg_style != PAM_PROMPT_ECHO_ON &&
++ cookie->msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
++ continue;
++ if (write(ud->responsefd[1], buf,
++ sprintf(buf, "%d\n", strlen(cookie->resp[i]->resp))) == -1) {
++ ipam_free_cookie(cookie);
++ return 0;
++ }
++ if (write(ud->responsefd[1], cookie->resp[i]->resp,
++ strlen(cookie->resp[i]->resp)) == -1) {
++ ipam_free_cookie(cookie);
++ return 0;
++ }
++ }
++ /* Find out what state we are changing to */
++ if (read(ud->statefd[0], &state, 1) != 1) {
++ ipam_free_cookie(cookie);
++ return 0;
++ }
++
++ return state == STATE_AUTH_OK ? 1 : 0;
++}
++
++#endif /* USE_PAM */
diff --git a/security/openssh/files/patch-auth-pam.h b/security/openssh/files/patch-auth-pam.h
new file mode 100644
index 000000000000..0d25afb860fa
--- /dev/null
+++ b/security/openssh/files/patch-auth-pam.h
@@ -0,0 +1,42 @@
+--- auth-pam.h.orig Mon Jun 24 06:55:53 2002
++++ auth-pam.h Sat May 5 03:12:45 2001
+@@ -0,0 +1,39 @@
++/*
++ * OpenSSH PAM authentication support.
++ *
++ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/patch-auth-pam.h,v 1.1 2002-06-24 21:13:06 dinoex Exp $
++ */
++#ifndef AUTH_PAM_H
++#define AUTH_PAM_H
++#include "includes.h"
++#ifdef USE_PAM
++
++#include "auth.h"
++#include <pwd.h> /* For struct passwd */
++
++void start_pam(struct passwd *pw);
++void finish_pam(void);
++int auth_pam_password(Authctxt *authctxt, const char *password);
++char **fetch_pam_environment(void);
++int do_pam_account(char *username, char *remote_user);
++void do_pam_session(char *username, const char *ttyname);
++void do_pam_setcred(void);
++void print_pam_messages(void);
++int pam_password_change_required(void);
++void do_pam_chauthtok(void);
++
++struct inverted_pam_cookie {
++ int state; /* Which state have we reached? */
++ pid_t pid; /* PID of child process */
++
++ /* Only valid in state STATE_CONV */
++ int num_msg; /* Number of messages */
++ struct pam_message **msg; /* Message structures */
++ struct pam_response **resp; /* Response structures */
++ struct inverted_pam_userdata *userdata;
++};
++void ipam_free_cookie(struct inverted_pam_cookie *cookie);
++struct inverted_pam_cookie *ipam_start_auth(const char *, const char *);
++
++#endif /* USE_PAM */
++#endif /* AUTH_PAM_H */
diff --git a/security/openssh/files/patch-auth-skey.c b/security/openssh/files/patch-auth-skey.c
new file mode 100644
index 000000000000..4ed5d6b47d69
--- /dev/null
+++ b/security/openssh/files/patch-auth-skey.c
@@ -0,0 +1,36 @@
+--- auth-skey.c.orig Wed Jun 19 02:27:55 2002
++++ auth-skey.c Mon Jun 24 20:35:50 2002
+@@ -26,7 +26,7 @@
+
+ #ifdef SKEY
+
+-#include <skey.h>
++#include <opie.h>
+
+ #include "xmalloc.h"
+ #include "auth.h"
+@@ -45,9 +45,11 @@
+ Authctxt *authctxt = ctx;
+ char challenge[1024], *p;
+ int len;
+- struct skey skey;
++ struct opie opie;
+
+- if (skeychallenge(&skey, authctxt->user, challenge) == -1)
++ if (opie_haskey(authctxt->user) != 0)
++ return -1;
++ if (opiechallenge(&opie, authctxt->user, challenge) == -1)
+ return -1;
+
+ *name = xstrdup("");
+@@ -73,8 +75,8 @@
+
+ if (authctxt->valid &&
+ numresponses == 1 &&
+- skey_haskey(authctxt->pw->pw_name) == 0 &&
+- skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1)
++ opie_haskey(authctxt->pw->pw_name) == 0 &&
++ opie_passverify(authctxt->pw->pw_name, responses[0]) != -1)
+ return 0;
+ return -1;
+ }
diff --git a/security/openssh/files/patch-auth.c b/security/openssh/files/patch-auth.c
index 446b88f8c8a3..ce62cee08b2e 100644
--- a/security/openssh/files/patch-auth.c
+++ b/security/openssh/files/patch-auth.c
@@ -1,8 +1,8 @@
---- auth.c.orig Fri Mar 1 14:12:10 2002
-+++ auth.c Fri Mar 8 20:57:17 2002
+--- auth.c.orig Fri May 17 16:27:55 2002
++++ auth.c Sat Jun 22 12:40:31 2002
@@ -25,7 +25,77 @@
#include "includes.h"
- RCSID("$OpenBSD: auth.c,v 1.35 2002/03/01 13:12:10 markus Exp $");
+ RCSID("$OpenBSD: auth.c,v 1.43 2002/05/17 14:27:55 millert Exp $");
+#if defined(__FreeBSD__) && __FreeBSD__ <= 3
+/*
@@ -78,20 +78,3 @@
#include "xmalloc.h"
#include "match.h"
-@@ -141,6 +211,16 @@
- }
- ga_free();
- }
-+#ifdef __FreeBSD__
-+ /* Fail if the account's expiration time has passed. */
-+ if (pw->pw_expire != 0) {
-+ struct timeval tv;
-+
-+ (void)gettimeofday(&tv, NULL);
-+ if (tv.tv_sec >= pw->pw_expire)
-+ return 0;
-+ }
-+#endif /* __FreeBSD__ */
- /* We found no reason not to let this user try to log on... */
- return 1;
- }
diff --git a/security/openssh/files/patch-auth.h b/security/openssh/files/patch-auth.h
new file mode 100644
index 000000000000..51e47f24c1e3
--- /dev/null
+++ b/security/openssh/files/patch-auth.h
@@ -0,0 +1,9 @@
+--- auth.h.orig Fri May 31 13:35:15 2002
++++ auth.h Mon Jun 24 20:35:50 2002
+@@ -185,5 +185,5 @@
+ #define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
+ #define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
+
+-#define SKEY_PROMPT "\nS/Key Password: "
++#define SKEY_PROMPT "\nOPIE Password: "
+ #endif
diff --git a/security/openssh/files/patch-auth1.c b/security/openssh/files/patch-auth1.c
index c579f6153dfb..1db999b0ad57 100644
--- a/security/openssh/files/patch-auth1.c
+++ b/security/openssh/files/patch-auth1.c
@@ -1,25 +1,38 @@
---- auth1.c.orig Wed Apr 10 10:21:47 2002
-+++ auth1.c Thu May 23 13:07:12 2002
-@@ -75,6 +75,18 @@
+--- auth1.c.orig Wed Jun 19 02:27:55 2002
++++ auth1.c Mon Jun 24 21:18:53 2002
+@@ -27,6 +27,14 @@
+ #include "uidswap.h"
+ #include "monitor_wrap.h"
+
++#ifdef HAVE_LOGIN_CAP
++#include <login_cap.h>
++#endif /* HAVE_LOGIN_CAP */
++#ifdef USE_PAM
++#include "auth-pam.h"
++#include <security/pam_appl.h>
++#endif /* USE_PAM */
++
+ /* import */
+ extern ServerOptions options;
+
+@@ -75,6 +83,16 @@
u_int ulen;
int type = 0;
struct passwd *pw = authctxt->pw;
+#ifdef HAVE_LOGIN_CAP
+ login_cap_t *lc;
-+#endif
++#endif /* HAVE_LOGIN_CAP */
+#ifdef USE_PAM
+ struct inverted_pam_cookie *pam_cookie;
+#endif /* USE_PAM */
-+#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
+ const char *from_host, *from_ip;
+
+ from_host = get_canonical_hostname(options.verify_reverse_mapping);
+ from_ip = get_remote_ipaddr();
-+#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
debug("Attempting authentication for %s%.100s.",
authctxt->valid ? "" : "illegal user ", authctxt->user);
-@@ -84,7 +96,11 @@
+@@ -84,7 +102,11 @@
#if defined(KRB4) || defined(KRB5)
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif
@@ -28,11 +41,11 @@
+ PRIVSEP(auth_pam_password(authctxt, ""))) {
+#else
+ PRIVSEP(auth_password(authctxt, ""))) {
-+#endif
++#endif /* USE_PAM */
auth_log(authctxt, 1, "without authentication", "");
return;
}
-@@ -94,6 +110,8 @@
+@@ -94,6 +116,8 @@
packet_send();
packet_write_wait();
@@ -41,7 +54,70 @@
for (;;) {
/* default to fail */
authenticated = 0;
-@@ -284,6 +302,34 @@
+@@ -243,12 +267,48 @@
+ packet_check_eom();
+
+ /* Try authentication with the password. */
+- authenticated = PRIVSEP(auth_password(authctxt, password));
++ authenticated =
++#ifdef USE_PAM
++ PRIVSEP(auth_pam_password(authctxt, password));
++#else
++ PRIVSEP(auth_password(authctxt, password));
++#endif /* USE_PAM */
+
+ memset(password, 0, strlen(password));
+ xfree(password);
+ break;
+
++#ifdef USE_PAM
++ case SSH_CMSG_AUTH_TIS:
++ debug("rcvd SSH_CMSG_AUTH_TIS: Trying PAM");
++ pam_cookie = ipam_start_auth("sshd", pw->pw_name);
++ /* We now have data available to send as a challenge */
++ if (pam_cookie->num_msg != 1 ||
++ (pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_OFF &&
++ pam_cookie->msg[0]->msg_style != PAM_PROMPT_ECHO_ON)) {
++ /* We got several challenges or an unknown challenge type */
++ ipam_free_cookie(pam_cookie);
++ pam_cookie = NULL;
++ break;
++ }
++ packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
++ packet_put_string(pam_cookie->msg[0]->msg, strlen(pam_cookie->msg[0]->msg));
++ packet_send();
++ packet_write_wait();
++ continue;
++ case SSH_CMSG_AUTH_TIS_RESPONSE:
++ debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
++ if (pam_cookie != NULL) {
++ char *response = packet_get_string(&dlen);
++
++ pam_cookie->resp[0]->resp = strdup(response);
++ xfree(response);
++ authenticated = ipam_complete_auth(pam_cookie);
++ ipam_free_cookie(pam_cookie);
++ pam_cookie = NULL;
++ }
++ break;
++#elif defined(SKEY)
+ case SSH_CMSG_AUTH_TIS:
+ debug("rcvd SSH_CMSG_AUTH_TIS");
+ if (options.challenge_response_authentication == 1) {
+@@ -275,6 +335,12 @@
+ xfree(response);
+ }
+ break;
++#else
++ case SSH_CMSG_AUTH_TIS:
++ /* TIS Authentication is unsupported */
++ log("TIS authentication unsupported.");
++ break;
++#endif
+
+ default:
+ /*
+@@ -284,6 +350,34 @@
log("Unknown message during authentication: type %d", type);
break;
}
@@ -76,14 +152,24 @@
#ifdef BSD_AUTH
if (authctxt->as) {
auth_close(authctxt->as);
-@@ -302,6 +348,15 @@
- /* Log before sending the reply */
+@@ -299,9 +393,24 @@
+ !auth_root_allowed(get_authname(type)))
+ authenticated = 0;
+
+- /* Log before sending the reply */
++ if (pw != NULL && pw->pw_uid == 0)
++ log("ROOT LOGIN as '%.100s' from %.100s",
++ pw->pw_name, from_host);
++
++ /* Log before ghT!
++sending the reply */
auth_log(authctxt, authenticated, get_authname(type), info);
+#ifdef USE_PAM
+ if (authenticated && !do_pam_account(pw->pw_name, client_user))
+ authenticated = 0;
+#endif
++
+ if (client_user != NULL) {
+ xfree(client_user);
+ client_user = NULL;
@@ -92,14 +178,14 @@
if (authenticated)
return;
-@@ -354,6 +409,11 @@
+@@ -354,6 +463,11 @@
authctxt->valid = 1;
else
debug("do_authentication: illegal user %s", user);
+
+#ifdef USE_PAM
-+ if (pw != NULL)
-+ start_pam(pw);
++ if (authctxt->pw != NULL)
++ start_pam(authctxt->pw);
+#endif
setproctitle("%s%s", authctxt->pw ? user : "unknown",
diff --git a/security/openssh/files/patch-auth2-chall.c b/security/openssh/files/patch-auth2-chall.c
new file mode 100644
index 000000000000..488bdf9d036e
--- /dev/null
+++ b/security/openssh/files/patch-auth2-chall.c
@@ -0,0 +1,28 @@
+--- auth2-chall.c.orig Wed Jun 19 02:27:55 2002
++++ auth2-chall.c Mon Jun 24 06:54:04 2002
+@@ -40,19 +40,19 @@
+
+ #ifdef BSD_AUTH
+ extern KbdintDevice bsdauth_device;
+-#else
+-#ifdef SKEY
++#elif defined(USE_PAM)
++extern KbdintDevice pam_device;
++#elif defined(SKEY)
+ extern KbdintDevice skey_device;
+ #endif
+-#endif
+
+ KbdintDevice *devices[] = {
+ #ifdef BSD_AUTH
+ &bsdauth_device,
+-#else
+-#ifdef SKEY
++#elif defined(USE_PAM)
++ &pam_device,
++#elif defined(SKEY)
+ &skey_device,
+-#endif
+ #endif
+ NULL
+ };
diff --git a/security/openssh/files/patch-auth2-pam.c b/security/openssh/files/patch-auth2-pam.c
new file mode 100644
index 000000000000..73605e236db2
--- /dev/null
+++ b/security/openssh/files/patch-auth2-pam.c
@@ -0,0 +1,336 @@
+--- auth2-pam.c.orig Mon Jun 24 06:54:42 2002
++++ auth2-pam.c Mon Apr 22 08:25:13 2002
+@@ -0,0 +1,333 @@
++/*-
++ * Copyright (c) 2002 Networks Associates Technology, Inc.
++ * All rights reserved.
++ *
++ * This software was developed for the FreeBSD Project by ThinkSec AS and
++ * NAI Labs, the Security Research Division of Network Associates, Inc.
++ * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
++ * DARPA CHATS research program.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior written
++ * permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ *
++ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/patch-auth2-pam.c,v 1.1 2002-06-24 21:13:06 dinoex Exp $
++ */
++
++#ifdef USE_PAM
++#include "includes.h"
++RCSID("$FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/patch-auth2-pam.c,v 1.1 2002-06-24 21:13:06 dinoex Exp $");
++
++#include <security/pam_appl.h>
++
++#include "auth.h"
++#include "log.h"
++#include "xmalloc.h"
++
++struct pam_ctxt {
++ char *pam_user;
++ pid_t pam_pid;
++ int pam_sock;
++ int pam_done;
++};
++
++static void pam_free_ctx(void *);
++
++/*
++ * Send message to parent or child.
++ */
++static int
++pam_send(struct pam_ctxt *ctxt, char *fmt, ...)
++{
++ va_list ap;
++ char *mstr;
++ size_t len;
++ int r;
++
++ va_start(ap, fmt);
++ len = vasprintf(&mstr, fmt, ap);
++ va_end(ap);
++ if (mstr == NULL)
++ exit(1);
++ if (ctxt->pam_pid != 0)
++ debug2("to child: %s", mstr);
++ r = send(ctxt->pam_sock, mstr, len + 1, MSG_EOR);
++ free(mstr);
++ return (r);
++}
++
++/*
++ * Peek at first byte of next message.
++ */
++static int
++pam_peek(struct pam_ctxt *ctxt)
++{
++ char ch;
++
++ if (recv(ctxt->pam_sock, &ch, 1, MSG_PEEK) < 1)
++ return (-1);
++ return (ch);
++}
++
++/*
++ * Receive a message from parent or child.
++ */
++static char *
++pam_receive(struct pam_ctxt *ctxt)
++{
++ char *buf;
++ size_t len;
++ ssize_t rlen;
++
++ len = 64;
++ buf = NULL;
++ do {
++ len *= 2;
++ buf = xrealloc(buf, len);
++ rlen = recv(ctxt->pam_sock, buf, len, MSG_PEEK);
++ if (rlen < 1) {
++ xfree(buf);
++ return (NULL);
++ }
++ } while (rlen == len);
++ if (recv(ctxt->pam_sock, buf, len, 0) != rlen) {
++ xfree(buf);
++ return (NULL);
++ }
++ if (ctxt->pam_pid != 0)
++ debug2("from child: %s", buf);
++ return (buf);
++}
++
++/*
++ * Conversation function for child process.
++ */
++static int
++pam_child_conv(int n,
++ const struct pam_message **msg,
++ struct pam_response **resp,
++ void *data)
++{
++ struct pam_ctxt *ctxt;
++ int i;
++
++ ctxt = data;
++ if (n <= 0 || n > PAM_MAX_NUM_MSG)
++ return (PAM_CONV_ERR);
++ if ((*resp = calloc(n, sizeof **resp)) == NULL)
++ return (PAM_BUF_ERR);
++ for (i = 0; i < n; ++i) {
++ resp[i]->resp_retcode = 0;
++ resp[i]->resp = NULL;
++ switch (msg[i]->msg_style) {
++ case PAM_PROMPT_ECHO_OFF:
++ pam_send(ctxt, "p%s", msg[i]->msg);
++ resp[i]->resp = pam_receive(ctxt);
++ break;
++ case PAM_PROMPT_ECHO_ON:
++ pam_send(ctxt, "P%s", msg[i]->msg);
++ resp[i]->resp = pam_receive(ctxt);
++ break;
++ case PAM_ERROR_MSG:
++ /*pam_send(ctxt, "e%s", msg[i]->msg);*/
++ break;
++ case PAM_TEXT_INFO:
++ /*pam_send(ctxt, "i%s", msg[i]->msg);*/
++ break;
++ default:
++ goto fail;
++ }
++ }
++ return (PAM_SUCCESS);
++ fail:
++ while (i)
++ free(resp[--i]);
++ free(*resp);
++ *resp = NULL;
++ return (PAM_CONV_ERR);
++}
++
++/*
++ * Child process.
++ */
++static void *
++pam_child(struct pam_ctxt *ctxt)
++{
++ struct pam_conv pam_conv = { pam_child_conv, ctxt };
++ pam_handle_t *pamh;
++ int pam_err;
++
++ pam_err = pam_start("sshd", ctxt->pam_user, &pam_conv, &pamh);
++ if (pam_err != PAM_SUCCESS)
++ goto auth_fail;
++ pam_err = pam_authenticate(pamh, 0);
++ if (pam_err != PAM_SUCCESS)
++ goto auth_fail;
++ pam_send(ctxt, "=OK");
++ pam_end(pamh, pam_err);
++ exit(0);
++ auth_fail:
++ pam_send(ctxt, "!%s", pam_strerror(pamh, pam_err));
++ pam_end(pamh, pam_err);
++ exit(0);
++}
++
++static void *
++pam_init_ctx(Authctxt *authctxt)
++{
++ struct pam_ctxt *ctxt;
++ int socks[2];
++ int i;
++
++ ctxt = xmalloc(sizeof *ctxt);
++ ctxt->pam_user = xstrdup(authctxt->user);
++ ctxt->pam_done = 0;
++ if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, socks) == -1) {
++ error("%s: failed create sockets: %s",
++ __func__, strerror(errno));
++ xfree(ctxt);
++ return (NULL);
++ }
++ if ((ctxt->pam_pid = fork()) == -1) {
++ error("%s: failed to fork auth-pam child: %s",
++ __func__, strerror(errno));
++ close(socks[0]);
++ close(socks[1]);
++ xfree(ctxt);
++ return (NULL);
++ }
++ if (ctxt->pam_pid == 0) {
++ /* close everything except our end of the pipe */
++ ctxt->pam_sock = socks[1];
++ for (i = 0; i < getdtablesize(); ++i)
++ if (i != ctxt->pam_sock)
++ close(i);
++ pam_child(ctxt);
++ /* not reached */
++ exit(1);
++ }
++ ctxt->pam_sock = socks[0];
++ close(socks[1]);
++ return (ctxt);
++}
++
++static int
++pam_query(void *ctx, char **name, char **info,
++ u_int *num, char ***prompts, u_int **echo_on)
++{
++ struct pam_ctxt *ctxt = ctx;
++ char *msg;
++
++ if ((msg = pam_receive(ctxt)) == NULL)
++ return (-1);
++ *name = xstrdup("");
++ *info = xstrdup("");
++ *prompts = xmalloc(sizeof(char *));
++ *echo_on = xmalloc(sizeof(u_int));
++ switch (*msg) {
++ case 'P':
++ **echo_on = 1;
++ case 'p':
++ *num = 1;
++ **prompts = xstrdup(msg + 1);
++ **echo_on = (*msg == 'P');
++ break;
++ case '=':
++ *num = 0;
++ **echo_on = 0;
++ ctxt->pam_done = 1;
++ break;
++ case '!':
++ error("%s", msg + 1);
++ default:
++ *num = 0;
++ **echo_on = 0;
++ xfree(msg);
++ ctxt->pam_done = -1;
++ return (-1);
++ }
++ xfree(msg);
++ return (0);
++}
++
++static int
++pam_respond(void *ctx, u_int num, char **resp)
++{
++ struct pam_ctxt *ctxt = ctx;
++ char *msg;
++
++ debug2(__func__);
++ switch (ctxt->pam_done) {
++ case 1:
++ return (0);
++ case 0:
++ break;
++ default:
++ return (-1);
++ }
++ if (num != 1) {
++ error("expected one response, got %u", num);
++ return (-1);
++ }
++ pam_send(ctxt, "%s", *resp);
++ switch (pam_peek(ctxt)) {
++ case 'P':
++ case 'p':
++ return (1);
++ case '=':
++ msg = pam_receive(ctxt);
++ xfree(msg);
++ ctxt->pam_done = 1;
++ return (0);
++ default:
++ msg = pam_receive(ctxt);
++ if (*msg == '!')
++ error("%s", msg + 1);
++ xfree(msg);
++ ctxt->pam_done = -1;
++ return (-1);
++ }
++}
++
++static void
++pam_free_ctx(void *ctxtp)
++{
++ struct pam_ctxt *ctxt = ctxtp;
++ int status;
++
++ close(ctxt->pam_sock);
++ kill(ctxt->pam_pid, SIGHUP);
++ waitpid(ctxt->pam_pid, &status, 0);
++ xfree(ctxt->pam_user);
++ xfree(ctxt);
++}
++
++KbdintDevice pam_device = {
++ "pam",
++ pam_init_ctx,
++ pam_query,
++ pam_respond,
++ pam_free_ctx
++};
++
++#endif /* USE_PAM */
diff --git a/security/openssh/files/patch-auth2-passwd.c b/security/openssh/files/patch-auth2-passwd.c
deleted file mode 100644
index da16a83e48f2..000000000000
--- a/security/openssh/files/patch-auth2-passwd.c
+++ /dev/null
@@ -1,14 +0,0 @@
---- auth2-passwd.c.orig Fri May 31 13:35:15 2002
-+++ auth2-passwd.c Fri Jun 21 22:54:05 2002
-@@ -48,7 +48,11 @@
- password = packet_get_string(&len);
- packet_check_eom();
- if (authctxt->valid &&
-+#ifdef USE_PAM
-+ PRIVSEP(auth_pam_password(authctxt, password)) == 1)
-+#else
- PRIVSEP(auth_password(authctxt, password)) == 1)
-+#endif
- authenticated = 1;
- memset(password, 0, len);
- xfree(password);
diff --git a/security/openssh/files/patch-auth2.c b/security/openssh/files/patch-auth2.c
index 23683cd1f3a2..6eb5ce175346 100644
--- a/security/openssh/files/patch-auth2.c
+++ b/security/openssh/files/patch-auth2.c
@@ -1,5 +1,5 @@
--- auth2.c.orig Fri May 31 13:35:15 2002
-+++ auth2.c Fri Jun 21 22:49:07 2002
++++ auth2.c Mon Jun 24 07:02:04 2002
@@ -133,6 +133,15 @@
Authmethod *m = NULL;
char *user, *service, *method, *style = NULL;
@@ -16,19 +16,22 @@
if (authctxt == NULL)
fatal("input_userauth_request: no authctxt");
-@@ -152,6 +161,11 @@
+@@ -152,8 +161,14 @@
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
+
+#ifdef USE_PAM
-+ start_pam(pw);
++ start_pam(authctxt->pw);
+#endif
+
} else {
log("input_userauth_request: illegal user %s", user);
++ authctxt->pw = NULL;
}
-@@ -168,6 +182,41 @@
+ setproctitle("%s%s", authctxt->pw ? user : "unknown",
+ use_privsep ? " [net]" : "");
+@@ -168,6 +183,41 @@
"(%s,%s) -> (%s,%s)",
authctxt->user, authctxt->service, user, service);
}
@@ -70,7 +73,7 @@
/* reset state */
auth2_challenge_stop(authctxt);
authctxt->postponed = 0;
-@@ -178,6 +227,12 @@
+@@ -178,6 +228,12 @@
debug2("input_userauth_request: try method %s", method);
authenticated = m->userauth(authctxt);
}
diff --git a/security/openssh/files/patch-key.c b/security/openssh/files/patch-key.c
new file mode 100644
index 000000000000..27d8a2ac3f8f
--- /dev/null
+++ b/security/openssh/files/patch-key.c
@@ -0,0 +1,11 @@
+--- key.c Mon Jun 24 20:46:53 2002
++++ key.c.orig Fri May 31 15:16:48 2002
+@@ -368,7 +368,7 @@
+ return 0;
+ }
+ fprintf(f, " %s", buf);
+- free(buf);
++ OPENSSL_free(buf);
+ return 1;
+ }
+
diff --git a/security/openssh/files/patch-misc.c b/security/openssh/files/patch-misc.c
deleted file mode 100644
index 0f8ef065fec0..000000000000
--- a/security/openssh/files/patch-misc.c
+++ /dev/null
@@ -1,13 +0,0 @@
---- misc.c.orig Thu Apr 12 22:09:37 2001
-+++ misc.c Sat May 26 15:39:25 2001
-@@ -111,6 +111,10 @@
- copy->pw_class = xstrdup(pw->pw_class);
- copy->pw_dir = xstrdup(pw->pw_dir);
- copy->pw_shell = xstrdup(pw->pw_shell);
-+#ifdef __FreeBSD__
-+ copy->pw_expire = pw->pw_expire;
-+ copy->pw_change = pw->pw_change;
-+#endif /* __FreeBSD__ */
- return copy;
- }
-
diff --git a/security/openssh/files/patch-monitor.c b/security/openssh/files/patch-monitor.c
new file mode 100644
index 000000000000..fc0f1911ddda
--- /dev/null
+++ b/security/openssh/files/patch-monitor.c
@@ -0,0 +1,36 @@
+--- monitor.c.orig Fri Jun 21 07:50:51 2002
++++ monitor.c Mon Jun 24 20:39:42 2002
+@@ -30,7 +30,7 @@
+ #include <openssl/dh.h>
+
+ #ifdef SKEY
+-#include <skey.h>
++#include <opie.h>
+ #endif
+
+ #include "ssh.h"
+@@ -656,11 +656,11 @@
+ int
+ mm_answer_skeyquery(int socket, Buffer *m)
+ {
+- struct skey skey;
++ struct opie opie;
+ char challenge[1024];
+ int res;
+
+- res = skeychallenge(&skey, authctxt->user, challenge);
++ res = opiechallenge(&opie, authctxt->user, challenge);
+
+ buffer_clear(m);
+ buffer_put_int(m, res);
+@@ -683,8 +683,8 @@
+
+ authok = (options.challenge_response_authentication &&
+ authctxt->valid &&
+- skey_haskey(authctxt->pw->pw_name) == 0 &&
+- skey_passcheck(authctxt->pw->pw_name, response) != -1);
++ opie_haskey(authctxt->pw->pw_name) == 0 &&
++ opie_passverify(authctxt->pw->pw_name, response) != -1);
+
+ xfree(response);
+
diff --git a/security/openssh/files/patch-pathnames.h b/security/openssh/files/patch-pathnames.h
index 0eb763623833..b8f4e585db5e 100644
--- a/security/openssh/files/patch-pathnames.h
+++ b/security/openssh/files/patch-pathnames.h
@@ -1,11 +1,11 @@
---- pathnames.h.orig Fri Mar 8 05:51:08 2002
-+++ pathnames.h Fri Mar 8 05:52:57 2002
+--- pathnames.h.orig Sat Jun 22 12:40:30 2002
++++ pathnames.h Mon Jun 24 23:05:59 2002
@@ -12,7 +12,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-#define ETCDIR "/etc"
-+#define ETCDIR "__PREFIX__/etc"
++#define ETCDIR "__PREFIX__/etc/ssh"
#define SSHDIR ETCDIR
#define _PATH_SSH_PIDDIR "/var/run"
@@ -18,3 +18,14 @@
/*
* The process id of the daemon listening for connections is saved here to
+@@ -123,8 +123,8 @@
+ #define _PATH_CP "cp"
+
+ /* for sftp */
+-#define _PATH_SFTP_SERVER "/usr/libexec/sftp-server"
++#define _PATH_SFTP_SERVER "__PREFIX__/libexec/sftp-server"
+ #define _PATH_LS "ls"
+
+ /* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */
+-#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"
++#define _PATH_PRIVSEP_CHROOT_DIR "__PREFIX__/empty"
diff --git a/security/openssh/files/patch-sshd_config b/security/openssh/files/patch-sshd_config
index 514a9fd7336a..d650766c0293 100644
--- a/security/openssh/files/patch-sshd_config
+++ b/security/openssh/files/patch-sshd_config
@@ -1,23 +1,12 @@
---- sshd_config.orig Fri Jun 21 23:07:45 2002
-+++ sshd_config Fri Jun 21 23:08:26 2002
-@@ -30,8 +30,10 @@
-
- # Authentication:
-
--#LoginGraceTime 600
--#PermitRootLogin yes
-+#LoginGraceTime 300
-+LoginGraceTime 600
-+#PermitRootLogin no
-+PermitRootLogin yes
- #StrictModes yes
-
- #RSAAuthentication yes
-@@ -74,6 +76,7 @@
+--- sshd_config Mon Jun 24 20:56:50 2002
++++ sshd_config.orig Sat Jun 22 12:40:35 2002
+@@ -74,7 +76,9 @@
#PrintLastLog yes
#KeepAlive yes
#UseLogin no
+UseLogin yes
#UsePrivilegeSeparation yes
++UsePrivilegeSeparation no
#Compression yes
+ #MaxStartups 10
diff --git a/security/openssh/pkg-plist b/security/openssh/pkg-plist
index 317a71167115..49bdec074f00 100644
--- a/security/openssh/pkg-plist
+++ b/security/openssh/pkg-plist
@@ -7,19 +7,29 @@ bin/ssh-agent
bin/ssh-keygen
bin/ssh-keyscan
etc/rc.d/sshd.sh.sample
-etc/moduli
-@unexec if cmp -s %D/etc/ssh_config %D/etc/ssh_config-dist; then rm -f %D/etc/ssh_config; fi
-@unexec if cmp -s %D/etc/sshd_config %D/etc/sshd_config-dist; then rm -f %D/etc/sshd_config; fi
-etc/ssh_config-dist
-etc/sshd_config-dist
-@exec [ ! -f %D/etc/ssh_config ] && cp %D/etc/ssh_config-dist %D/etc/ssh_config
-@exec [ ! -f %D/etc/sshd_config ] && cp %D/etc/sshd_config-dist %D/etc/sshd_config
+etc/ssh/moduli
+@exec [ -f %D/etc/ssh_config ] && [ ! -f %D/etc/ssh/ssh_config ] && ln %D/etc/ssh_config %D/etc/ssh/ssh_config
+@exec [ -f %D/etc/sshd_config ] && [ ! -f %D/etc/ssh/sshd_config ] && ln %D/etc/sshd_config %D/etc/ssh/sshd_config
+@exec [ -f %D/etc/ssh_host_key ] && [ ! -f %D/etc/ssh/ssh_host_key ] && ln %D/etc/ssh_host_key %D/etc/ssh/ssh_host_key
+@exec [ -f %D/etc/ssh_host_key.pub ] && [ ! -f %D/etc/ssh/ssh_host_key.pub ] && ln %D/etc/ssh_host_key.pub %D/etc/ssh/ssh_host_key.pub
+@exec [ -f %D/etc/ssh_host_rsa_key ] && [ ! -f %D/etc/ssh/ssh_host_rsa_key ] && ln %D/etc/ssh_host_rsa_key %D/etc/ssh/ssh_host_rsa_key
+@exec [ -f %D/etc/ssh_host_rsa_key.pub ] && [ ! -f %D/etc/ssh/ssh_host_rsa_key.pub ] && ln %D/etc/ssh_host_rsa_key.pub %D/etc/ssh/ssh_host_rsa_key.pub
+@exec [ -f %D/etc/ssh_host_dsa_key ] && [ ! -f %D/etc/ssh/ssh_host_dsa_key ] && ln %D/etc/ssh_host_dsa_key %D/etc/ssh/ssh_host_dsa_key
+@exec [ -f %D/etc/ssh_host_dsa_key.pub ] && [ ! -f %D/etc/ssh/ssh_host_dsa_key.pub ] && ln %D/etc/ssh_host_dsa_key.pub %D/etc/ssh/ssh_host_dsa_key.pub
+@unexec if cmp -s %D/etc/ssh/ssh_config %D/etc/ssh/ssh_config-dist; then rm -f %D/etc/ssh/ssh_config; fi
+@unexec if cmp -s %D/etc/ssh/sshd_config %D/etc/ssh/sshd_config-dist; then rm -f %D/etc/ssh/sshd_config; fi
+etc/ssh/ssh_config-dist
+etc/ssh/sshd_config-dist
+@exec [ ! -f %D/etc/ssh/ssh_config ] && cp %D/etc/ssh/ssh_config-dist %D/etc/ssh/ssh_config
+@exec [ ! -f %D/etc/ssh/sshd_config ] && cp %D/etc/ssh/sshd_config-dist %D/etc/ssh/sshd_config
sbin/sshd
+@dirrm etc/ssh
libexec/sftp-server
libexec/ssh-keysign
libdata/ssh/Ssh.bin
@dirrm libdata/ssh
-@exec if [ ! -f %D/etc/ssh_host_key ]; then echo ">> Generating a secret RSA1 host key."; %D/bin/ssh-keygen -t rsa1 -N "" -f %D/etc/ssh_host_key; fi
-@exec if [ ! -f %D/etc/ssh_host_rsa_key ]; then echo ">> Generating a secret RSA host key."; %D/bin/ssh-keygen -t rsa -N "" -f %D/etc/ssh_host_rsa_key; fi
-@exec if [ ! -f %D/etc/ssh_host_dsa_key ]; then echo ">> Generating a secret DSA host key."; %D/bin/ssh-keygen -t dsa -N "" -f %D/etc/ssh_host_dsa_key; fi
-@exec if [ ! -x %D/etc/rc.d/sshd.sh ]; then echo "#!/bin/sh" > %D/etc/rc.d/sshd.sh && exec echo "[ -x %D/sbin/sshd ] && %D/sbin/sshd && echo -n ' sshd'" >> %D/etc/rc.d/sshd.sh && exec chmod 0555 %D/etc/rc.d/sshd.sh; fi
+@exec mkdir -p %D/empty
+@dirrm empty
+@exec if [ ! -f %D/etc/ssh/ssh_host_key ]; then echo ">> Generating a secret RSA1 host key."; %D/bin/ssh-keygen -t rsa1 -N "" -f %D/etc/ssh/ssh_host_key; fi
+@exec if [ ! -f %D/etc/ssh/ssh_host_rsa_key ]; then echo ">> Generating a secret RSA host key."; %D/bin/ssh-keygen -t rsa -N "" -f %D/etc/ssh/ssh_host_rsa_key; fi
+@exec if [ ! -f %D/etc/ssh/ssh_host_dsa_key ]; then echo ">> Generating a secret DSA host key."; %D/bin/ssh-keygen -t dsa -N "" -f %D/etc/ssh/ssh_host_dsa_key; fi