Marcel Telka
2024-03-11 8054375a2bc887e1a9097f4690f81f91897ece3e
Add HPN-SSH

27 files added
1 files modified
4007 ■■■■■ changed files
components/network/hpn-ssh/Makefile 110 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/files/hpnssh.xml 179 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/files/hpnsshd 63 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/hpn-ssh-service.p5m 64 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/hpn-ssh.p5m 56 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/manifests/sample-manifest.p5m 60 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0001-Skip-config-check.patch 28 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0002-PAM-Support.patch 59 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0003-lastlogin.patch 23 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0006-GSS-store-creds-for-Solaris.patch 160 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0007-DTrace-support-for-SFTP.patch 353 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0008-Add-DisableBanner-option.patch 161 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0009-PAM-conversation-fix.patch 84 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0010-PAM-enhancements-for-Solaris.patch 615 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0013-Solaris-Auditing-support.patch 762 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0015-Enable-login-to-a-role-if-PAM-is-ok-with-it.patch 135 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0016-PAM-setcred-failures.patch 39 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0017-Don-t-call-do_pam_setcred-twice.patch 33 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0018-Per-session-xauthfile.patch 229 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0019-PubKeyPlugin-support.patch 239 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0027-Set-default-sshd-options-based-on-etc-default-login.patch 128 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0028-Compatibility-for-SunSSH_1.5-should-include-old-DH-K.patch 73 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0029-Accept-LANG-and-LC_-environment-variables-from-clien.patch 155 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/0031-Restore-tcpwrappers-libwrap-support.patch 141 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/1002-ssh-copy-id-use-correct-shell.patch 8 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/patches/2000-sshd_config-default.patch 28 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/pkg5 20 ●●●●● patch | view | raw | blame | history
doc/reserved_uids_and_gids.md 2 ●●●●● patch | view | raw | blame | history
components/network/hpn-ssh/Makefile
New file
@@ -0,0 +1,110 @@
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright 2018 Till Wegmüller
# Copyright 2019 Michal Nowak
#
include ../../../make-rules/shared-macros.mk
COMPONENT_NAME=        hpn-ssh
COMPONENT_VERSION=    18.3.1
COMPONENT_SUMMARY=    High performance SSH/SCP
COMPONENT_SRC=        $(COMPONENT_NAME)-hpn-$(HUMAN_VERSION)
COMPONENT_PROJECT_URL=    https://www.psc.edu/hpn-ssh-home/
COMPONENT_ARCHIVE=    $(COMPONENT_SRC).tar.gz
COMPONENT_ARCHIVE_HASH=    sha256:7165ecef8ae008aff8e317a5f0d2f546e56d5173ae82a51fa75525dcba67d48f
COMPONENT_ARCHIVE_URL=    https://github.com/rapier1/hpn-ssh/archive/refs/tags/hpn-$(HUMAN_VERSION).tar.gz
COMPONENT_FMRI=        network/hpn-ssh
COMPONENT_LICENSE=    BSD, BSD-like
COMPONENT_LICENSE_FILE=    LICENCE
COMPONENT_SUMMARY.$(COMPONENT_NAME)=        $(COMPONENT_SUMMARY) - client and utilities
COMPONENT_FMRI.$(COMPONENT_NAME)-service=    service/$(COMPONENT_FMRI)
COMPONENT_SUMMARY.$(COMPONENT_NAME)-service=    $(COMPONENT_SUMMARY) - servers and services
TEST_TARGET= $(SKIP_TEST)
include $(WS_MAKE_RULES)/common.mk
COMPONENT_PREP_ACTION = ( cd $(@D) ; autoreconf -f -i )
# Enable various fixes and enhancements implemented by patches
CFLAGS += -DSET_USE_PAM
CFLAGS += -DPAM_ENHANCEMENT
CFLAGS += -DPAM_BUGFIX
CFLAGS += -DDTRACE_SFTP
CFLAGS += -DDISABLE_BANNER
CFLAGS += -DDEPRECATE_SUNSSH_OPT
CFLAGS += -DPER_SESSION_XAUTHFILE
# configure is unable to find OpenSSL headers without this workaround
CFLAGS += -I$(OPENSSL_INCDIR)
# We need to disable lazyloading of dynamic dependent libraries. During the
# pre-authentication phase, hpnsshd will chroot to /var/empty which doesn't
# contain any files. If we use lazyloading, hpnsshd will fail to find any
# libraries that it needs.
LDFLAGS += -B direct -z nolazyload
# configure is unable to find OpenSSL libraries by default so we need to pass
# OPENSSL_LIBDIR to --with-ssl-dir as a workaround
CONFIGURE_OPTIONS += --with-ssl-dir=$(OPENSSL_LIBDIR)
CONFIGURE_OPTIONS += --with-ssl-engine
CONFIGURE_OPTIONS += --with-audit=solaris
CONFIGURE_OPTIONS += --with-libedit
CONFIGURE_OPTIONS += --with-kerberos5
CONFIGURE_OPTIONS += --with-pam
CONFIGURE_OPTIONS += --with-sandbox=solaris
CONFIGURE_OPTIONS += --with-solaris-contracts
CONFIGURE_OPTIONS += --with-solaris-privs
CONFIGURE_OPTIONS += --with-solaris-projects
CONFIGURE_OPTIONS += --with-tcp-wrappers
CONFIGURE_OPTIONS += --with-4in6
CONFIGURE_OPTIONS += --with-xauth=/usr/bin/xauth
CONFIGURE_OPTIONS += --enable-strip=no
CONFIGURE_OPTIONS += --without-rpath
CONFIGURE_OPTIONS += --disable-lastlog
CONFIGURE_OPTIONS += --sysconfdir=$(ETCDIR)
# Install hpnssh-copy-id and its man page
COMPONENT_POST_INSTALL_ACTION += $(INSTALL) -Dm755 $(SOURCE_DIR)/contrib/hpnssh-copy-id $(PROTOUSRBINDIR)/hpnssh-copy-id ;
COMPONENT_POST_INSTALL_ACTION += $(INSTALL) -Dm644 $(SOURCE_DIR)/contrib/hpnssh-copy-id.1 $(PROTOUSRSHAREMAN1DIR)/hpnssh-copy-id.1 ;
# Install the service related files
COMPONENT_POST_INSTALL_ACTION += $(INSTALL) -Dm0444 $(COMPONENT_DIR)/files/hpnssh.xml $(PROTO_DIR)/lib/svc/manifest/network/hpnssh.xml ;
COMPONENT_POST_INSTALL_ACTION += $(INSTALL) -Dm0555 $(COMPONENT_DIR)/files/hpnsshd $(PROTO_DIR)/lib/svc/method/hpnsshd ;
COMPONENT_TEST_TARGETS = tests
# Auto-generated dependencies
REQUIRED_PACKAGES += SUNWcs
REQUIRED_PACKAGES += library/libedit
REQUIRED_PACKAGES += library/security/openssl-31
REQUIRED_PACKAGES += library/zlib
REQUIRED_PACKAGES += network/ssh-askpass
REQUIRED_PACKAGES += service/security/kerberos-5
REQUIRED_PACKAGES += shell/bash
REQUIRED_PACKAGES += shell/ksh93
REQUIRED_PACKAGES += system/library
REQUIRED_PACKAGES += system/library/security/gss
REQUIRED_PACKAGES += x11/session/xauth
components/network/hpn-ssh/files/hpnssh.xml
New file
@@ -0,0 +1,179 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!--
    CDDL HEADER START
    The contents of this file are subject to the terms of the
    Common Development and Distribution License (the "License").
    You may not use this file except in compliance with the License.
    You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    or http://www.opensolaris.org/os/licensing.
    See the License for the specific language governing permissions
    and limitations under the License.
    When distributing Covered Code, include this CDDL HEADER in each
    file and include the License file at usr/src/OPENSOLARIS.LICENSE.
    If applicable, add the following below this CDDL HEADER, with the
    fields enclosed by brackets "[]" replaced with your own identifying
    information: Portions Copyright [yyyy] [name of copyright owner]
    CDDL HEADER END
    Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
    Use is subject to license terms.
    Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
    NOTE:  This service manifest is not editable; its contents will
    be overwritten by package or patch operations, including
    operating system upgrade.  Make customizations in a different
    file.
-->
<service_bundle type='manifest' name='network/hpnssh'>
<service
    name='network/hpnssh'
    type='service'
    version='1'>
    <create_default_instance enabled='false' />
    <single_instance />
    <dependency name='fs-local'
        grouping='require_all'
        restart_on='none'
        type='service'>
        <service_fmri
            value='svc:/system/filesystem/local' />
    </dependency>
    <dependency name='fs-autofs'
        grouping='optional_all'
        restart_on='none'
        type='service'>
        <service_fmri value='svc:/system/filesystem/autofs' />
    </dependency>
    <dependency name='net-loopback'
        grouping='require_all'
        restart_on='none'
        type='service'>
        <service_fmri value='svc:/network/loopback' />
    </dependency>
    <dependency name='net-physical'
        grouping='require_all'
        restart_on='none'
        type='service'>
        <service_fmri value='svc:/network/physical' />
    </dependency>
    <dependency name='cryptosvc'
        grouping='require_all'
        restart_on='none'
        type='service'>
        <service_fmri value='svc:/system/cryptosvc' />
    </dependency>
    <dependency name='utmp'
        grouping='require_all'
        restart_on='none'
        type='service'>
        <service_fmri value='svc:/system/utmp' />
    </dependency>
    <dependency name='network_ipfilter'
        grouping='optional_all'
        restart_on='error'
        type='service'>
        <service_fmri value='svc:/network/ipfilter:default' />
    </dependency>
    <dependency name='config_data'
        grouping='require_all'
        restart_on='restart'
        type='path'>
        <service_fmri
            value='file://localhost/etc/hpnssh/sshd_config' />
    </dependency>
    <dependent
        name='hpnssh_multi-user-server'
        grouping='optional_all'
        restart_on='none'>
            <service_fmri
                value='svc:/milestone/multi-user-server' />
    </dependent>
    <exec_method
        type='method'
        name='start'
        exec='/lib/svc/method/hpnsshd start'
        timeout_seconds='60'>
        <method_context security_flags="current"/>
    </exec_method>
    <exec_method
        type='method'
        name='stop'
        exec=':kill'
        timeout_seconds='60' />
    <exec_method
        type='method'
        name='refresh'
        exec=':kill -HUP'
        timeout_seconds='60' />
    <property_group name='startd'
        type='framework'>
        <!-- sub-process core dumps shouldn't restart session -->
        <propval name='ignore_error'
            type='astring' value='core,signal' />
    </property_group>
        <property_group name='general' type='framework'>
                <!-- to start stop sshd -->
                <propval name='action_authorization' type='astring'
                        value='solaris.smf.manage.ssh' />
        </property_group>
    <property_group name='firewall_context' type='com.sun,fw_definition'>
        <propval name='name' type='astring' value='hpnssh' />
        <propval name='ipf_method' type='astring'
            value='/lib/svc/method/hpnsshd ipfilter' />
    </property_group>
    <property_group name='firewall_config' type='com.sun,fw_configuration'>
        <propval name='policy' type='astring' value='use_global' />
        <propval name='block_policy' type='astring'
            value='use_global' />
        <propval name='apply_to' type='astring' value='' />
        <propval name='apply_to_6' type='astring' value='' />
        <propval name='exceptions' type='astring' value='' />
        <propval name='exceptions_6' type='astring' value='' />
        <propval name='target' type='astring' value='' />
        <propval name='target_6' type='astring' value='' />
        <propval name='value_authorization' type='astring'
            value='solaris.smf.value.firewall.config' />
    </property_group>
    <stability value='Unstable' />
    <template>
        <common_name>
            <loctext xml:lang='C'>
                HPN-SSH server
            </loctext>
        </common_name>
        <documentation>
            <manpage title='hpnsshd' section='8' manpath='/usr/share/man' />
        </documentation>
    </template>
</service>
</service_bundle>
components/network/hpn-ssh/files/hpnsshd
New file
@@ -0,0 +1,63 @@
#!/sbin/sh
#
# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
# Copyright 2023 Klaus Ziegler
#
. /lib/svc/share/ipf_include.sh
. /lib/svc/share/smf_include.sh
SSHDIR=/etc/hpnssh
create_ipf_rules()
{
    FMRI=$1
    ipf_file=`fmri_to_file ${FMRI} $IPF_SUFFIX`
    ipf6_file=`fmri_to_file ${FMRI} $IPF6_SUFFIX`
    policy=`get_policy ${FMRI}`
    #
    # Get port from the sshd_config file
    #
    tports=`grep "^Port" "$SSHDIR/sshd_config" 2>/dev/null | \
        awk '{print $2}'`
    echo "# $FMRI" >$ipf_file
    echo "# $FMRI" >$ipf6_file
    for port in $tports; do
        generate_rules $FMRI $policy "tcp" $port $ipf_file
        generate_rules $FMRI $policy "tcp" $port $ipf6_file _6
    done
}
# This script is being used as part of an SMF
# start/stop/refresh method for HPN-SSH server.
# Note: there is no refresh/restart switch defined,
# because this is done by the SMF restarter property.
#
case $1 in
'ipfilter')
    create_ipf_rules $2
    ;;
'start')
    #
    # If host keys don't exist when the service is started, create them.
    #
    /usr/bin/hpnssh-keygen -A
    /usr/sbin/hpnsshd
    ;;
*)
    echo "Usage: $0 { start | restart }"
    exit 1
    ;;
esac
exit $?
components/network/hpn-ssh/hpn-ssh-service.p5m
New file
@@ -0,0 +1,64 @@
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with # fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
#
<transform file path=usr/sbin/hpnsshd$ -> default restart_fmri svc:/network/hpnssh:default>
<transform file path=usr/libexec/hpnssh-keysign$ -> default mode 4555>
<transform file path=etc/hpnssh/sshd_config$ -> default mode 0644>
<transform file path=etc/hpnssh/sshd_config$ -> default preserve true>
set name=pkg.fmri value=pkg:/$(COMPONENT_FMRI)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
set name=pkg.human-version value=$(HUMAN_VERSION)
set name=pkg.summary value="$(COMPONENT_SUMMARY)"
set name=info.classification \
    value=org.opensolaris.category.2008:Applications/Internet \
    value=org.opensolaris.category.2008:System/Security
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
license $(COMPONENT_LICENSE_FILE) license='$(COMPONENT_LICENSE)'
dir  path=var/empty owner=root group=sys mode=0755 sysattr=readonly
group groupname=hpnsshd gid=24
user username=hpnsshd ftpuser=false gcos-field="hpnsshd privsep" group=hpnsshd \
    home-dir=/var/empty login-shell=/bin/false uid=24
depend type=require fmri=pkg:/network/hpn-ssh
file path=etc/hpnssh/moduli
file path=etc/hpnssh/sshd_config
file path=lib/svc/manifest/network/hpnssh.xml
file path=lib/svc/method/hpnsshd
file path=usr/lib/dtrace/hpnsftp.d
file path=usr/libexec/hpnsftp-server
file path=usr/libexec/hpnssh-keysign
file path=usr/libexec/hpnssh-pkcs11-helper
file path=usr/libexec/hpnssh-sk-helper
file path=usr/sbin/hpnsshd
file path=usr/share/man/man5/hpnmoduli.5
file path=usr/share/man/man5/hpnsshd_config.5
file path=usr/share/man/man8/hpnsftp-server.8
file path=usr/share/man/man8/hpnssh-keysign.8
file path=usr/share/man/man8/hpnssh-pkcs11-helper.8
file path=usr/share/man/man8/hpnssh-sk-helper.8
file path=usr/share/man/man8/hpnsshd.8
components/network/hpn-ssh/hpn-ssh.p5m
New file
@@ -0,0 +1,56 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright 2018 Till Wegmüller
#
# A full copy of the text of the CDDL should have accompanied this
set name=pkg.fmri value=pkg:/$(COMPONENT_FMRI)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
set name=pkg.human-version value=$(HUMAN_VERSION)
set name=pkg.summary value="$(COMPONENT_SUMMARY)"
set name=info.classification \
    value=org.opensolaris.category.2008:Applications/Internet \
    value=org.opensolaris.category.2008:System/Security
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
license $(COMPONENT_LICENSE_FILE) license='$(COMPONENT_LICENSE)'
<transform file path=etc/hpnssh/ssh_config$ -> default preserve true>
<transform file path=etc/hpnssh/ssh_config$ -> default mode 0644>
depend type=conditional fmri=pkg:/x11/session/xauth \
    predicate=pkg:/x11/library/libxau
depend type=conditional fmri=pkg:/network/ssh-askpass \
    predicate=pkg:/x11/server/xserver-common
file path=etc/hpnssh/ssh_config
file path=usr/bin/hpnscp
file path=usr/bin/hpnsftp
file path=usr/bin/hpnssh
file path=usr/bin/hpnssh-add
file path=usr/bin/hpnssh-agent
file path=usr/bin/hpnssh-copy-id
file path=usr/bin/hpnssh-keygen
file path=usr/bin/hpnssh-keyscan
file path=usr/share/man/man1/hpnscp.1
file path=usr/share/man/man1/hpnsftp.1
file path=usr/share/man/man1/hpnssh-add.1
file path=usr/share/man/man1/hpnssh-agent.1
file path=usr/share/man/man1/hpnssh-copy-id.1
file path=usr/share/man/man1/hpnssh-keygen.1
file path=usr/share/man/man1/hpnssh-keyscan.1
file path=usr/share/man/man1/hpnssh.1
file path=usr/share/man/man5/hpnssh_config.5
components/network/hpn-ssh/manifests/sample-manifest.p5m
New file
@@ -0,0 +1,60 @@
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2024 <contributor>
#
set name=pkg.fmri value=pkg:/$(COMPONENT_FMRI)@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
set name=pkg.human-version value=$(HUMAN_VERSION)
set name=pkg.summary value="$(COMPONENT_SUMMARY)"
set name=info.classification value="$(COMPONENT_CLASSIFICATION)"
set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
license $(COMPONENT_LICENSE_FILE) license='$(COMPONENT_LICENSE)'
file path=etc/hpnssh/moduli
file path=etc/hpnssh/ssh_config
file path=etc/hpnssh/sshd_config
file path=lib/svc/manifest/network/hpnssh.xml
file path=lib/svc/method/hpnsshd
file path=usr/bin/hpnscp
file path=usr/bin/hpnsftp
file path=usr/bin/hpnssh
file path=usr/bin/hpnssh-add
file path=usr/bin/hpnssh-agent
file path=usr/bin/hpnssh-copy-id
file path=usr/bin/hpnssh-keygen
file path=usr/bin/hpnssh-keyscan
file path=usr/lib/dtrace/hpnsftp.d
file path=usr/libexec/hpnsftp-server
file path=usr/libexec/hpnssh-keysign
file path=usr/libexec/hpnssh-pkcs11-helper
file path=usr/libexec/hpnssh-sk-helper
file path=usr/sbin/hpnsshd
file path=usr/share/man/man1/hpnscp.1
file path=usr/share/man/man1/hpnsftp.1
file path=usr/share/man/man1/hpnssh-add.1
file path=usr/share/man/man1/hpnssh-agent.1
file path=usr/share/man/man1/hpnssh-copy-id.1
file path=usr/share/man/man1/hpnssh-keygen.1
file path=usr/share/man/man1/hpnssh-keyscan.1
file path=usr/share/man/man1/hpnssh.1
file path=usr/share/man/man5/hpnmoduli.5
file path=usr/share/man/man5/hpnssh_config.5
file path=usr/share/man/man5/hpnsshd_config.5
file path=usr/share/man/man8/hpnsftp-server.8
file path=usr/share/man/man8/hpnssh-keysign.8
file path=usr/share/man/man8/hpnssh-pkcs11-helper.8
file path=usr/share/man/man8/hpnssh-sk-helper.8
file path=usr/share/man/man8/hpnsshd.8
components/network/hpn-ssh/patches/0001-Skip-config-check.patch
New file
@@ -0,0 +1,28 @@
#
# This change is to remove some misleading error messages when running
# "gmake install". OpenSSH mixes the building and running together. Some
# system setup checking for running the program needs to be removed, because
# they are not suitable in a build system.  This is for OpenIndiana only, so we
# will not contribute back this change to the upstream community.
#
--- hpn-ssh-hpn-18.3.1/Makefile.in.orig
+++ hpn-ssh-hpn-18.3.1/Makefile.in
@@ -424,7 +424,16 @@
 install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files
 check-config:
-    -$(DESTDIR)$(sbindir)/hpnsshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
+# On OpenIndiana, to workaround OpenSSH's unlucky mixing of 'building ssh' and
+# 'running ssh', on build machine the following requisites shouldn't be
+# enforced:
+#     1) existence of privsep user hpnsshd
+#     2) existence of privsep directory /var/empty
+#     3) read permissions for /etc/hpnssh/ssh_host_[rsa,dsa]_key
+#
+#    -$(DESTDIR)$(sbindir)/hpnsshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
+#
+    @echo 'OpenIndiana: skipping check-config'
 install-files:
     $(MKDIR_P) $(DESTDIR)$(bindir)
components/network/hpn-ssh/patches/0002-PAM-Support.patch
New file
@@ -0,0 +1,59 @@
#
# To comply to the Solaris PAM policy, the UsePAM option is changed to be
# always on and not configurable on Solaris.  This is for Solaris only, so we
# will not contribute the changes to the upstream community.
#
--- hpn-ssh-hpn-18.3.1/servconf.c.orig
+++ hpn-ssh-hpn-18.3.1/servconf.c
@@ -285,7 +285,12 @@
     /* Portable-specific options */
     if (options->use_pam == -1)
+#ifdef SET_USE_PAM
+        /* use_pam should be always set to 1 on Solaris */
+        options->use_pam = 1;
+#else
         options->use_pam = 0;
+#endif
     /* Standard Options */
     if (options->num_host_key_files == 0) {
@@ -1392,8 +1397,17 @@
     switch (opcode) {
     /* Portable-specific options */
     case sUsePAM:
+#ifdef SET_USE_PAM
+        /* UsePAM is always on and not configurable on Solaris */
+        logit("%s line %d: ignoring UsePAM option value."
+            " This option is always on.", filename, linenum);
+        while (arg)
+            arg = strdelim(&str);
+        break;
+#else
         intptr = &options->use_pam;
         goto parse_flag;
+#endif
     /* Standard Options */
     case sBadOption:
--- hpn-ssh-hpn-18.3.1/sshd_config.orig
+++ hpn-ssh-hpn-18.3.1/sshd_config
@@ -70,17 +70,6 @@
 #GSSAPIAuthentication no
 #GSSAPICleanupCredentials yes
-# Set this to 'yes' to enable PAM authentication, account processing,
-# and session processing. If this is enabled, PAM authentication will
-# be allowed through the KbdInteractiveAuthentication and
-# PasswordAuthentication.  Depending on your PAM configuration,
-# PAM authentication via KbdInteractiveAuthentication may bypass
-# the setting of "PermitRootLogin prohibit-password".
-# If you just want the PAM account and session checks to run without
-# PAM authentication, then enable this but set PasswordAuthentication
-# and KbdInteractiveAuthentication to 'no'.
-#UsePAM no
-
 #AllowAgentForwarding yes
 #AllowTcpForwarding yes
 #GatewayPorts no
components/network/hpn-ssh/patches/0003-lastlogin.patch
New file
@@ -0,0 +1,23 @@
--- hpn-ssh-hpn-18.3.1/hpnsshd_config.5.orig
+++ hpn-ssh-hpn-18.3.1/hpnsshd_config.5
@@ -1610,8 +1610,8 @@
 .Xr sshd 8
 should print the date and time of the last user login when a user logs
 in interactively.
-The default is
-.Cm yes .
+On OpenIndiana this option is always ignored since pam_unix_session(7)
+reports the last login time.
 .It Cm PrintMotd
 Specifies whether
 .Xr sshd 8
@@ -2127,7 +2127,8 @@
 .El
 .Sh SEE ALSO
 .Xr sftp-server 8 ,
-.Xr sshd 8
+.Xr sshd 8 ,
+.Xr pam_unix_session 7
 .Sh AUTHORS
 .An -nosplit
 OpenSSH is a derivative of the original and free
components/network/hpn-ssh/patches/0006-GSS-store-creds-for-Solaris.patch
New file
@@ -0,0 +1,160 @@
--- hpn-ssh-hpn-18.3.1/configure.ac.orig
+++ hpn-ssh-hpn-18.3.1/configure.ac
@@ -1161,6 +1161,9 @@
         ],
     )
     TEST_SHELL=$SHELL    # let configure find us a capable shell
+    AC_DEFINE([USE_GSS_STORE_CRED], [1], [Use the Solaris-style GSS cred store])
+    AC_DEFINE([GSSAPI_STORECREDS_NEEDS_RUID], [1], [GSSAPI storecreds needs ruid])
+    AC_DEFINE([HAVE_PAM_AUSER], [1], [pam_auser])
     ;;
 *-*-sunos4*)
     CPPFLAGS="$CPPFLAGS -DSUNOS4"
--- hpn-ssh-hpn-18.3.1/gss-serv-krb5.c.orig
+++ hpn-ssh-hpn-18.3.1/gss-serv-krb5.c
@@ -109,7 +109,7 @@
     return retval;
 }
-
+#ifndef USE_GSS_STORE_CRED
 /* This writes out any forwarded credentials from the structure populated
  * during userauth. Called after we have setuid to the user */
@@ -195,6 +195,7 @@
     return;
 }
+#endif /* #ifndef USE_GSS_STORE_CRED */
 ssh_gssapi_mech gssapi_kerberos_mech = {
     "toWM5Slw5Ew8Mqkay+al2g==",
@@ -203,7 +204,11 @@
     NULL,
     &ssh_gssapi_krb5_userok,
     NULL,
+#ifdef USE_GSS_STORE_CRED
+    NULL
+#else
     &ssh_gssapi_krb5_storecreds
+#endif
 };
 #endif /* KRB5 */
--- hpn-ssh-hpn-18.3.1/gss-serv.c.orig
+++ hpn-ssh-hpn-18.3.1/gss-serv.c
@@ -44,6 +44,7 @@
 #include "session.h"
 #include "misc.h"
 #include "servconf.h"
+#include "sshbuf.h"
 #include "ssh-gss.h"
@@ -319,22 +320,66 @@
 void
 ssh_gssapi_cleanup_creds(void)
 {
+#ifdef USE_GSS_STORE_CRED
+    debug("removing gssapi cred file not implemented");
+#else
     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);
     }
+#endif /* USE_GSS_STORE_CRED */
 }
 /* As user */
 void
 ssh_gssapi_storecreds(void)
 {
+#ifdef USE_GSS_STORE_CRED
+    OM_uint32 maj_status, min_status;
+
+    if (gssapi_client.creds == NULL) {
+        debug("No credentials stored");
+        return;
+    }
+
+    maj_status = gss_store_cred(&min_status, gssapi_client.creds,
+        GSS_C_INITIATE, &gssapi_client.mech->oid, 1, 1, NULL, NULL);
+
+    if (GSS_ERROR(maj_status)) {
+        struct sshbuf *b;
+        gss_buffer_desc msg;
+        OM_uint32 lmin;
+        OM_uint32 more = 0;
+        if ((b = sshbuf_new()) == NULL) fatal("malloc");
+        /* GSS-API error */
+        do {
+            gss_display_status(&lmin, maj_status, GSS_C_GSS_CODE,
+                GSS_C_NULL_OID, &more, &msg);
+            sshbuf_put(b, msg.value, msg.length);
+            sshbuf_put(b, "\n", 1);
+            gss_release_buffer(&lmin, &msg);
+        } while (more != 0);
+        /* Mechanism specific error */
+        do {
+            gss_display_status(&lmin, min_status, GSS_C_MECH_CODE,
+                &gssapi_client.mech->oid, &more, &msg);
+            sshbuf_put(b, msg.value, msg.length);
+            sshbuf_put(b, "\n", 1);
+            gss_release_buffer(&lmin, &msg);
+        } while (more != 0);
+        sshbuf_put(b, "\0", 1);
+        error("GSS-API error while storing delegated credentials: %s",
+            sshbuf_ptr(b));
+        sshbuf_free(b);
+    }
+#else    /* #ifdef USE_GSS_STORE_CRED */
     if (gssapi_client.mech && gssapi_client.mech->storecreds) {
         (*gssapi_client.mech->storecreds)(&gssapi_client);
     } else
         debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
+#endif    /* #ifdef USE_GSS_STORE_CRED */
 }
 /* This allows GSSAPI methods to do things to the child's environment based
--- hpn-ssh-hpn-18.3.1/servconf.c.orig
+++ hpn-ssh-hpn-18.3.1/servconf.c
@@ -624,7 +624,11 @@
     { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
 #ifdef GSSAPI
     { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+#ifdef USE_GSS_STORE_CRED
+    { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+#else /* USE_GSS_STORE_CRED */
     { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+#endif /* USE_GSS_STORE_CRED */
     { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
 #else
     { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
--- hpn-ssh-hpn-18.3.1/sshd.c.orig
+++ hpn-ssh-hpn-18.3.1/sshd.c
@@ -2313,9 +2313,23 @@
 #ifdef GSSAPI
     if (options.gss_authentication) {
+#ifdef GSSAPI_STORECREDS_NEEDS_RUID
+        if (setreuid(authctxt->pw->pw_uid, -1) != 0) {
+            debug("setreuid %u: %.100s",
+                (u_int) authctxt->pw->pw_uid, strerror(errno));
+            goto bail_storecred;
+        }
+#endif
         temporarily_use_uid(authctxt->pw);
         ssh_gssapi_storecreds();
         restore_uid();
+#ifdef GSSAPI_STORECREDS_NEEDS_RUID
+        if (setuid(geteuid()) != 0) {
+            fatal("setuid %u: %.100s", (u_int) geteuid(),
+                strerror(errno));
+        }
+ bail_storecred: ;
+#endif
     }
 #endif
 #ifdef USE_PAM
components/network/hpn-ssh/patches/0007-DTrace-support-for-SFTP.patch
New file
@@ -0,0 +1,353 @@
--- hpn-ssh-hpn-18.3.1/Makefile.in.orig
+++ hpn-ssh-hpn-18.3.1/Makefile.in
@@ -103,6 +103,7 @@
     monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \
     ssh-ed25519-sk.o ssh-rsa.o dh.o \
     msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
+    sftp_provider.o \
     ssh-pkcs11.o smult_curve25519_ref.o \
     poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \
     cipher-chachapoly-libcrypto-mt.o \
@@ -133,7 +134,7 @@
     srclimit.o sftp-server.o sftp-common.o \
     sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
     sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
-    sandbox-solaris.o uidswap.o cipher-switch.o $(SKOBJS)
+    sandbox-solaris.o uidswap.o cipher-switch.o sftp_provider.o $(SKOBJS)
 SFTP_CLIENT_OBJS=sftp-common.o sftp-client.o sftp-glob.o
@@ -153,7 +154,8 @@
 SSHKEYSCAN_OBJS=ssh-keyscan.o $(SKOBJS)
-SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o
+SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o sftp_provider.o
+ROOTDLIBDIR=$(DESTDIR)/usr/lib/dtrace
 SFTP_OBJS=    sftp.o sftp-usergroup.o progressmeter.o $(SFTP_CLIENT_OBJS)
@@ -266,9 +268,22 @@
 moduli:
     echo
+# dtrace sftp
+sftp_provider.h: $(srcdir)/sftp_provider.d
+    /usr/sbin/dtrace -xnolibs -h -s $(srcdir)/sftp_provider.d \
+        -o $(srcdir)/sftp_provider.h
+
+sftp_provider.o: sftp_provider.d sftp_provider.h sftp-server.o
+    /usr/sbin/dtrace -G -64 -xnolibs -s $(srcdir)/sftp_provider.d \
+        sftp-server.o -o sftp_provider.o
+
+# special case for sftp-server.o, it includes sftp_provider.h
+sftp-server.o: sftp_provider.h sftp-server.c
+    $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $(srcdir)/sftp-server.c
+
 clean:    regressclean
     rm -f *.o *.lo *.a $(TARGETS) logintest config.cache config.log
-    rm -f *.out core survey
+    rm -f *.out core survey sftp_provider.h
     rm -f regress/check-perm$(EXEEXT)
     rm -f regress/mkdtemp$(EXEEXT)
     rm -f regress/unittests/test_helper/*.a
@@ -470,6 +485,7 @@
     $(INSTALL) -m 644 hpnssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/hpnssh-keysign.8
     $(INSTALL) -m 644 hpnssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/hpnssh-pkcs11-helper.8
     $(INSTALL) -m 644 hpnssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/hpnssh-sk-helper.8
+    mkdir -p $(ROOTDLIBDIR) && cp $(srcdir)/hpnsftp.d $(ROOTDLIBDIR)/
 install-sysconf:
     $(MKDIR_P) $(DESTDIR)$(sysconfdir)
--- hpn-ssh-hpn-18.3.1/sftp-server.c.orig
+++ hpn-ssh-hpn-18.3.1/sftp-server.c
@@ -56,6 +56,9 @@
 #include "sftp.h"
 #include "sftp-common.h"
+#ifdef DTRACE_SFTP
+#include "sftp_provider_impl.h"
+#endif
 char *sftp_realpath(const char *, char *); /* sftp-realpath.c */
@@ -803,14 +806,17 @@
     u_int32_t len;
     int r, handle, fd, ret, status = SSH2_FX_FAILURE;
     u_int64_t off;
+    char *fpath;
     if ((r = get_handle(iqueue, &handle)) != 0 ||
         (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
         (r = sshbuf_get_u32(iqueue, &len)) != 0)
         fatal_fr(r, "parse");
+    fpath = handle_to_name(handle);
+
     debug("request %u: read \"%s\" (handle %d) off %llu len %u",
-        id, handle_to_name(handle), handle, (unsigned long long)off, len);
+        id, fpath, handle, (unsigned long long)off, len);
     if ((fd = handle_to_fd(handle)) == -1)
         goto out;
     if (len > SFTP_MAX_READ_LENGTH) {
@@ -829,6 +835,9 @@
             strerror(errno));
         goto out;
     }
+#ifdef DTRACE_SFTP
+    SFTP_TRANSFER_START_OP("read", fd, fpath, len);
+#endif
     if (len == 0) {
         /* weird, but not strictly disallowed */
         ret = 0;
@@ -841,11 +850,18 @@
         status = SSH2_FX_EOF;
         goto out;
     }
+#ifdef DTRACE_SFTP
+    SFTP_TRANSFER_DONE_OP("read", fd, fpath, ret);
+#endif
     send_data(id, buf, ret);
     handle_update_read(handle, ret);
     /* success */
     status = SSH2_FX_OK;
  out:
+#ifdef DTRACE_SFTP
+    if (status != SSH2_FX_OK)
+        SFTP_TRANSFER_DONE_OP("read", fd, fpath, ret);
+#endif
     if (status != SSH2_FX_OK)
         send_status(id, status);
 }
@@ -857,14 +873,17 @@
     size_t len;
     int r, handle, fd, ret, status;
     u_char *data;
+    char *fpath;
     if ((r = get_handle(iqueue, &handle)) != 0 ||
         (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
         (r = sshbuf_get_string(iqueue, &data, &len)) != 0)
         fatal_fr(r, "parse");
+    fpath = handle_to_name(handle);
+
     debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
-        id, handle_to_name(handle), handle, (unsigned long long)off, len);
+        id, fpath, handle, (unsigned long long)off, len);
     fd = handle_to_fd(handle);
     if (fd < 0)
@@ -877,7 +896,13 @@
                 strerror(errno));
         } else {
 /* XXX ATOMICIO ? */
+#ifdef DTRACE_SFTP
+            SFTP_TRANSFER_START_OP("write", fd, fpath, len);
+#endif
             ret = write(fd, data, len);
+#ifdef DTRACE_SFTP
+            SFTP_TRANSFER_DONE_OP("write", fd, fpath, ret);
+#endif
             if (ret == -1) {
                 status = errno_to_portable(errno);
                 error_f("write \"%.100s\": %s",
--- /dev/null
+++ hpn-ssh-hpn-18.3.1/hpnsftp.d
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#pragma D depends_on library net.d
+#pragma D depends_on library io.d
+#pragma D depends_on module lofs
+
+typedef struct sftpinfo {
+    string sfi_user;        /* user name */
+    string sfi_operation;        /* SFTP Operation */
+    ssize_t sfi_nbytes;        /* bytes transferred, if any */
+    string sfi_pathname;        /* pathname of transfer */
+    string sfi_fsresource;        /* Dataset(ZFS) or resource name */
+} sftpinfo_t;
+
+/*
+ * This structure must match the definition of same in sftp_provider_impl.h.
+ */
+typedef struct sftpproto {
+    int64_t sftp_nbytes;        /* bytes written or read */
+    uint64_t sftp_user;        /* user name */
+    uint64_t sftp_operation;    /* SFTP operation */
+    uint64_t sftp_raddr;        /* remote address */
+    uint64_t sftp_pathname;        /* path with file name */
+    int32_t sftp_fd;        /* fd for transfer, if any */
+} sftpproto_t;
+
+#pragma D binding "1.6.1" translator
+translator conninfo_t <sftpproto_t *s> {
+    ci_protocol = "tcp";
+    ci_remote = copyinstr((uintptr_t)
+        *(uint64_t *)copyin((uintptr_t)&s->sftp_raddr, sizeof (uint64_t)));
+    ci_local = "<unknown>";
+};
+
+#pragma D binding "1.6.1" translator
+translator sftpinfo_t <sftpproto_t *s> {
+    sfi_user = copyinstr((uintptr_t)
+        *(uint64_t *)copyin((uintptr_t)&s->sftp_user, sizeof (uint64_t)));
+    sfi_operation = copyinstr((uintptr_t)
+        *(uint64_t *)copyin((uintptr_t)&s->sftp_operation,
+        sizeof (uint64_t)));
+    sfi_nbytes =
+        *(uint64_t *)copyin((uintptr_t)&s->sftp_nbytes, sizeof (uint64_t));
+    sfi_fsresource = stringof(fds[*(int32_t *)copyin((uintptr_t)&s->sftp_fd,
+        sizeof (int32_t))].fi_fs) == "lofs" ? stringof(((struct loinfo *)
+        curthread->t_procp->p_user.u_finfo.fi_list[*(int32_t *)copyin(
+        (uintptr_t)&s->sftp_fd, sizeof (int32_t))].uf_file->f_vnode->
+        v_vfsp->vfs_data)->li_realvfs->vfs_resource->rs_string) :
+        stringof(curthread->t_procp->p_user.u_finfo.fi_list[
+        *(int32_t *)copyin((uintptr_t)&s->sftp_fd, sizeof (int32_t))].
+        uf_file->f_vnode->v_vfsp->vfs_resource->rs_string);
+    sfi_pathname = copyinstr((uintptr_t)*(uint64_t *)copyin(
+        (uintptr_t)&s->sftp_pathname, sizeof (uint64_t)));
+};
--- /dev/null
+++ hpn-ssh-hpn-18.3.1/sftp_provider.d
@@ -0,0 +1,61 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * We seem currently unable to depend properly on existing D libraries (like
+ * hpnsftp.d). But the definitions for conninfo_t and sftpinfo_t are stored there
+ * (and have to be, since that's where the real translators live). So we're
+ * forced to define something here to satisfy dtrace(8), but none of the
+ * definitions or translators here are actually used.
+ */
+typedef struct sftpinfo {
+    int dummy;
+} sftpinfo_t;
+
+typedef struct sftpproto {
+    int dummy;
+} sftpproto_t;
+
+typedef struct conninfo {
+    int dummy;
+} conninfo_t;
+
+translator conninfo_t <sftpproto_t *dp> {
+};
+
+translator sftpinfo_t <sftpproto_t *dp> {
+};
+
+provider sftp {
+    probe transfer__start(sftpproto_t *p) :
+        (conninfo_t *p, sftpinfo_t *p);
+    probe transfer__done(sftpproto_t *p) :
+        (conninfo_t *p, sftpinfo_t *p);
+};
+
+#pragma D attributes Evolving/Evolving/ISA provider sftp provider
+#pragma D attributes Private/Private/Unknown provider sftp module
+#pragma D attributes Private/Private/Unknown provider sftp function
+#pragma D attributes Private/Private/ISA provider sftp name
+#pragma D attributes Evolving/Evolving/ISA provider sftp args
--- /dev/null
+++ hpn-ssh-hpn-18.3.1/sftp_provider_impl.h
@@ -0,0 +1,73 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef    _SFTP_PROVIDER_IMPL_H
+#define    _SFTP_PROVIDER_IMPL_H
+
+#ifdef    __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure must match the definition of same in hpnsftp.d.
+ */
+typedef struct sftpproto {
+    int64_t sftp_nbytes;        /* bytes writtten or read */
+    const char *sftp_user;        /* user name */
+    const char *sftp_operation;    /* SFTP Operation */
+    const char *sftp_raddr;        /* remote address */
+    const char *sftp_pathname;    /* path with file name */
+    int32_t sftp_fd;        /* fd for transfer, if any */
+} sftpproto_t;
+
+#define    SFTP_TRANSFER_PROTO(proto, op, fd, path, len) \
+    bzero((proto), sizeof (struct sftpproto)); \
+    (proto)->sftp_user = (pw->pw_name ? pw->pw_name : "UNKNOWN"); \
+    (proto)->sftp_operation = (op ? op : "UNKNOWN"); \
+    (proto)->sftp_raddr = (client_addr); \
+    (proto)->sftp_fd = (fd); \
+    (proto)->sftp_pathname = (path ? path : "UNKNOWN"); \
+    (proto)->sftp_nbytes = (len); \
+
+#define    SFTP_TRANSFER_START_OP(op, fd, path, len) \
+    if (SFTP_TRANSFER_START_ENABLED()) { \
+        sftpproto_t proto; \
+        SFTP_TRANSFER_PROTO(&proto, op, fd, path, len); \
+        SFTP_TRANSFER_START(&proto); \
+    } \
+
+#define    SFTP_TRANSFER_DONE_OP(op, fd, path, len) \
+    if (SFTP_TRANSFER_DONE_ENABLED()) { \
+        sftpproto_t proto; \
+        SFTP_TRANSFER_PROTO(&proto, op, fd, path, len); \
+        SFTP_TRANSFER_DONE(&proto); \
+    } \
+
+#include "sftp_provider.h"
+
+#ifdef    __cplusplus
+}
+#endif
+
+#endif /* _SFTP_PROVIDER_IMPL_H */
components/network/hpn-ssh/patches/0008-Add-DisableBanner-option.patch
New file
@@ -0,0 +1,161 @@
--- hpn-ssh-hpn-18.3.1/readconf.c.orig
+++ hpn-ssh-hpn-18.3.1/readconf.c
@@ -168,6 +168,9 @@
     oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
     oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
     oHashKnownHosts,
+#ifdef DISABLE_BANNER
+    oDisableBanner,
+#endif
     oTunnel, oTunnelDevice,
     oLocalCommand, oPermitLocalCommand, oRemoteCommand,
     oTcpRcvBufPoll, oHPNDisabled,
@@ -298,6 +301,9 @@
     { "controlpersist", oControlPersist },
     { "hashknownhosts", oHashKnownHosts },
     { "include", oInclude },
+#ifdef DISABLE_BANNER
+    { "disablebanner", oDisableBanner },
+#endif
     { "tunnel", oTunnel },
     { "tunneldevice", oTunnelDevice },
     { "localcommand", oLocalCommand },
@@ -1026,6 +1032,17 @@
     return -1;
 }
+#ifdef DISABLE_BANNER
+static const struct multistate multistate_disablebanner[] = {
+    { "true",            SSH_DISABLEBANNER_YES },
+    { "false",            SSH_DISABLEBANNER_NO },
+    { "yes",            SSH_DISABLEBANNER_YES },
+    { "no",                SSH_DISABLEBANNER_NO },
+    { "in-exec-mode",        SSH_DISABLEBANNER_INEXECMODE },
+    { NULL, -1 }
+};
+#endif
+
 /*
  * Processes a single option line as used in the configuration files. This
  * only sets those values that have not already been set.
@@ -2425,6 +2442,13 @@
         }
         break;
+#ifdef DISABLE_BANNER
+    case oDisableBanner:
+            intptr = &options->disable_banner;
+                multistate_ptr = multistate_disablebanner;
+                goto parse_multistate;
+#endif
+
     case oDeprecated:
         debug("%s line %d: Deprecated option \"%s\"",
             filename, linenum, keyword);
@@ -2672,6 +2696,9 @@
     options->stdin_null = -1;
     options->fork_after_authentication = -1;
     options->proxy_use_fdpass = -1;
+#ifdef DISABLE_BANNER
+    options->disable_banner = -1;
+#endif
     options->ignored_unknown = NULL;
     options->num_canonical_domains = 0;
     options->num_permitted_cnames = 0;
@@ -2906,6 +2933,10 @@
         options->canonicalize_fallback_local = 1;
     if (options->canonicalize_hostname == -1)
         options->canonicalize_hostname = SSH_CANONICALISE_NO;
+#ifdef DISABLE_BANNER
+    if (options->disable_banner == -1)
+        options->disable_banner = 0;
+#endif
     if (options->fingerprint_hash == -1)
         options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
 #ifdef ENABLE_SK_INTERNAL
--- hpn-ssh-hpn-18.3.1/readconf.h.orig
+++ hpn-ssh-hpn-18.3.1/readconf.h
@@ -198,6 +198,9 @@
     u_int    num_channel_timeouts;
     char    *ignored_unknown; /* Pattern list of unknown tokens to ignore */
+#ifdef DISABLE_BANNER
+        int     disable_banner; /* Disable display of banner */
+#endif
 }       Options;
 #define SSH_PUBKEY_AUTH_NO    0x00
@@ -243,6 +246,12 @@
 #define SSH_KEYSTROKE_CHAFF_MIN_MS        1024
 #define SSH_KEYSTROKE_CHAFF_RNG_MS        2048
+#ifdef DISABLE_BANNER
+#define SSH_DISABLEBANNER_NO        0
+#define SSH_DISABLEBANNER_YES        1
+#define SSH_DISABLEBANNER_INEXECMODE    2
+#endif
+
 const char *kex_default_pk_alg(void);
 char    *ssh_connection_hash(const char *thishost, const char *host,
     const char *portstr, const char *user, const char *jump_host);
--- hpn-ssh-hpn-18.3.1/hpnssh_config.5.orig
+++ hpn-ssh-hpn-18.3.1/hpnssh_config.5
@@ -713,6 +713,14 @@
 then the backgrounded master connection will automatically terminate
 after it has remained idle (with no client connections) for the
 specified time.
+.It Cm DisableBanner
+If set to yes, disables the display of the  banner  message.
+If set to in-exec-mode, disables the display of banner message when in remote
+command mode only.
+.Pp
+The default value is no, which means that the banner is displayed unless the
+log level  is  QUIET, FATAL, or ERROR. See also the Banner option in
+.Xr sshd_config 4 . This option applies to protocol version 2 only.
 .It Cm DisableMTAES
 Switch the encryption cipher being used from the multithreaded MT-AES-CTR cipher
 back to the stock single-threaded AES-CTR cipher. This may prove to be more
--- hpn-ssh-hpn-18.3.1/sshconnect2.c.orig
+++ hpn-ssh-hpn-18.3.1/sshconnect2.c
@@ -85,6 +85,10 @@
 extern char *server_version_string;
 extern Options options;
+#ifdef DISABLE_BANNER
+extern struct sshbuf *command;
+#endif
+
 /*
  * tty_flag is set in ssh.c. Use this in ssh_userauth2:
  * if it is set, then prevent the switch to the null cipher.
@@ -630,8 +634,28 @@
     if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 ||
         (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0)
         goto out;
-    if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO)
-        fmprintf(stderr, "%s", msg);
+#ifdef DISABLE_BANNER
+    /*
+     * Banner is a warning message according to RFC 4252. So, never print
+     * a banner in error log level or lower. If the log level is higher,
+     * use DisableBanner option to decide whether to display it or not.
+     */
+    if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO &&
+            (options.disable_banner == SSH_DISABLEBANNER_NO ||
+            (options.disable_banner == SSH_DISABLEBANNER_INEXECMODE &&
+            sshbuf_len(command) == 0))) {
+#else
+    if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) {
+#endif
+        char *safe;
+
+        if (len > 65536)
+            len = 65536;
+        safe = xmalloc(len * 4 + 1); /* max expansion from strnvis() */
+        strnvis(safe, msg, len * 4 + 1, VIS_SAFE|VIS_OCTAL|VIS_NOSLASH);
+        fmprintf(stderr, "%s", safe);
+        free(safe);
+    }
     r = 0;
  out:
     free(msg);
components/network/hpn-ssh/patches/0009-PAM-conversation-fix.patch
New file
@@ -0,0 +1,84 @@
--- hpn-ssh-hpn-18.3.1/auth-pam.c.orig
+++ hpn-ssh-hpn-18.3.1/auth-pam.c
@@ -1281,11 +1281,13 @@
     free(env);
 }
+#ifndef PAM_BUGFIX
 /*
  * "Blind" conversation function for password authentication.  Assumes that
  * echo-off prompts are for the password and stores messages for later
  * display.
  */
+#endif
 static int
 sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
     struct pam_response **resp, void *data)
@@ -1307,12 +1309,24 @@
     for (i = 0; i < n; ++i) {
         switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
         case PAM_PROMPT_ECHO_OFF:
+#ifdef PAM_BUGFIX
+            /*
+             * PAM conversation function for the password userauth
+             * method (non-interactive) really cannot do any
+             * prompting.  We set the PAM_AUTHTOK item in
+             * sshpam_auth_passwd()to avoid conversation. If some
+             * modules still try to converse, then the password
+             * userauth will fail.
+             */
+            goto fail;
+#else
             if (sshpam_password == NULL)
                 goto fail;
             if ((reply[i].resp = strdup(sshpam_password)) == NULL)
                 goto fail;
             reply[i].resp_retcode = PAM_SUCCESS;
             break;
+#endif
         case PAM_ERROR_MSG:
         case PAM_TEXT_INFO:
             len = strlen(PAM_MSG_MEMBER(msg, i, msg));
@@ -1349,6 +1363,9 @@
 int
 sshpam_auth_passwd(Authctxt *authctxt, const char *password)
 {
+#ifdef PAM_BUGFIX
+    int set_item_rtn;
+#endif
     int flags = (options.permit_empty_passwd == 0 ?
         PAM_DISALLOW_NULL_AUTHTOK : 0);
     char *fake = NULL;
@@ -1369,6 +1386,15 @@
         options.permit_root_login != PERMIT_YES))
         sshpam_password = fake = fake_password(password);
+#ifdef PAM_BUGFIX
+    sshpam_err = pam_set_item(sshpam_handle, PAM_AUTHTOK, password);
+    if (sshpam_err != PAM_SUCCESS) {
+        debug("PAM: %s: failed to set PAM_AUTHTOK: %s", __func__,
+            pam_strerror(sshpam_handle, sshpam_err));
+        return 0;
+    }
+#endif
+
     sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
         (const void *)&passwd_conv);
     if (sshpam_err != PAM_SUCCESS)
@@ -1380,6 +1406,16 @@
     free(fake);
     if (sshpam_err == PAM_MAXTRIES)
         sshpam_set_maxtries_reached(1);
+
+#ifdef PAM_BUGFIX
+    set_item_rtn = pam_set_item(sshpam_handle, PAM_AUTHTOK, NULL);
+    if (set_item_rtn != PAM_SUCCESS) {
+        debug("PAM: %s: failed to set PAM_AUTHTOK: %s", __func__,
+            pam_strerror(sshpam_handle, set_item_rtn));
+        return 0;
+    }
+#endif
+
     if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
         debug("PAM: password authentication accepted for %.100s",
             authctxt->user);
components/network/hpn-ssh/patches/0010-PAM-enhancements-for-Solaris.patch
New file
@@ -0,0 +1,615 @@
--- hpn-ssh-hpn-18.3.1/auth-pam.c.orig
+++ hpn-ssh-hpn-18.3.1/auth-pam.c
@@ -687,6 +687,66 @@
     sshpam_handle = NULL;
 }
+#ifdef PAM_ENHANCEMENT
+char *
+derive_pam_service_name(Authctxt *authctxt)
+{
+    char *svcname = xmalloc(BUFSIZ);
+
+    /*
+     * If PamServiceName is set we use that for everything, including
+     * SSHv1
+     */
+    if (options.pam_service_name != NULL) {
+        (void) strlcpy(svcname, options.pam_service_name, BUFSIZ);
+        return (svcname);
+    }
+
+    char *method_name = authctxt->authmethod_name;
+
+    if (!method_name)
+        fatal("Userauth method unknown while starting PAM");
+
+    /*
+     * For SSHv2 we use "sshd-<userauth name>
+     * The "sshd" prefix can be changed via the PAMServicePrefix
+     * sshd_config option.
+     */
+    if (strcmp(method_name, "none") == 0) {
+        snprintf(svcname, BUFSIZ, "%s-none",
+            options.pam_service_prefix);
+    }
+    if (strcmp(method_name, "password") == 0) {
+        snprintf(svcname, BUFSIZ, "%s-password",
+            options.pam_service_prefix);
+    }
+    if (strcmp(method_name, "keyboard-interactive") == 0) {
+        /* "keyboard-interactive" is too long, shorten it */
+        snprintf(svcname, BUFSIZ, "%s-kbdint",
+            options.pam_service_prefix);
+    }
+    if (strcmp(method_name, "publickey") == 0) {
+        /* "publickey" is too long, shorten it */
+        snprintf(svcname, BUFSIZ, "%s-pubkey",
+            options.pam_service_prefix);
+    }
+    if (strcmp(method_name, "hostbased") == 0) {
+        snprintf(svcname, BUFSIZ, "%s-hostbased",
+            options.pam_service_prefix);
+    }
+    if (strncmp(method_name, "gssapi-", 7) == 0) {
+        /*
+         * Although OpenSSH only supports "gssapi-with-mic"
+         * for now. We will still map any userauth method
+         * prefixed with "gssapi-" to the gssapi PAM service.
+         */
+        snprintf(svcname, BUFSIZ, "%s-gssapi",
+            options.pam_service_prefix);
+    }
+    return svcname;
+}
+#endif /* PAM_ENHANCEMENT */
+
 static int
 sshpam_init(struct ssh *ssh, Authctxt *authctxt)
 {
@@ -700,23 +760,76 @@
         fatal("Username too long from %s port %d",
             ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
 #endif
+
+#ifdef PAM_ENHANCEMENT
+    const char *pam_service;
+    const char **ptr_pam_service = &pam_service;
+    char *svc = NULL;
+
+    svc = derive_pam_service_name(authctxt);
+    debug3("PAM service is %s", svc);
+#endif
+
     if (sshpam_handle == NULL) {
         if (ssh == NULL) {
             fatal("%s: called initially with no "
                 "packet context", __func__);
         }
     } if (sshpam_handle != NULL) {
+#ifdef PAM_ENHANCEMENT
+            /* get the pam service name */
+        sshpam_err = pam_get_item(sshpam_handle,
+            PAM_SERVICE, (sshpam_const void **)ptr_pam_service);
+        if (sshpam_err != PAM_SUCCESS)
+            fatal("Failed to get the PAM service name");
+        debug3("Previous pam_service is %s", pam_service ?
+            pam_service : "NULL");
+
+        /* get the pam user name */
+        sshpam_err = pam_get_item(sshpam_handle,
+            PAM_USER, (sshpam_const void **)ptr_pam_user);
+
+        /*
+         * only need to re-start if either user or service is
+         * different.
+         */
+        if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0
+            && strncmp(svc, pam_service, strlen(svc)) == 0) {
+            free(svc);
+            return (0);
+        }
+
+        /*
+         * Clean up previous PAM state.  No need to clean up session
+         * and creds.
+         */
+        sshpam_authenticated = 0;
+        sshpam_account_status = -1;
+
+        sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, NULL);
+        if (sshpam_err != PAM_SUCCESS)
+            debug3("Cannot remove PAM conv"); /* a warning only */
+#else /* Original */
         /* We already have a PAM context; check if the user matches */
         sshpam_err = pam_get_item(sshpam_handle,
             PAM_USER, (sshpam_const void **)ptr_pam_user);
         if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
             return (0);
+#endif /* PAM_ENHANCEMENT */
         pam_end(sshpam_handle, sshpam_err);
         sshpam_handle = NULL;
     }
     debug("PAM: initializing for \"%s\"", user);
+#ifdef PAM_ENHANCEMENT
+    debug3("Starting PAM service %s for user %s method %s", svc, user,
+        authctxt->authmethod_name);
+    sshpam_err =
+        pam_start(svc, user, &store_conv, &sshpam_handle);
+    free(svc);
+#else /* Original */
     sshpam_err =
         pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
+#endif
     sshpam_authctxt = authctxt;
     if (sshpam_err != PAM_SUCCESS) {
--- hpn-ssh-hpn-18.3.1/auth.h.orig
+++ hpn-ssh-hpn-18.3.1/auth.h
@@ -95,6 +95,9 @@
     /* Information exposed to session */
     struct sshbuf    *session_info;    /* Auth info for environment */
+#ifdef PAM_ENHANCEMENT
+    char        *authmethod_name;
+#endif
 };
 /*
--- hpn-ssh-hpn-18.3.1/auth2.c.orig
+++ hpn-ssh-hpn-18.3.1/auth2.c
@@ -317,9 +317,17 @@
 #endif
         }
 #ifdef USE_PAM
+#ifdef PAM_ENHANCEMENT
+        /*
+         * Start PAM here and once only, if each userauth does not
+         * has its own PAM service.
+         */
+        if (options.use_pam && !options.pam_service_per_authmethod)
+#else
         if (options.use_pam)
+#endif /* PAM_ENHANCEMENT */
             PRIVSEP(start_pam(ssh));
-#endif
+#endif /* USE_PAM */
         ssh_packet_set_log_preamble(ssh, "%suser %s",
             authctxt->valid ? "authenticating " : "invalid ", user);
         setproctitle("%s%s", authctxt->valid ? user : "unknown",
@@ -356,6 +364,18 @@
     /* try to authenticate user */
     m = authmethod_lookup(authctxt, method);
     if (m != NULL && authctxt->failures < options.max_authtries) {
+
+#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
+        /* start PAM service for each userauth */
+        if (options.use_pam && options.pam_service_per_authmethod) {
+            if (authctxt->authmethod_name != NULL)
+                free(authctxt->authmethod_name);
+            authctxt->authmethod_name = xstrdup(method);
+            if (use_privsep)
+                mm_inform_authmethod(method);
+            PRIVSEP(start_pam(authctxt));
+        }
+#endif
         debug2("input_userauth_request: try method %s", method);
         authenticated =    m->userauth(ssh, method);
     }
@@ -381,6 +401,10 @@
     char *methods;
     int r, partial = 0;
+#ifdef  PAM_ENHANCEMENT
+    debug3("%s: entering", __func__);
+#endif
+
     if (authenticated) {
         if (!authctxt->valid) {
             fatal("INTERNAL ERROR: authenticated invalid user %s",
@@ -404,6 +428,25 @@
     }
     if (authenticated && options.num_auth_methods != 0) {
+
+#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
+                /*
+                 * If each userauth has its own PAM service, then PAM needs to
+                 * perform the account check for this service.
+                 */
+                if (options.use_pam && options.pam_service_per_authmethod &&
+                    !PRIVSEP(do_pam_account())) {
+                        /* if PAM returned a message, send it to the user */
+                        if (sshbuf_len(loginmsg) > 0) {
+                                sshbuf_put(loginmsg, "\0", 1);
+                                userauth_send_banner(ssh, sshbuf_ptr(loginmsg));
+                                ssh_packet_write_wait(ssh);
+                        }
+
+                        fatal("Access denied for user %s by PAM account "
+                            "configuration", authctxt->user);
+                }
+#endif
         if (!auth2_update_methods_lists(authctxt, method, submethod)) {
             authenticated = 0;
             partial = 1;
@@ -421,7 +464,19 @@
         return;
 #ifdef USE_PAM
+#ifdef PAM_ENHANCEMENT
+        /*
+         * PAM needs to perform account checks after auth. However, if each
+         * userauth has its own PAM service and options.num_auth_methods != 0,
+         * then no need to perform account checking, because it was done
+         * already.
+         */
+    if (options.use_pam && authenticated &&
+        !(options.num_auth_methods != 0 &&
+        options.pam_service_per_authmethod)) {
+#else
     if (options.use_pam && authenticated) {
+#endif
         int r, success = PRIVSEP(do_pam_account());
         /* If PAM returned a message, send it to the user. */
--- hpn-ssh-hpn-18.3.1/monitor.c.orig
+++ hpn-ssh-hpn-18.3.1/monitor.c
@@ -117,6 +117,9 @@
 int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
 int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
 int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
+#ifdef PAM_ENHANCEMENT
+int mm_answer_authmethod(struct ssh *, int, struct sshbuf *);
+#endif
 int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
 int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
 int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
@@ -190,10 +193,17 @@
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+#ifdef PAM_ENHANCEMENT
+    {MONITOR_REQ_AUTHMETHOD, MON_ISAUTH, mm_answer_authmethod},
+#endif
     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
 #ifdef USE_PAM
+#ifdef PAM_ENHANCEMENT
+    {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start},
+#else
     {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+#endif
     {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
     {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx},
     {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query},
@@ -300,6 +310,25 @@
         /* Special handling for multiple required authentications */
         if (options.num_auth_methods != 0) {
+
+#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
+            /*
+             * If each userauth has its own PAM service, then PAM
+             * need to perform account check for this service.
+             */
+            if (options.use_pam && authenticated &&
+                options.pam_service_per_authmethod) {
+                struct sshbuf *m;
+                if ((m = sshbuf_new()) == NULL)
+                    fatal("%s: sshbuf_new", __func__);
+                mm_request_receive_expect(pmonitor->m_sendfd,
+                    MONITOR_REQ_PAM_ACCOUNT, m);
+                authenticated = mm_answer_pam_account(ssh,
+                    pmonitor->m_sendfd, m);
+                sshbuf_free(m);
+            }
+#endif
+
             if (authenticated &&
                 !auth2_update_methods_lists(authctxt,
                 auth_method, auth_submethod)) {
@@ -317,8 +346,21 @@
                 !auth_root_allowed(ssh, auth_method))
                 authenticated = 0;
 #ifdef USE_PAM
+#ifdef PAM_ENHANCEMENT
+                        /*
+                         * PAM needs to perform account checks after auth.
+                         * However, if each userauth has its own PAM service
+                         * and options.num_auth_methods != 0, then no need to
+                         * perform account checking, because it was done
+                         * already.
+                         */
+            if (options.use_pam && authenticated &&
+                !(options.num_auth_methods != 0 &&
+                options.pam_service_per_authmethod)) {
+#else
             /* PAM needs to perform account checks after auth */
             if (options.use_pam && authenticated) {
+#endif
                 struct sshbuf *m;
                 if ((m = sshbuf_new()) == NULL)
@@ -802,6 +844,11 @@
     monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
     monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
+#ifdef PAM_ENHANCEMENT
+    /* Allow authmethod information on the auth context */
+    monitor_permit(mon_dispatch, MONITOR_REQ_AUTHMETHOD, 1);
+#endif
+
 #ifdef USE_PAM
     if (options.use_pam)
         monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
@@ -825,6 +872,27 @@
     return (0);
 }
+#ifdef PAM_ENHANCEMENT
+int
+mm_answer_authmethod(struct ssh *ssh, int sock, struct sshbuf *m)
+{
+    Authctxt *authctxt = ssh->authctxt;
+
+    monitor_permit_authentications(1);
+    /*sshbuf_dump(m, stderr);*/
+    sshbuf_get_cstring(m, &authctxt->authmethod_name, NULL);
+    debug3("%s: authmethod_name=%s", __func__, authctxt->authmethod_name);
+
+    if (authctxt->authmethod_name &&
+        strlen(authctxt->authmethod_name) == 0) {
+        free(authctxt->authmethod_name);
+        authctxt->authmethod_name = NULL;
+    }
+
+    return (0);
+}
+#endif
+
 int
 mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
 {
--- hpn-ssh-hpn-18.3.1/monitor.h.orig
+++ hpn-ssh-hpn-18.3.1/monitor.h
@@ -63,6 +63,9 @@
     MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
     MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
+#ifdef PAM_ENHANCEMENT
+    MONITOR_REQ_AUTHMETHOD = 114,
+#endif
 };
 struct ssh;
--- hpn-ssh-hpn-18.3.1/monitor_wrap.c.orig
+++ hpn-ssh-hpn-18.3.1/monitor_wrap.c
@@ -396,6 +396,24 @@
     sshbuf_free(m);
 }
+#ifdef PAM_ENHANCEMENT
+/* Inform the privileged process about the authentication method */
+void
+mm_inform_authmethod(char *authmethod)
+{
+    struct sshbuf *m;
+
+    debug3("%s entering", __func__);
+    if ((m = sshbuf_new()) == NULL)
+        fatal("%s: sshbuf_new", __func__);
+    sshbuf_put_cstring(m, authmethod);
+
+    mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHMETHOD, m);
+
+    sshbuf_free(m);
+}
+#endif
+
 /* Do the password authentication */
 int
 mm_auth_password(struct ssh *ssh, char *password)
--- hpn-ssh-hpn-18.3.1/servconf.c.orig
+++ hpn-ssh-hpn-18.3.1/servconf.c
@@ -203,6 +203,18 @@
     options->channel_timeouts = NULL;
     options->num_channel_timeouts = 0;
     options->unused_connection_timeout = -1;
+#ifdef PAM_ENHANCEMENT
+    options->pam_service_name = NULL;
+    options->pam_service_prefix = NULL;
+
+    /*
+     * Each user method will have its own PAM service by default.
+     * However, if PAMServiceName is specified
+     * then there will be only one PAM service for the
+     * entire user authentication.
+     */
+    options->pam_service_per_authmethod = 1;
+#endif
 }
 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -454,6 +466,12 @@
         options->ip_qos_bulk = IPTOS_DSCP_CS1;
     if (options->version_addendum == NULL)
         options->version_addendum = xstrdup("");
+
+#ifdef PAM_ENHANCEMENT
+    if (options->pam_service_prefix == NULL)
+        options->pam_service_prefix = _SSH_PAM_SERVICE_PREFIX;
+#endif
+
     if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
         options->fwd_opts.streamlocal_bind_mask = 0177;
     if (options->fwd_opts.streamlocal_bind_unlink == -1)
@@ -547,6 +565,9 @@
     sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
     sUsePrivilegeSeparation, sAllowAgentForwarding,
     sHostCertificate, sInclude,
+#ifdef PAM_ENHANCEMENT
+    sPAMServicePrefix, sPAMServiceName,
+#endif
     sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
     sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
     sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
@@ -698,6 +719,10 @@
     { "forcecommand", sForceCommand, SSHCFG_ALL },
     { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
     { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
+#ifdef PAM_ENHANCEMENT
+    { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL },
+    { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL },
+#endif
     { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
     { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
     { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
@@ -2605,6 +2630,37 @@
         }
         goto parse_time;
+    case sPAMServicePrefix:
+        arg = strdelim(&str);
+        if (!arg || *arg == '\0')
+            fatal("%s line %d: Missing argument.",
+                filename, linenum);
+        if (options->pam_service_name != NULL)
+            fatal("%s line %d: PAMServiceName and PAMServicePrefix"
+                " are mutually exclusive.", filename, linenum);
+        if (options->pam_service_prefix == NULL)
+            options->pam_service_prefix = xstrdup(arg);
+        break;
+
+    case sPAMServiceName:
+        arg = strdelim(&str);
+        if (!arg || *arg == '\0')
+            fatal("%s line %d: Missing argument.",
+                filename, linenum);
+        if (options->pam_service_prefix != NULL)
+            fatal("%s line %d: PAMServiceName and PAMServicePrefix"
+                " are mutually exclusive.", filename, linenum);
+        if (options->pam_service_name == NULL) {
+            options->pam_service_name = xstrdup(arg);
+
+            /*
+             * When this option is specified, we will not have
+             * PAM service for each auth method.
+                         */
+            options->pam_service_per_authmethod = 0;
+        }
+        break;
+
     case sDeprecated:
     case sIgnore:
     case sUnsupported:
--- hpn-ssh-hpn-18.3.1/servconf.h.orig
+++ hpn-ssh-hpn-18.3.1/servconf.h
@@ -71,6 +71,10 @@
     struct addrinfo *addrs;
 };
+#ifdef PAM_ENHANCEMENT
+#define _SSH_PAM_SERVICE_PREFIX "sshd"
+#endif
+
 typedef struct {
     u_int    num_ports;
     u_int    ports_from_cmdline;
@@ -228,6 +232,12 @@
     u_int    num_auth_methods;
     char   **auth_methods;
+#ifdef PAM_ENHANCEMENT
+    char   *pam_service_prefix;
+    char   *pam_service_name;
+    int    pam_service_per_authmethod;
+#endif
+
     int    fingerprint_hash;
     int    expose_userauth_info;
     u_int64_t timing_secret;
--- hpn-ssh-hpn-18.3.1/hpnsshd.8.orig
+++ hpn-ssh-hpn-18.3.1/hpnsshd.8
@@ -1017,6 +1017,33 @@
 started last).
 The content of this file is not sensitive; it can be world-readable.
 .El
+
+.Sh SECURITY
+sshd uses pam(3PAM) for password and keyboard-interactive methods as well as
+for account management, session management, and the password management for all
+authentication methods.
+.Pp
+Each SSHv2 userauth type has its own PAM service name:
+
+.Bd -literal -offset 3n
+
+-----------------------------------------------
+| SSHv2 Userauth       | PAM Service Name     |
+-----------------------------------------------
+| none                 | sshd-none            |
+-----------------------------------------------
+| password             | sshd-password        |
+-----------------------------------------------
+| keyboard-interactive | sshd-kbdint          |
+-----------------------------------------------
+| pubkey               | sshd-pubkey          |
+-----------------------------------------------
+| hostbased            | sshd-hostbased       |
+-----------------------------------------------
+| gssapi-with-mic      | sshd-gssapi          |
+-----------------------------------------------
+.Ed
+
 .Sh SEE ALSO
 .Xr hpnscp 1 ,
 .Xr hpnsftp 1 ,
--- hpn-ssh-hpn-18.3.1/hpnsshd_config.5.orig
+++ hpn-ssh-hpn-18.3.1/hpnsshd_config.5
@@ -1401,6 +1401,35 @@
 protection against man-in-the-middle attacks. As with NoneEnabled all authentication
 remains encrypted and integrity is ensured. Default is
 .Cm no.
+.It Cm PAMServiceName
+Specifies the PAM service name for the PAM session.
+The
+.Cm PAMServiceName
+and
+.Cm PAMServicePrefix
+options are mutually exclusive and if both are set, sshd does not start.
+If this option is set the service name is the same for all user authentication
+methods.
+The option has no default value.
+See
+.Cm PAMServicePrefix
+for more information.
+.It Cm PAMServicePrefix
+Specifies the PAM service name prefix for service names used for individual
+user authentication methods.
+The default is sshd.
+The
+.Cm PAMServiceName
+and
+.Cm PAMServicePrefix
+options are mutually exclusive and if both are set, sshd does not start.
+.Pp
+For example, if this option is set to
+.Cm admincli ,
+the service name for the keyboard-interactive authentication method is
+.Sy admincli-kbdint
+instead of the default
+.Sy sshd-kbdint .
 .It Cm PasswordAuthentication
 Specifies whether password authentication is allowed.
 The default is
@@ -1943,8 +1972,7 @@
 is enabled, you will not be able to run
 .Xr sshd 8
 as a non-root user.
-The default is
-.Cm no .
+On OpenIndiana, the option is always enabled.
 .It Cm VersionAddendum
 Optionally specifies additional text to append to the SSH protocol banner
 sent by the server upon connection.
components/network/hpn-ssh/patches/0013-Solaris-Auditing-support.patch
New file
@@ -0,0 +1,762 @@
--- hpn-ssh-hpn-18.3.1/INSTALL.orig
+++ hpn-ssh-hpn-18.3.1/INSTALL
@@ -103,9 +103,13 @@
 Basic Security Module (BSM):
-Native BSM support is known to exist in Solaris from at least 2.5.1,
-FreeBSD 6.1 and OS X.  Alternatively, you may use the OpenBSM
-implementation (http://www.openbsm.org).
+Native BSM support is known to exist in Solaris from at least 2.5.1
+to Solaris 10.  From Solaris 11 the previously documented BSM (libbsm)
+interfaces are no longer public and are unsupported.  While not public
+interfaces, audit-solaris.c implements Solaris Audit from Solaris 11.
+Native BSM support is known to exist in FreeBSD 6.1 and OS X.
+Alternatively, you may use the OpenBSM implementation
+(http://www.openbsm.org).
 makedepend:
@@ -171,8 +175,9 @@
 There are a few other options to the configure script:
 --with-audit=[module] enable additional auditing via the specified module.
-Currently, drivers for "debug" (additional info via syslog) and "bsm"
-(Sun's Basic Security Module) are supported.
+Currently, drivers for "debug" (additional info via syslog), and "bsm"
+(Sun's Legacy Basic Security Module prior to Solaris 11), and "solaris"
+(Sun's Audit infrastructure from Solaris 11) are supported.
 --with-pam enables PAM support. If PAM support is compiled in, it must
 also be enabled in sshd_config (refer to the UsePAM directive).
--- hpn-ssh-hpn-18.3.1/Makefile.in.orig
+++ hpn-ssh-hpn-18.3.1/Makefile.in
@@ -122,7 +122,7 @@
     sshconnect.o sshconnect2.o mux.o cipher-switch.o $(SKOBJS)
 SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
-    audit.o audit-bsm.o audit-linux.o platform.o \
+    audit.o audit-bsm.o audit-linux.o audit-solaris.o platform.o \
     sshpty.o sshlogin.o servconf.o serverloop.o \
     auth.o auth2.o auth-options.o session.o \
     auth2-chall.o groupaccess.o \
--- hpn-ssh-hpn-18.3.1/README.platform.orig
+++ hpn-ssh-hpn-18.3.1/README.platform
@@ -71,10 +71,10 @@
 libssl-dev, libz-dev and libpam-dev.
-Solaris
--------
-If you enable BSM auditing on Solaris, you need to update audit_event(4)
-for praudit(1m) to give sensible output.  The following line needs to be
+Prior to Solaris 11
+-------------------
+If you enable BSM auditing on Solaris, you need to update audit_event(5)
+for praudit(8) to give sensible output.  The following line needs to be
 added to /etc/security/audit_event:
     32800:AUE_openssh:OpenSSH login:lo
@@ -85,6 +85,9 @@
 number is already in use on your system, you may change it at build time
 by configure'ing --with-cflags=-DAUE_openssh=32801 then rebuilding.
+From Solaris 11
+---------------
+Solaris Audit is supported by configuring --with-audit=solaris.
 Platforms using PAM
 -------------------
--- hpn-ssh-hpn-18.3.1/audit-bsm.c.orig
+++ hpn-ssh-hpn-18.3.1/audit-bsm.c
@@ -348,7 +348,7 @@
 /* Below is the sshd audit API code */
 void
-audit_connection_from(const char *host, int port)
+audit_connection_from(struct ssh *ssh, const char *host, int port)
 {
     AuditInfoTermID *tid = &ssh_bsm_tid;
     char buf[1024];
--- hpn-ssh-hpn-18.3.1/audit-linux.c.orig
+++ hpn-ssh-hpn-18.3.1/audit-linux.c
@@ -71,7 +71,7 @@
 /* Below is the sshd audit API code */
 void
-audit_connection_from(const char *host, int port)
+audit_connection_from(struct ssh *ssh, const char *host, int port)
 {
     /* not implemented */
 }
--- /dev/null
+++ hpn-ssh-hpn-18.3.1/audit-solaris.c
@@ -0,0 +1,574 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include "includes.h"
+#if defined(USE_SOLARIS_AUDIT)
+
+#include "audit.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "log.h"
+#include "packet.h"
+
+#include <errno.h>
+#include <pwd.h>
+#include <string.h>
+
+#include <bsm/adt.h>
+#include <bsm/adt_event.h>
+
+#ifdef    ADT_DEBUG
+#include <bsm/audit.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <values.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ucred.h>
+#include <values.h>
+
+#include <bsm/adt.h>
+#include <bsm/audit.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* semi private adt functions to extract information */
+
+extern void adt_get_asid(const adt_session_data_t *, au_asid_t *);
+extern void adt_get_auid(const adt_session_data_t *, au_id_t *);
+extern void adt_get_mask(const adt_session_data_t *, au_mask_t *);
+extern void adt_get_termid(const adt_session_data_t *, au_tid_addr_t *);
+
+extern void __auditd_debug(char *, ...);
+
+void
+__audit_pidinfo(void)
+{
+    adt_session_data_t *ah = NULL;
+    au_id_t    auid;
+    char *auid_name = "badname";
+    struct passwd *pwd;
+    au_asid_t asid;
+    au_mask_t mask;
+    char flags[512];
+    au_tid_addr_t tid;
+    char    pbuf[INET6_ADDRSTRLEN];
+    int    af = AF_INET;
+    int    remote;
+    int    local;
+
+    if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
+        __auditd_debug("cannot start session %s\n", strerror(errno));
+        return;
+    }
+    if (ah == NULL) {
+        __auditd_debug("ah is NULL\n");
+        return;
+    }
+    adt_get_auid(ah, &auid);
+    if ((pwd = getpwuid((uid_t)auid)) != NULL) {
+        auid_name = pwd->pw_name;
+    }
+    __auditd_debug("audit id = %s(%d)\n", auid_name, auid);
+
+    adt_get_mask(ah, &mask);
+    if (getauditflagschar(flags, &mask, NULL) < 0) {
+        (void) strlcpy(flags, "badflags", sizeof (flags));
+    }
+#ifdef    _LP64
+    __auditd_debug("preselection mask = %s(0x%lx,0x%lx)\n", flags,
+        mask.am_success, mask.am_failure);
+#else    /* _ILP32 */
+    __auditd_debug("preselection mask = %s(0x%llx,0x%llx)\n", flags,
+        mask.am_success, mask.am_failure);
+#endif    /* _LP64 */
+
+    adt_get_termid(ah, &tid);
+    __auditd_debug("tid type=%d, maj=%u, min=%u, addr=%x:%x:%x:%x\n",
+        tid.at_type,
+        (uint16_t)((tid.at_port) >> BITS(uint16_t)),
+        (uint16_t)(tid.at_port & UINT16_MAX),
+        tid.at_addr[0],
+        tid.at_addr[1],
+        tid.at_addr[2],
+        tid.at_addr[3]);
+    if (tid.at_type == AU_IPv6) {
+        af = AF_INET6;
+    }
+    (void) inet_ntop(af, (void *)(tid.at_addr), pbuf,
+        sizeof (pbuf));
+    remote = (tid.at_port >> BITS(uint16_t));
+    local = (tid.at_port & UINT16_MAX);
+    __auditd_debug("tid type-%d (remote,local,host)= %u,%u,%s\n",
+        tid.at_type, remote, local, pbuf);
+    adt_get_asid(ah, &asid);
+    __auditd_debug("audit session id = %u\n",  asid);
+    (void) adt_end_session(ah);
+}
+#else    /* !ADT_DEBUG */
+/*ARGSUSED*/
+/*PRINTFLIKE1*/
+static void
+__auditd_debug(char *fmt, ...)
+{
+}
+static void
+__audit_pidinfo()
+{
+}
+#endif    /* ADT_DEBUG */
+
+#include <security/pam_appl.h>
+
+#include <sys/types.h>
+
+extern Authctxt *the_authctxt;
+
+extern const char *audit_username(void);
+extern const char *audit_event_lookup(ssh_audit_event_t);
+
+static adt_session_data_t *ah = NULL;        /* audit session handle */
+static adt_termid_t    *tid = NULL;        /* peer terminal id */
+
+static void audit_login(void);
+static void audit_logout(void);
+static void audit_fail(int);
+
+/* Below is the sshd audit API Solaris adt interpretation */
+
+/*
+ * Called after a connection has been accepted but before any authentication
+ * has been attempted.
+ */
+/* ARGSUSED */
+void
+audit_connection_from(struct ssh *ssh, const char *host, int port)
+{
+    int peer = ssh_packet_get_connection_in(ssh);
+    adt_session_data_t    *ah = NULL;
+
+    if (adt_load_termid(peer, &tid) != 0) {
+        error("adt audit_connection_from: unable to load tid for %d:%s",
+            peer, strerror(errno));
+        goto err;
+    }
+    if (adt_start_session(&ah, NULL, 0) != 0) {
+        error("adt audit_connection_from: unable to start session "
+            "for %s:%d:%s", host, port, strerror(errno));
+        goto err;
+    }
+    if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT, 0,
+        ADT_NO_AUDIT, tid, ADT_SETTID) != 0) {
+        error("adt audit_connection_from: unable to set user "
+            "for %s:%d:%s", host, port, strerror(errno));
+        goto err;
+    }
+    if (adt_set_proc(ah) != 0) {
+        error("adt audit_connection_from: unable to set proc "
+            "for %s:%d:%s", host, port, strerror(errno));
+        goto err;
+    }
+    (void) adt_end_session(ah);
+    debug("adt audit_connection_from(%s, %d): peerfd=%d", host, port,
+        peer);
+    __auditd_debug("%d/%d:%d-adt audit_connection_from(%s, %d)ctxt=%p: "
+        "peerfd=%d\n", getpid(), getuid(), geteuid(), host, port,
+        (void *)the_authctxt, peer);
+    __audit_pidinfo();
+    return;
+
+err:
+    free(tid);
+    tid = NULL;
+    if (ah != NULL) {
+        (void) adt_end_session(ah);
+    }
+}
+
+/*
+ * Called when various events occur (see audit.h for a list of possible
+ * events and what they mean).
+ *
+ *    Entry    the_authcntxt
+ */
+void
+audit_event(struct ssh *ssh, ssh_audit_event_t event)
+{
+    static boolean_t logged_in = B_FALSE;    /* if user did login */
+    int fail = PAM_IGNORE;        /* default unset */
+    static boolean_t did_maxtries = B_FALSE; /* if interactive and abort */
+
+    debug("adt audit_event(%s)", audit_event_lookup(event));
+    __auditd_debug("%d/%d:%d-adt audit_event(%s/%s)ctxt=%p\n",
+        getpid(), getuid(), geteuid(), audit_event_lookup(event),
+        audit_username(), (void *)the_authctxt);
+    __audit_pidinfo();
+
+    switch (event) {
+    case SSH_AUTH_SUCCESS:        /* authentication success */
+        logged_in = B_TRUE;
+        audit_login();         /* ADT_ssh; */
+        return;
+
+    case SSH_CONNECTION_CLOSE:    /* connection closed, all done */
+        if (logged_in) {
+            audit_logout();        /* ADT_logout; */
+            logged_in = B_FALSE;
+        } else {
+            error("adt audit_event logout without login");
+        }
+        free(tid);
+        tid = NULL;
+        return;
+
+    /* Translate fail events to Solaris PAM errors */
+
+    /* auth2.c: userauth_finish as audit_event(SSH_LOGIN_EXCEED_MAXTRIES) */
+    /* auth1.c:do_authloop audit_event(SSH_LOGIN_EXCEED_MAXTRIES) */
+    case SSH_LOGIN_EXCEED_MAXTRIES:
+        fail = PAM_MAXTRIES;
+        did_maxtries = B_TRUE;
+        break;
+
+    /* auth2.c: userauth_finish as audit_event(SSH_LOGIN_ROOT_DENIED) */
+    /* auth1.c:do_authloop audit_event(SSH_LOGIN_ROOT_DENIED) */
+    case SSH_LOGIN_ROOT_DENIED:
+        fail = PAM_PERM_DENIED;
+        break;
+
+    /* auth2.c: input_userauth_request as audit_event(SSH_INVALID_USER) */
+    /* auth.c: getpwnamallow as audit_event(SSH_INVALID_USER) */
+    case SSH_INVALID_USER:
+        fail = PAM_USER_UNKNOWN;
+        break;
+
+    /* seems unused, but translate to the Solaris PAM error */
+    case SSH_NOLOGIN:
+        fail = PAM_ACCT_EXPIRED;
+        break;
+
+    /*
+     * auth.c in auth_log as it's walking through methods calls
+     * audit_classify_method(method) which maps
+     *
+     * none        -> SSH_AUTH_FAIL_NONE
+     * password    -> SSH_AUTH_FAIL_PASSWD
+     *
+     * publickey    -> SSH_AUTH_FAIL_PUBKEY
+     * rsa        -> SSH_AUTH_FAIL_PUBKEY
+     *
+     * keyboard-interactive    -> SSH_AUTH_FAIL_KBDINT
+     * challenge-response    -> SSH_AUTH_FAIL_KBDINT
+     *
+     * hostbased    -> SSH_AUTH_FAIL_HOSTBASED
+     * rhosts-rsa    -> SSH_AUTH_FAIL_HOSTBASED
+     *
+     * gssapi-with-mic    -> SSH_AUTH_FAIL_GSSAPI
+     *
+     * unknown method    -> SSH_AUDIT_UNKNOWN
+     */
+    /*
+     * see mon_table mon_dispatch_proto20[], mon_dispatch_postauth20[],
+     * mon_dispatch_proto15[], mon_dispatch_postauth15[]:
+     * MONITOR_REQ_AUDIT_EVENT
+     * called from monitor.c:mm_answer_audit_event()
+     * SSH_AUTH_FAIL_PUBKEY, SSH_AUTH_FAIL_HOSTBASED,
+     * SSH_AUTH_FAIL_GSSAPI, SSH_LOGIN_EXCEED_MAXTRIES,
+     * SSH_LOGIN_ROOT_DENIED, SSH_CONNECTION_CLOSE SSH_INVALID_USER
+     * monitor_wrap.c: mm_audit_event()
+     */
+    case SSH_AUTH_FAIL_NONE:    /* auth type none */
+    case SSH_AUTH_FAIL_PUBKEY:    /* authtype publickey */
+        break;
+
+    case SSH_AUTH_FAIL_PASSWD:    /* auth type password */
+    case SSH_AUTH_FAIL_KBDINT:    /* authtype keyboard-interactive */
+    case SSH_AUTH_FAIL_HOSTBASED:    /* auth type hostbased */
+    case SSH_AUTH_FAIL_GSSAPI:    /* auth type gssapi-with-mic */
+    case SSH_AUDIT_UNKNOWN:        /* auth type unknown */
+        fail = PAM_AUTH_ERR;
+        break;
+
+    /* sshd.c: cleanup_exit: server specific fatal cleanup */
+    case SSH_CONNECTION_ABANDON:    /* bailing with fatal error */
+        /*
+         * This seems to occur with OpenSSH client when
+         * the user login shell exits.
+         */
+        if (logged_in) {
+            audit_logout();        /* ADT_logout; */
+            logged_in = B_FALSE;
+            return;
+        } else if (!did_maxtries) {
+            fail = PAM_AUTHINFO_UNAVAIL;
+        } else {
+            /* reset saw max tries */
+            did_maxtries = FALSE;
+        }
+        free(tid);
+        tid = NULL;
+        break;
+
+    default:
+        error("adt audit_event: unknown event %d", event);
+        __auditd_debug("%d/%d:%d-unknown event %d",
+            getpid(), getuid(), geteuid(), event);
+        __audit_pidinfo();
+        break;
+    }
+    audit_fail(fail);
+}
+
+/*
+ * Called when a user session is started.  Argument is the tty allocated to
+ * the session, or NULL if no tty was allocated.
+ *
+ * Note that this may be called multiple times if multiple sessions are used
+ * within a single connection.
+ */
+/* ARGSUSED */
+void
+audit_session_open(struct logininfo *li)
+{
+    const char *t = li->line ? li->line : "(no tty)";
+
+    debug("adt audit_session_open: user=%s:tty=%s", audit_username(),
+        t);
+    __auditd_debug("%d/%d:%d-adt audit_session_open:ctxt=%p "
+        "user=%s:tty=%s\n", getpid(), getuid(), geteuid(),
+        (void *)the_authctxt, audit_username(), t);
+    __audit_pidinfo();
+}
+
+/*
+ * Called when a user session is closed.  Argument is the tty allocated to
+ * the session, or NULL if no tty was allocated.
+ *
+ * Note that this may be called multiple times if multiple sessions are used
+ * within a single connection.
+ */
+/* ARGSUSED */
+void
+audit_session_close(struct logininfo *li)
+{
+    const char *t = li->line ? li->line : "(no tty)";
+
+    debug("adt audit_session_close: user=%s:tty=%s", audit_username(),
+        t);
+    __auditd_debug("%d/%d:%d-adt audit_session_close:ctxt=%p "
+        "user=%s:tty=%s\n", getpid(), getuid(), geteuid(),
+        (void *)the_authctxt, audit_username(), t);
+    __audit_pidinfo();
+}
+
+/*
+ * This will be called when a user runs a non-interactive command.  Note that
+ * it may be called multiple times for a single connection since SSH2 allows
+ * multiple sessions within a single connection.
+ */
+/* ARGSUSED */
+void
+audit_run_command(const char *command)
+{
+    debug("adt audit_run_command: \"%s\"", command);
+    __auditd_debug("%d/%d:%d-adt audit_run_command:ctxt=%p \"%s\"\n",
+        getpid(), getuid(), geteuid(), (void *)the_authctxt, command);
+    __audit_pidinfo();
+}
+
+/*
+ * audit_login - audit successful login
+ *
+ *    Entry    the_authctxt should be valid ;-)
+ *        and pam_setcred called.
+ *        adt_info &  ADT_INFO_PW_SUCCESS if successful
+ *        password change.
+ *
+ *    Exit    ah = audit session established for audit_logout();
+ */
+static void
+audit_login(void)
+{
+    adt_event_data_t *event;
+    uid_t uid = ADT_NO_ATTRIB;
+    gid_t gid = (gid_t)ADT_NO_ATTRIB;
+    au_id_t    auid;
+
+    if ((the_authctxt != NULL) && (the_authctxt->valid != 0)) {
+        uid = the_authctxt->pw->pw_uid;
+        gid = the_authctxt->pw->pw_gid;
+    }
+
+    if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
+        error("adt_start_session: %s", strerror(errno));
+        return;
+    }
+
+    adt_get_auid(ah, &auid);
+
+    if (adt_set_user(ah, uid, gid, uid, gid, NULL,
+        auid == AU_NOAUDITID ? ADT_NEW : ADT_USER)) {
+        error("adt_set_user auid=%d, uid=%d", auid, uid);
+        (void) adt_end_session(ah);
+        ah = NULL;
+        free(tid);
+        tid = NULL;
+        return;
+    }
+    if ((event = adt_alloc_event(ah, ADT_ssh)) == NULL) {
+        error("adt_alloc_event(ADT_ssh): %s", strerror(errno));
+        return;
+    }
+    if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
+        error("adt_put_event(ADT_ssh, ADT_SUCCESS): %s",
+            strerror(errno));
+    }
+    /* should audit successful password change here */
+    adt_free_event(event);
+}
+
+/*
+ * audit_logout - audit the logout
+ *
+ *    Entry    ah = audit session.
+ */
+static void
+audit_logout(void)
+{
+    adt_event_data_t *event;
+
+    if ((event = adt_alloc_event(ah, ADT_logout)) == NULL) {
+        error("adt_alloc_event(ADT_logout): %s", strerror(errno));
+        return;
+    }
+    if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
+        error("adt_put_event(ADT_logout, ADT_SUCCESS): %s",
+            strerror(errno));
+    }
+    adt_free_event(event);
+    (void) adt_end_session(ah);
+    ah = NULL;
+}
+
+/*
+ * audit_fail - audit login failure.
+ *
+ *    Entry    the_authctxt assumed to have some info.
+ *            user = user who asked to be authenticated.
+ *        tid = connection audit TID set by audit_connect_from();
+ *
+ *    N.B.    pam_strerror() prototype takes a pam handle and error number.
+ *        At least on Solaris, pam_strerror never uses the pam handle.
+ *        Since there doesn't seem to be a pam handle available, this
+ *        code just uses NULL.
+ */
+static void
+audit_fail(int pamerr)
+{
+    adt_session_data_t *ah = NULL;
+    adt_event_data_t *event;
+    uid_t    uid = ADT_NO_ATTRIB;
+    gid_t    gid = (gid_t)ADT_NO_ATTRIB;
+
+    __auditd_debug("%d/%d:%d-audit_fail(%s) ctxt=%p\n",
+        getpid(), getuid(), geteuid(), pam_strerror(NULL, pamerr),
+        (void *)the_authctxt);
+    if (the_authctxt != NULL) {
+        uid_t     pwuid = ADT_NO_ATTRIB;
+
+        if (the_authctxt->pw != NULL) {
+            pwuid = the_authctxt->pw->pw_uid;
+        }
+        __auditd_debug("valid=%d, user=%s, uid=%d\n",
+            the_authctxt->valid, audit_username(), pwuid);
+    } else {
+        __auditd_debug("\tNo autxctxt\n");
+    }
+    __audit_pidinfo();
+    if (pamerr == PAM_IGNORE) {
+        return;
+    }
+    if ((the_authctxt != NULL) && (the_authctxt->valid != 0)) {
+        uid = the_authctxt->pw->pw_uid;
+        gid = the_authctxt->pw->pw_gid;
+    } else if ((the_authctxt != NULL) && (the_authctxt->user != NULL)) {
+        struct passwd *pw;
+
+        if ((pw = getpwnam(the_authctxt->user)) != NULL) {
+            uid = pw->pw_uid;
+            gid = pw->pw_gid;
+        }
+    }
+    if (adt_start_session(&ah, NULL, 0) != 0) {
+        error("adt_start_session(ADT_ssh, 0, fail=%s):"
+            " %s", pam_strerror(NULL, pamerr), strerror(errno));
+        __auditd_debug("%d/%d:%d-adt_start_session(ADT_ssh, "
+            "PROC_DATA, fail=%s): %s", getpid(), getuid(),
+            geteuid(), pam_strerror(NULL, pamerr),
+            strerror(errno));
+        return;
+    }
+    __auditd_debug("%d/%d:%d-audit_fail+start_session() ah=%p\n",
+        getpid(), getuid(), geteuid(), (void *)ah);
+    if (adt_set_user(ah, uid, gid, uid, gid, tid, ADT_NEW) != 0) {
+        error("adt_set_user(ADT_ssh, PROC_DATA, fail=%s): %s",
+            pam_strerror(NULL, pamerr), strerror(errno));
+        __auditd_debug("%d/%d:%d-adt_set_user(ADT_ssh, "
+            "PROC_DATA, fail=%s): %s", getpid(), getuid(),
+            geteuid(), pam_strerror(NULL, pamerr),
+            strerror(errno));
+        goto done;
+    }
+    __auditd_debug("%d/%d:%d-audit_fail+set_user() ah=%p\n", getpid(),
+        getuid(), geteuid(), (void *)ah);
+    if ((event = adt_alloc_event(ah, ADT_ssh)) == NULL) {
+        error("adt_alloc_event(ADT_ssh, fail=%s): %s",
+            pam_strerror(NULL, pamerr), strerror(errno));
+        __auditd_debug("%d/%d:%d-adt_set_user(ADT_ssh, 0, "
+            "fail=%s): %s", getpid(), getuid(), geteuid(),
+            pam_strerror(NULL, pamerr), strerror(errno));
+    } else if (adt_put_event(event, ADT_FAILURE,
+        ADT_FAIL_PAM + pamerr) != 0) {
+        error("adt_put_event(ADT_ssh, fail=%s): %s",
+            pam_strerror(NULL, pamerr), strerror(errno));
+        __auditd_debug("%d/%d:%d-adt_put_event(ADT_ssh, fail=%s): %s",
+            getpid(), getuid(), geteuid(), pam_strerror(NULL, pamerr),
+            strerror(errno));
+    }
+    __auditd_debug("%d/%d:%d-audit_fail+put_event() ah=%p\n", getpid(),
+        getuid(), geteuid(), (void *)ah);
+    /* should audit authentication with failed password change here. */
+    adt_free_event(event);
+done:
+    (void) adt_end_session(ah);
+}
+#endif    /* USE_SOLARIS_AUDIT */
--- hpn-ssh-hpn-18.3.1/audit.c.orig
+++ hpn-ssh-hpn-18.3.1/audit.c
@@ -120,7 +120,7 @@
  * has been attempted.
  */
 void
-audit_connection_from(const char *host, int port)
+audit_connection_from(struct ssh *, const char *host, int port)
 {
     debug("audit connection from %s port %d euid %d", host, port,
         (int)geteuid());
--- hpn-ssh-hpn-18.3.1/audit.h.orig
+++ hpn-ssh-hpn-18.3.1/audit.h
@@ -47,7 +47,7 @@
 };
 typedef enum ssh_audit_event_type ssh_audit_event_t;
-void    audit_connection_from(const char *, int);
+void    audit_connection_from(struct ssh *, const char *, int);
 void    audit_event(struct ssh *, ssh_audit_event_t);
 void    audit_session_open(struct logininfo *);
 void    audit_session_close(struct logininfo *);
--- hpn-ssh-hpn-18.3.1/configure.ac.orig
+++ hpn-ssh-hpn-18.3.1/configure.ac
@@ -1761,7 +1761,7 @@
 AUDIT_MODULE=none
 AC_ARG_WITH([audit],
-    [  --with-audit=module     Enable audit support (modules=debug,bsm,linux)],
+    [  --with-audit=module     Enable audit support (modules=debug,bsm,linux,solaris)],
     [
       AC_MSG_CHECKING([for supported audit module])
       case "$withval" in
@@ -1798,6 +1798,13 @@
         SSHDLIBS="$SSHDLIBS -laudit"
         AC_DEFINE([USE_LINUX_AUDIT], [1], [Use Linux audit module])
         ;;
+      solaris)
+        AC_MSG_RESULT([solaris])
+        AUDIT_MODULE=solaris
+        AC_CHECK_HEADERS([bsm/adt.h])
+        SSHDLIBS="$SSHDLIBS -lbsm"
+        AC_DEFINE([USE_SOLARIS_AUDIT], [1], [Use Solaris audit module])
+        ;;
       debug)
         AUDIT_MODULE=debug
         AC_MSG_RESULT([debug])
--- hpn-ssh-hpn-18.3.1/defines.h.orig
+++ hpn-ssh-hpn-18.3.1/defines.h
@@ -715,6 +715,11 @@
 # define CUSTOM_SSH_AUDIT_EVENTS
 #endif
+#ifdef USE_SOLARIS_AUDIT
+# define SSH_AUDIT_EVENTS
+# define CUSTOM_SSH_AUDIT_EVENTS
+#endif
+
 #if !defined(HAVE___func__) && defined(HAVE___FUNCTION__)
 #  define __func__ __FUNCTION__
 #elif !defined(HAVE___func__)
--- hpn-ssh-hpn-18.3.1/sshd.c.orig
+++ hpn-ssh-hpn-18.3.1/sshd.c
@@ -2216,7 +2216,7 @@
     remote_ip = ssh_remote_ipaddr(ssh);
 #ifdef SSH_AUDIT_EVENTS
-    audit_connection_from(remote_ip, remote_port);
+    audit_connection_from(ssh, remote_ip, remote_port);
 #endif
     rdomain = ssh_packet_rdomain_in(ssh);
@@ -2308,8 +2308,10 @@
     }
 #ifdef SSH_AUDIT_EVENTS
+#ifndef USE_SOLARIS_AUDIT
     audit_event(ssh, SSH_AUTH_SUCCESS);
 #endif
+#endif
 #ifdef GSSAPI
     if (options.gss_authentication) {
@@ -2338,6 +2340,10 @@
         do_pam_session(ssh);
     }
 #endif
+#ifdef    USE_SOLARIS_AUDIT
+    /* Audit should take place after all successful pam */
+    audit_event(ssh, SSH_AUTH_SUCCESS);
+#endif    /* USE_SOLARIS_AUDIT */
     /*
      * In privilege separation, we fork another child and prepare
components/network/hpn-ssh/patches/0015-Enable-login-to-a-role-if-PAM-is-ok-with-it.patch
New file
@@ -0,0 +1,135 @@
--- hpn-ssh-hpn-18.3.1/auth-pam.c.orig
+++ hpn-ssh-hpn-18.3.1/auth-pam.c
@@ -1213,6 +1213,20 @@
     return (sshpam_account_status);
 }
+#ifdef HAVE_PAM_AUSER
+void
+do_pam_set_auser(const char* auser)
+{
+    if (auser != NULL) {
+        debug("PAM: setting PAM_AUSER to \"%s\"", auser);
+        sshpam_err = pam_set_item(sshpam_handle, PAM_AUSER, auser);
+        if (sshpam_err != PAM_SUCCESS)
+            error("PAM: failed to set PAM_AUSER: %s",
+                pam_strerror(sshpam_handle, sshpam_err));
+    }
+}
+#endif
+
 void
 do_pam_setcred(int init)
 {
--- hpn-ssh-hpn-18.3.1/auth-pam.h.orig
+++ hpn-ssh-hpn-18.3.1/auth-pam.h
@@ -44,4 +44,9 @@
 void sshpam_set_maxtries_reached(int);
 int is_pam_session_open(void);
+#ifdef HAVE_PAM_AUSER
+void do_pam_set_auser(const char *);
+#endif
+void do_pam_set_tty(const char *);
+
 #endif /* USE_PAM */
--- hpn-ssh-hpn-18.3.1/auth.h.orig
+++ hpn-ssh-hpn-18.3.1/auth.h
@@ -98,6 +98,9 @@
 #ifdef PAM_ENHANCEMENT
     char        *authmethod_name;
 #endif
+#ifdef HAVE_PAM_AUSER
+    char        *auser;
+#endif
 };
 /*
--- hpn-ssh-hpn-18.3.1/auth2-hostbased.c.orig
+++ hpn-ssh-hpn-18.3.1/auth2-hostbased.c
@@ -80,6 +80,9 @@
     debug("signature:");
     sshbuf_dump_data(sig, slen, stderr);
 #endif
+#ifdef HAVE_PAM_AUSER
+    authctxt->auser = NULL;
+#endif
     pktype = sshkey_type_from_name(pkalg);
     if (pktype == KEY_UNSPEC) {
         /* this is perfectly legal */
@@ -151,6 +154,13 @@
         sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0)
         authenticated = 1;
+#ifdef HAVE_PAM_AUSER
+    if (authenticated) {
+        authctxt->auser = cuser;
+        cuser = NULL;
+    }
+#endif
+
     auth2_record_key(authctxt, authenticated, key);
     sshbuf_free(b);
 done:
--- hpn-ssh-hpn-18.3.1/auth2.c.orig
+++ hpn-ssh-hpn-18.3.1/auth2.c
@@ -427,6 +427,14 @@
 #endif
     }
+#ifdef HAVE_PAM_AUSER
+    if (!use_privsep) {
+        do_pam_set_auser(authctxt->auser);
+        free(authctxt->auser);
+        authctxt->auser = NULL;
+    }
+#endif
+
     if (authenticated && options.num_auth_methods != 0) {
 #if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
--- hpn-ssh-hpn-18.3.1/monitor.c.orig
+++ hpn-ssh-hpn-18.3.1/monitor.c
@@ -391,6 +391,12 @@
         }
     }
+#if defined(HAVE_PAM_AUSER) && defined(USE_PAM)
+    if (hostbased_cuser != NULL) {
+        free(hostbased_cuser);
+        hostbased_cuser = NULL;
+    }
+#endif
     if (!authctxt->valid)
         fatal_f("authenticated invalid user");
     if (strcmp(auth_method, "unknown") == 0)
@@ -594,14 +600,16 @@
 {
     /* reset state */
     free(key_blob);
+#if !defined(HAVE_PAM_AUSER) || !defined(USE_PAM)
     free(hostbased_cuser);
+    hostbased_cuser = NULL;
+#endif
     free(hostbased_chost);
     sshauthopt_free(key_opts);
     key_blob = NULL;
     key_bloblen = 0;
     key_blobtype = MM_NOKEY;
     key_opts = NULL;
-    hostbased_cuser = NULL;
     hostbased_chost = NULL;
 }
@@ -1074,6 +1082,11 @@
     if (!options.use_pam)
         fatal("%s: PAM not enabled", __func__);
+#ifdef HAVE_PAM_AUSER
+    if (hostbased_cuser != NULL)
+        do_pam_set_auser(hostbased_cuser);
+#endif
+
     ret = do_pam_account();
     if ((r = sshbuf_put_u32(m, ret)) != 0 ||
components/network/hpn-ssh/patches/0016-PAM-setcred-failures.patch
New file
@@ -0,0 +1,39 @@
--- hpn-ssh-hpn-18.3.1/auth-pam.c.orig
+++ hpn-ssh-hpn-18.3.1/auth-pam.c
@@ -1246,12 +1246,19 @@
         sshpam_cred_established = 1;
         return;
     }
+
+#ifdef PAM_BUGFIX
+    /* Server will fatal out when pam_setcred() failed. */
+    fatal("PAM: pam_setcred(): %s", pam_strerror(sshpam_handle,
+        sshpam_err));
+#else /* orig */
     if (sshpam_authenticated)
         fatal("PAM: pam_setcred(): %s",
             pam_strerror(sshpam_handle, sshpam_err));
     else
         debug("PAM: pam_setcred(): %s",
             pam_strerror(sshpam_handle, sshpam_err));
+#endif /* PAM_BUGFIX */
 }
 static int
@@ -1347,10 +1354,16 @@
     if (sshpam_err == PAM_SUCCESS)
         sshpam_session_open = 1;
     else {
+#ifdef PAM_BUGFIX
+        /* Server will fatal out when pam_open_session() failed */
+        fatal("PAM: pam_open_session(): %s",
+            pam_strerror(sshpam_handle, sshpam_err));
+#else /* orig */
         sshpam_session_open = 0;
         auth_restrict_session(ssh);
         error("PAM: pam_open_session(): %s",
             pam_strerror(sshpam_handle, sshpam_err));
+#endif /* PAM_BUGFIX */
     }
 }
components/network/hpn-ssh/patches/0017-Don-t-call-do_pam_setcred-twice.patch
New file
@@ -0,0 +1,33 @@
# This issue has been raised with the upstream OpenSSH community:
#
# 2426 OpenSSH doesn't need the second call to do_pam_setcred() on non-Linux
#      platforms
# https://bugzilla.mindrot.org/show_bug.cgi?id=2426
#
# The OpenSSH maintainers added a call to do_pam_setcred() in
# platform_setusercontext_post_groups() with no corresponding bugID along with
# a befuddling comment that initgroups(3C) wipes out supplementary groups:
#
#https://anongit.mindrot.org/openssh.git/commit/platform.c?id=cc12418e18242ce1f61d7035da4956274ba13a96
#
# This only applies in the Linux world if the LinuxPAM pam_group(8) module
# has been installed and configured which allows one to assign additional
# secondary groups to a user using /etc/security/group.conf in addition to
# /etc/group.  To confuse things a bit more, there is an OpenPAM PAM module
# of the same name, pam_group(8), which has different functionality, it
# performs access control based on group membership.
#
# In short, this additional call to do_pam_setcred() is Linux-specific and
# shouldn't be called on Solaris.
#
--- hpn-ssh-hpn-18.3.1/platform.c.orig
+++ hpn-ssh-hpn-18.3.1/platform.c
@@ -146,7 +146,7 @@
 void
 platform_setusercontext_post_groups(struct passwd *pw)
 {
-#if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
+#if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) && !defined(PAM_SUN_CODEBASE)
     /*
      * PAM credentials may take the form of supplementary groups.
      * These will have been wiped by the above initgroups() call.
components/network/hpn-ssh/patches/0018-Per-session-xauthfile.patch
New file
@@ -0,0 +1,229 @@
This patch is to fix a X11 connection failure when a user's home directory
is read-only.
Oracle contributed back this fix to the OpenSSH upstream community. For
more information, see https://bugzilla.mindrot.org/show_bug.cgi?id=2440
In the future, if this fix is accepted by the upsteam in a later release, we
will remove this patch when we upgrade to that release.
--- hpn-ssh-hpn-18.3.1/session.c.orig
+++ hpn-ssh-hpn-18.3.1/session.c
@@ -62,6 +62,10 @@
 #include <unistd.h>
 #include <limits.h>
+#ifdef PER_SESSION_XAUTHFILE
+#include <libgen.h>
+#endif
+
 #include "openbsd-compat/sys-queue.h"
 #include "xmalloc.h"
 #include "ssh.h"
@@ -129,6 +133,11 @@
 static int session_pty_req(struct ssh *, Session *);
+#ifdef PER_SESSION_XAUTHFILE
+void   session_xauthfile_cleanup(Session *);
+void   cleanup_all_session_xauthfile();
+#endif
+
 /* import */
 extern ServerOptions options;
 extern char *__progname;
@@ -1104,6 +1113,11 @@
             auth_sock_name);
+#ifdef PER_SESSION_XAUTHFILE
+        if (s->auth_file != NULL)
+                child_set_env(&env, &envsize, "XAUTHORITY", s->auth_file);
+#endif
+
     /* Set custom environment options from pubkey authentication. */
     if (options.permit_user_env) {
         for (n = 0 ; n < auth_opts->nenv; n++) {
@@ -2006,6 +2020,11 @@
     int r, success;
     u_char single_connection = 0;
+#ifdef PER_SESSION_XAUTHFILE
+    int fd;
+    char xauthdir[] = "/tmp/ssh-xauth-XXXXXX";
+#endif
+
     if (s->auth_proto != NULL || s->auth_data != NULL) {
         error("session_x11_req: session %d: "
             "x11 forwarding already active", s->self);
@@ -2020,19 +2039,82 @@
     s->single_connection = single_connection;
-    if (xauth_valid_string(s->auth_proto) &&
-        xauth_valid_string(s->auth_data))
-        success = session_setup_x11fwd(ssh, s);
-    else {
+    if (!xauth_valid_string(s->auth_proto) ||
+        !xauth_valid_string(s->auth_data)) {
         success = 0;
         error("Invalid X11 forwarding data");
+        goto out;
     }
+
+#ifdef PER_SESSION_XAUTHFILE
+    /*
+     * Create per session X authority file in the /tmp directory.
+     *
+     * If mkdtemp() or open() fails then s->auth_file remains NULL which
+     * means that we won't set XAUTHORITY variable in child's environment
+     * and xauth(1) will use the default location for the authority file.
+     */
+    temporarily_use_uid(s->pw);
+    if (mkdtemp(xauthdir) != NULL) {
+        s->auth_file = xmalloc(MAXPATHLEN);
+        if (snprintf(s->auth_file, MAXPATHLEN, "%s/xauthfile",
+            xauthdir) >= MAXPATHLEN) {
+            error("temporary X authority file name was too long "
+                "for the buffer allocated");
+            success = 0;
+            restore_uid();
+            goto out;
+        }
+        /*
+         * we don't want that "creating new authority file" message to
+         * be printed by xauth(1) so we must create that file
+         * beforehand.
+         */
+        if ((fd = open(s->auth_file, O_CREAT | O_EXCL | O_RDONLY,
+            S_IRUSR | S_IWUSR)) == -1) {
+            error("failed to create the temporary X authority "
+                "file %s: %.100s; will use the default one",
+                s->auth_file, strerror(errno));
+            free(s->auth_file);
+            s->auth_file = NULL;
+            if (rmdir(xauthdir) == -1) {
+                error("cannot remove xauth directory "
+                    "%s: %.100s", xauthdir, strerror(errno));
+            }
+        } else {
+            if (close(fd) != 0) {
+                error("close() failed on temporary X authority "
+                    "file: %s", strerror(errno));
+                success = 0;
+                restore_uid();
+                goto out;
+            }
+            debug("temporary X authority file %s created",
+                s->auth_file);
+            debug("session number = %d", s->self);
+        }
+    } else {
+        error("failed to create a directory for the temporary X "
+            "authority file: %.100s; will use the default xauth file",
+            strerror(errno));
+    }
+    restore_uid();
+#endif
+
+    success = session_setup_x11fwd(ssh, s);
+
+out:
     if (!success) {
         free(s->auth_proto);
         free(s->auth_data);
         s->auth_proto = NULL;
         s->auth_data = NULL;
+#ifdef PER_SESSION_XAUTHFILE
+        free(s->auth_file);
+        s->auth_file = NULL;
+#endif
     }
+
     return success;
 }
@@ -2312,6 +2394,51 @@
     PRIVSEP(session_pty_cleanup2(s));
 }
+#ifdef PER_SESSION_XAUTHFILE
+/*
+ * We use a different temporary X authority file per session so we should
+ * remove those files when cleanup_exit() is called.
+ */
+void
+session_xauthfile_cleanup(Session *s)
+{
+    if (s == NULL || s->auth_file == NULL) {
+        return;
+    }
+
+    debug("session_xauthfile_cleanup: session %d removing %s", s->self,
+        s->auth_file);
+
+    if (unlink(s->auth_file) == -1) {
+        error("session_xauthfile_cleanup: cannot remove xauth file "
+            "%s: %.100s", s->auth_file, strerror(errno));
+        return;
+    }
+
+    /* dirname() will modify s->auth_file but that's ok */
+    if (rmdir(dirname(s->auth_file)) == -1) {
+        error("session_xauthfile_cleanup: "
+            "cannot remove xauth directory %s: %.100s",
+            s->auth_file, strerror(errno));
+        return;
+    }
+    free(s->auth_file);
+    s->auth_file = NULL;
+}
+
+/*
+ * This is called by do_cleanup() when cleanup_exit() is called.
+ */
+void
+cleanup_all_session_xauthfile()
+{
+    int i;
+    for (i = 0; i < sessions_nalloc; i++) {
+                session_xauthfile_cleanup(&sessions[i]);
+    }
+}
+#endif
+
 static char *
 sig2name(int sig)
 {
@@ -2459,6 +2586,9 @@
     free(s->auth_display);
     free(s->auth_data);
     free(s->auth_proto);
+#ifdef PER_SESSION_XAUTHFILE
+    session_xauthfile_cleanup(s);
+#endif
     free(s->subsys);
     if (s->env != NULL) {
         for (i = 0; i < s->num_env; i++) {
@@ -2714,6 +2844,10 @@
         auth_info_file = NULL;
     }
+#ifdef PER_SESSION_XAUTHFILE
+    cleanup_all_session_xauthfile();
+#endif
+
     /*
      * Cleanup ptys/utmp only if privsep is disabled,
      * or if running in monitor.
--- hpn-ssh-hpn-18.3.1/session.h.orig
+++ hpn-ssh-hpn-18.3.1/session.h
@@ -50,6 +50,9 @@
     char    *auth_display;
     char    *auth_proto;
     char    *auth_data;
+#ifdef PER_SESSION_XAUTHFILE
+    char    *auth_file;    /* xauth(1) authority file */
+#endif
     int    single_connection;
     int    chanid;
components/network/hpn-ssh/patches/0019-PubKeyPlugin-support.patch
New file
@@ -0,0 +1,239 @@
This adds the PubKeyPlugin directive and associated code from
SunSSH, allowing an in-process shared library to be called
into to check public keys for authentication.
--- hpn-ssh-hpn-18.3.1/auth2-pubkey.c.orig
+++ hpn-ssh-hpn-18.3.1/auth2-pubkey.c
@@ -23,6 +23,11 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2015 Joyent, Inc.
+ * Use is subject to license terms.
+ */
 #include "includes.h"
@@ -41,11 +46,13 @@
 #include <time.h>
 #include <unistd.h>
 #include <limits.h>
+#include <dlfcn.h>
 #include "xmalloc.h"
 #include "ssh.h"
 #include "ssh2.h"
 #include "packet.h"
+#include "digest.h"
 #include "kex.h"
 #include "sshbuf.h"
 #include "log.h"
@@ -84,6 +91,15 @@
     return ret;
 }
+static const char *RSA_SYM_NAME = "sshd_user_rsa_key_allowed";
+static const char *ECDSA_SYM_NAME = "sshd_user_ecdsa_key_allowed";
+typedef int (*RSA_SYM)(struct passwd *, RSA *, const char *);
+typedef int (*ECDSA_SYM)(struct passwd *, EC_KEY *, const char *);
+
+static const char *UNIV_SYM_NAME = "sshd_user_key_allowed";
+typedef int (*UNIV_SYM)(struct passwd *, const char *,
+    const u_char *, size_t);
+
 static int
 userauth_pubkey(struct ssh *ssh, const char *method)
 {
@@ -745,6 +761,124 @@
     return found_key;
 }
+/**
+ * Checks whether or not access is allowed based on a plugin specified
+ * in sshd_config (PubKeyPlugin).
+ *
+ * Note that this expects a symbol in the loaded library that takes
+ * the current user (pwd entry), the current RSA key and it's fingerprint.
+ * The symbol is expected to return 1 on success and 0 on failure.
+ *
+ * While we could optimize this code to dlopen once in the process' lifetime,
+ * sshd is already a slow beast, so this is really not a concern.
+ * The overhead is basically a rounding error compared to everything else, and
+ * it keeps this code minimally invasive.
+ */
+static int
+user_key_allowed_from_plugin(struct passwd *pw, struct sshkey *key)
+{
+    RSA_SYM rsa_sym = NULL;
+    ECDSA_SYM ecdsa_sym = NULL;
+    UNIV_SYM univ_sym = NULL;
+    char *fp = NULL;
+    char *argfp = NULL;
+    void *handle = NULL;
+    int success = 0;
+
+    if (options.pubkey_plugin == NULL || pw == NULL || key == NULL ||
+        (key->type != KEY_RSA &&
+        key->type != KEY_DSA && key->type != KEY_ECDSA))
+        return success;
+
+    handle = dlopen(options.pubkey_plugin, RTLD_NOW);
+    if (handle == NULL) {
+        debug("Unable to open library %s: %s", options.pubkey_plugin,
+        dlerror());
+        goto out;
+    }
+
+    /*
+     * If we have the new-style universal symbol for checking keys, use
+     * that instead of the old-style per-key-type symbols.
+     */
+    univ_sym = (UNIV_SYM)dlsym(handle, UNIV_SYM_NAME);
+    if (univ_sym != NULL) {
+        u_char *blob;
+        const char *type = sshkey_type(key);
+        size_t len = 0;
+        if (sshkey_to_blob(key, &blob, &len) != 0) {
+            debug("failed to convert key to rfc4253 format");
+            goto out;
+        }
+        debug("Invoking %s from %s", UNIV_SYM_NAME,
+            options.pubkey_plugin);
+        success = (*univ_sym)(pw, type, blob, len);
+        debug("pubkeyplugin returned: %d", success);
+        goto out;
+    }
+
+    /* Otherwise, continue with the old-style fingerprint symbols. */
+    fp = sshkey_fingerprint(key, SSH_DIGEST_MD5, SSH_FP_HEX);
+    if (fp == NULL) {
+        debug("failed to generate fingerprint");
+        goto out;
+    }
+    if (strncmp(fp, "MD5:", 4) != 0) {
+        debug("fingerprint not in MD5:hex format");
+        goto out;
+    }
+    /* give the plugin the string without leading MD5: */
+    argfp = fp + 4;
+
+    switch (key->type) {
+    case KEY_RSA:
+        rsa_sym = (RSA_SYM)dlsym(handle, RSA_SYM_NAME);
+        if (rsa_sym == NULL) {
+            debug("Unable to resolve symbol %s: %s", RSA_SYM_NAME,
+            dlerror());
+            goto out;
+        }
+        debug2("Invoking %s from %s", RSA_SYM_NAME,
+            options.pubkey_plugin);
+        success = (*rsa_sym)(pw, key->rsa, argfp);
+        break;
+    case KEY_ECDSA:
+        ecdsa_sym = (ECDSA_SYM)dlsym(handle, ECDSA_SYM_NAME);
+        if (ecdsa_sym == NULL) {
+            debug("Unable to resolve symbol %s: %s", ECDSA_SYM_NAME,
+            dlerror());
+            goto out;
+        }
+        debug2("Invoking %s from %s", ECDSA_SYM_NAME,
+            options.pubkey_plugin);
+        success = (*ecdsa_sym)(pw, key->ecdsa, argfp);
+        break;
+    default:
+        debug2("user_key_plugins only support RSA and ECDSA keys");
+    }
+
+    debug("pubkeyplugin returned: %d", success);
+
+out:
+    if (handle != NULL) {
+        dlclose(handle);
+        ecdsa_sym = NULL;
+        rsa_sym = NULL;
+        univ_sym = NULL;
+        handle = NULL;
+    }
+
+    if (success)
+        verbose("Found matching %s key: %s", sshkey_type(key), fp);
+
+    if (fp != NULL) {
+        free(fp);
+        fp = NULL;
+    }
+
+    return success;
+}
+
 /*
  * Check whether key authenticates and authorises the user.
  */
@@ -796,6 +930,10 @@
     sshauthopt_free(opts);
     opts = NULL;
+    success = user_key_allowed_from_plugin(pw, key);
+    if (success > 0)
+        goto out;
+
     if ((success = user_key_command_allowed2(pw, key, remote_ip,
         remote_host, conn_id, rdomain, &opts)) != 0)
         goto out;
--- hpn-ssh-hpn-18.3.1/servconf.c.orig
+++ hpn-ssh-hpn-18.3.1/servconf.c
@@ -215,6 +215,7 @@
      */
     options->pam_service_per_authmethod = 1;
 #endif
+    options->pubkey_plugin = NULL;
 }
 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -577,6 +578,7 @@
     sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
     sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
     sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout,
+    sPubKeyPlugin,
     sDeprecated, sIgnore, sUnsupported
 } ServerOpCodes;
@@ -748,6 +750,7 @@
     { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
     { "rdomain", sRDomain, SSHCFG_ALL },
     { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
+    { "pubkeyplugin", sPubKeyPlugin, SSHCFG_ALL },
     { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
     { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
     { "channeltimeout", sChannelTimeout, SSHCFG_ALL },
@@ -2661,6 +2664,18 @@
         }
         break;
+    case sPubKeyPlugin:
+        /*
+         * Can't use parse_filename, as we need to support plain
+         * names which dlopen will find on our lib path.
+         */
+        arg = strdelim(&str);
+        if (!arg || *arg == '\0')
+            fatal("%s line %d: missing file name.",
+                filename, linenum);
+        options->pubkey_plugin = xstrdup(arg);
+        break;
+
     case sDeprecated:
     case sIgnore:
     case sUnsupported:
--- hpn-ssh-hpn-18.3.1/servconf.h.orig
+++ hpn-ssh-hpn-18.3.1/servconf.h
@@ -240,6 +240,7 @@
     int    fingerprint_hash;
     int    expose_userauth_info;
+    char    *pubkey_plugin;
     u_int64_t timing_secret;
     char   *sk_provider;
     int    required_rsa_size;    /* minimum size of RSA keys */
components/network/hpn-ssh/patches/0027-Set-default-sshd-options-based-on-etc-default-login.patch
New file
@@ -0,0 +1,128 @@
--- hpn-ssh-hpn-18.3.1/pathnames.h.orig
+++ hpn-ssh-hpn-18.3.1/pathnames.h
@@ -42,6 +42,7 @@
 #define _PATH_HOST_XMSS_KEY_FILE    SSHDIR "/ssh_host_xmss_key"
 #define _PATH_HOST_RSA_KEY_FILE        SSHDIR "/ssh_host_rsa_key"
 #define _PATH_DH_MODULI            SSHDIR "/moduli"
+#define _PATH_DEFAULT_LOGIN        ETCDIR "/default/login"
 #ifndef _PATH_SSH_PROGRAM
 #define _PATH_SSH_PROGRAM        "/usr/bin/hpnssh"
--- hpn-ssh-hpn-18.3.1/servconf.c.orig
+++ hpn-ssh-hpn-18.3.1/servconf.c
@@ -36,6 +36,7 @@
 #include <unistd.h>
 #include <limits.h>
 #include <stdarg.h>
+#include <deflt.h>
 #include <errno.h>
 #ifdef HAVE_UTIL_H
 #include <util.h>
@@ -225,6 +226,64 @@
     return o == NULL || strcasecmp(o, "none") == 0;
 }
+/*
+ * Reads /etc/default/login and defaults several ServerOptions:
+ *
+ * PermitRootLogin
+ * PermitEmptyPasswords
+ * LoginGraceTime
+ *
+ * CONSOLE=*      -> PermitRootLogin=without-password
+ * #CONSOLE=*     -> PermitRootLogin=yes
+ *
+ * PASSREQ=YES    -> PermitEmptyPasswords=no
+ * PASSREQ=NO     -> PermitEmptyPasswords=yes
+ * #PASSREQ=*     -> PermitEmptyPasswords=no
+ *
+ * TIMEOUT=<secs> -> LoginGraceTime=<secs>
+ * #TIMEOUT=<secs> -> LoginGraceTime=300
+ */
+static void
+deflt_fill_default_server_options(ServerOptions *options)
+{
+    int    flags;
+    char    *ptr;
+
+    if (defopen(_PATH_DEFAULT_LOGIN))
+        return;
+
+    /* Ignore case */
+    flags = defcntl(DC_GETFLAGS, 0);
+    TURNOFF(flags, DC_CASE);
+    (void) defcntl(DC_SETFLAGS, flags);
+
+    if (options->permit_root_login == PERMIT_NOT_SET &&
+        (ptr = defread("CONSOLE=")) != NULL)
+        options->permit_root_login = PERMIT_NO_PASSWD;
+
+    if (options->permit_empty_passwd == -1 &&
+        (ptr = defread("PASSREQ=")) != NULL) {
+        if (strcasecmp("YES", ptr) == 0)
+            options->permit_empty_passwd = 0;
+        else if (strcasecmp("NO", ptr) == 0)
+            options->permit_empty_passwd = 1;
+    }
+
+    if (options->max_authtries == -1 &&
+        (ptr = defread("RETRIES=")) != NULL) {
+        options->max_authtries = atoi(ptr);
+    }
+
+    if (options->login_grace_time == -1) {
+        if ((ptr = defread("TIMEOUT=")) != NULL)
+            options->login_grace_time = (unsigned)atoi(ptr);
+        else
+            options->login_grace_time = 300;
+    }
+
+    (void) defopen((char *)NULL);
+}
+
 static void
 assemble_algorithms(ServerOptions *o)
 {
@@ -305,6 +364,8 @@
         options->use_pam = 0;
 #endif
+    deflt_fill_default_server_options(options);
+
     /* Standard Options */
     if (options->num_host_key_files == 0) {
         /* fill default hostkeys for protocols */
--- hpn-ssh-hpn-18.3.1/hpnsshd_config.5.orig
+++ hpn-ssh-hpn-18.3.1/hpnsshd_config.5
@@ -1350,7 +1350,14 @@
 connection.
 Once the number of failures reaches half this value,
 additional failures are logged.
-The default is 6.
+The default is 6, or the value given by
+.Dq RETRIES=
+in the file
+.Pa /etc/default/login ,
+if available
+.Po see
+.Xr login 1
+.Pc .
 .It Cm MaxSessions
 Specifies the maximum number of open shell, login or subsystem (e.g. sftp)
 sessions permitted per network connection.
@@ -1438,7 +1445,14 @@
 When password authentication is allowed, it specifies whether the
 server allows login to accounts with empty password strings.
 The default is
-.Cm no .
+.Cm no
+unless
+.Dq PASSREQ=YES
+is present in
+.Pa /etc/default/login
+.Po see
+.Xr login 1
+.Pc .
 .It Cm PermitListen
 Specifies the addresses/ports on which a remote TCP port forwarding may listen.
 The listen specification must be one of the following forms:
components/network/hpn-ssh/patches/0028-Compatibility-for-SunSSH_1.5-should-include-old-DH-K.patch
New file
@@ -0,0 +1,73 @@
We use the kex compat mechanism here to recognise old SunSSH
versions and present a kex proposal that always includes the
dh-group14 and -group1 algorithms.
Without this, an old SunSSH client cannot connect to our
new daemon.
--- hpn-ssh-hpn-18.3.1/compat.c.orig
+++ hpn-ssh-hpn-18.3.1/compat.c
@@ -36,6 +36,7 @@
 #include "compat.h"
 #include "log.h"
 #include "match.h"
+#include "sshbuf.h"
 /* determine bug flags from SSH protocol banner */
 void
@@ -51,8 +52,12 @@
           "OpenSSH_3.1*",    SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR|
                     SSH_BUG_SIGTYPE},
         { "OpenSSH_3.*",    SSH_OLD_FORWARD_ADDR|SSH_BUG_SIGTYPE },
-        { "Sun_SSH_1.0*",    SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
-                    SSH_BUG_SIGTYPE},
+        { "Sun_SSH_1.2*,"
+          "Sun_SSH_1.3*,"
+          "Sun_SSH_1.4*,"
+          "Sun_SSH_1.5*",    SSH_OLD_DHGEX},
+        { "Sun_SSH_1.*",    SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
+                    SSH_BUG_SIGTYPE|SSH_OLD_DHGEX},
         { "OpenSSH_2*,"
           "OpenSSH_3*,"
           "OpenSSH_4*",        SSH_BUG_SIGTYPE },
@@ -167,6 +172,31 @@
     debug_f("no match: %s", version);
 }
+/*
+ * Adds an algorithm to the end of a proposal list, only if the algorithm is
+ * not already present.
+ */
+static char *
+append_proposal(char *proposal, const char *append)
+{
+    struct sshbuf *b;
+    char *fix_prop;
+
+    if (strstr(proposal, append) != NULL)
+        return proposal;
+    if ((b = sshbuf_new()) == NULL)
+        fatal("sshbuf_new()");
+    sshbuf_put(b, proposal, strlen(proposal));
+    if (sshbuf_len(b) > 0)
+        sshbuf_put(b, ",", 1);
+    sshbuf_put(b, append, strlen(append));
+    sshbuf_put(b, "\0", 1);
+    fix_prop = sshbuf_dup_string(b);
+    sshbuf_free(b);
+
+    return fix_prop;
+}
+
 /* Always returns pointer to allocated memory, caller must free. */
 char *
 compat_kex_proposal(struct ssh *ssh, const char *p)
@@ -185,6 +215,8 @@
             "diffie-hellman-group-exchange-sha256,"
             "diffie-hellman-group-exchange-sha1")) == NULL)
             fatal("match_filter_denylist failed");
+        p = append_proposal(p, "diffie-hellman-group14-sha1");
+        p = append_proposal(p, "diffie-hellman-group1-sha1");
         free(cp);
         cp = cp2;
     }
components/network/hpn-ssh/patches/0029-Accept-LANG-and-LC_-environment-variables-from-clien.patch
New file
@@ -0,0 +1,155 @@
This preserves most of the old SunSSH locale negotiation
behaviour (at least the parts that are most commonly used).
--- hpn-ssh-hpn-18.3.1/servconf.c.orig
+++ hpn-ssh-hpn-18.3.1/servconf.c
@@ -174,7 +174,7 @@
     options->client_alive_interval = -1;
     options->client_alive_count_max = -1;
     options->num_authkeys_files = 0;
-    options->num_accept_env = 0;
+    options->num_accept_env = -1;
     options->num_setenv = 0;
     options->permit_tun = -1;
     options->permitted_opens = NULL;
@@ -494,6 +494,33 @@
         options->max_sessions = DEFAULT_SESSIONS_MAX;
     if (options->use_dns == -1)
         options->use_dns = 0;
+    if (options->num_accept_env == -1) {
+        options->num_accept_env = 0;
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LANG");
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LC_ALL");
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LC_CTYPE");
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LC_COLLATE");
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LC_TIME");
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LC_NUMERIC");
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LC_MONETARY");
+        opt_array_append("[default]", 0, "AcceptEnv",
+            &options->accept_env, &options->num_accept_env,
+            "LC_MESSAGES");
+    }
     if (options->client_alive_interval == -1)
         options->client_alive_interval = 0;
     if (options->client_alive_count_max == -1)
@@ -2233,8 +2260,12 @@
             if (*arg == '\0' || strchr(arg, '=') != NULL)
                 fatal("%s line %d: Invalid environment name.",
                     filename, linenum);
+            if (options->num_accept_env == -1)
+                options->num_accept_env = 0;
             if (!*activep)
                 continue;
+            if (strcmp(arg, "none") == 0)
+                continue;
             opt_array_append(filename, linenum, keyword,
                 &options->accept_env, &options->num_accept_env,
                 arg);
@@ -2971,7 +3002,7 @@
 } while(0)
 #define M_CP_STRARRAYOPT(s, num_s) do {\
     u_int i; \
-    if (src->num_s != 0) { \
+    if (src->num_s != 0 && src->num_s != -1) { \
         for (i = 0; i < dst->num_s; i++) \
             free(dst->s[i]); \
         free(dst->s); \
--- hpn-ssh-hpn-18.3.1/session.c.orig
+++ hpn-ssh-hpn-18.3.1/session.c
@@ -848,6 +848,18 @@
 }
 /*
+ * If the given environment variable is set in the daemon's environment,
+ * push it into the new child as well. If it is unset, do nothing.
+ */
+static void
+child_inherit_env(char ***envp, u_int *envsizep, const char *name)
+{
+    char *value;
+    if ((value = getenv(name)) != NULL)
+        child_set_env(envp, envsizep, 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 '#')
@@ -1031,6 +1043,16 @@
     ssh_gssapi_do_child(&env, &envsize);
 #endif
+    /* Default to the system-wide locale/language settings. */
+    child_inherit_env(&env, &envsize, "LANG");
+    child_inherit_env(&env, &envsize, "LC_ALL");
+    child_inherit_env(&env, &envsize, "LC_CTYPE");
+    child_inherit_env(&env, &envsize, "LC_COLLATE");
+    child_inherit_env(&env, &envsize, "LC_TIME");
+    child_inherit_env(&env, &envsize, "LC_NUMERIC");
+    child_inherit_env(&env, &envsize, "LC_MONETARY");
+    child_inherit_env(&env, &envsize, "LC_MESSAGES");
+
     /* Set basic environment. */
     for (i = 0; i < s->num_env; i++)
         child_set_env(&env, &envsize, s->env[i].name, s->env[i].val);
@@ -1074,8 +1096,7 @@
     /* Normal systems set SHELL by default. */
     child_set_env(&env, &envsize, "SHELL", shell);
-    if (getenv("TZ"))
-        child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+    child_inherit_env(&env, &envsize, "TZ");
     if (s->term)
         child_set_env(&env, &envsize, "TERM", s->term);
     if (s->display)
--- hpn-ssh-hpn-18.3.1/sshd_config.orig
+++ hpn-ssh-hpn-18.3.1/sshd_config
@@ -26,6 +26,10 @@
 #SyslogFacility AUTH
 #LogLevel INFO
+# Use the client's locale/language settings
+#AcceptEnv LANG LC_ALL LC_CTYPE LC_COLLATE LC_TIME LC_NUMERIC
+#AcceptEnv LC_MONETARY LC_MESSAGES
+
 # Authentication:
 #LoginGraceTime 2m
--- hpn-ssh-hpn-18.3.1/hpnsshd_config.5.orig
+++ hpn-ssh-hpn-18.3.1/hpnsshd_config.5
@@ -96,7 +96,20 @@
 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.
+The default is to accept only
+.Ev LANG
+and the
+.Ev LC_*
+family of environment variables. If any
+.Cm AcceptEnv
+directives are present in your config file, they will replace this default
+.Po
+ie, only the variables you list will be passed into the session's
+.Xr environ 7
+.Pc .
+You can also use an argument of
+.Dq none
+to specify that no environment variables should be passed.
 .It Cm AddressFamily
 Specifies which address family should be used by
 .Xr sshd 8 .
components/network/hpn-ssh/patches/0031-Restore-tcpwrappers-libwrap-support.patch
New file
@@ -0,0 +1,141 @@
--- hpn-ssh-hpn-18.3.1/configure.ac.orig
+++ hpn-ssh-hpn-18.3.1/configure.ac
@@ -1656,6 +1656,62 @@
     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 to use ldns
 LDNS_MSG="no"
 AC_ARG_WITH(ldns,
@@ -5683,6 +5739,7 @@
 echo "                   OSF SIA support: $SIA_MSG"
 echo "                 KerberosV support: $KRB5_MSG"
 echo "                   SELinux support: $SELINUX_MSG"
+echo "              TCP Wrappers support: $TCPW_MSG"
 echo "                   libedit support: $LIBEDIT_MSG"
 echo "                   libldns support: $LDNS_MSG"
 echo "  Solaris process contract support: $SPC_MSG"
--- hpn-ssh-hpn-18.3.1/hpnsshd.8.orig
+++ hpn-ssh-hpn-18.3.1/hpnsshd.8
@@ -924,6 +924,12 @@
 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 hpnssh 1 ) .
@@ -1053,6 +1059,7 @@
 .Xr hpnssh-keygen 1 ,
 .Xr hpnssh-keyscan 1 ,
 .Xr chroot 2 ,
+.Xr hosts_access 5 ,
 .Xr login.conf 5 ,
 .Xr moduli 5 ,
 .Xr hpnsshd_config 5 ,
--- hpn-ssh-hpn-18.3.1/sshd.c.orig
+++ hpn-ssh-hpn-18.3.1/sshd.c
@@ -128,6 +128,17 @@
 #include "srclimit.h"
 #include "dh.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)
@@ -2218,6 +2229,24 @@
 #ifdef SSH_AUDIT_EVENTS
     audit_connection_from(ssh, 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 (ssh_packet_connection_is_on_socket(ssh)) {
+        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 */
     rdomain = ssh_packet_rdomain_in(ssh);
components/network/hpn-ssh/patches/1002-ssh-copy-id-use-correct-shell.patch
New file
@@ -0,0 +1,8 @@
--- hpn-ssh-hpn-18.3.1/contrib/hpnssh-copy-id.orig
+++ hpn-ssh-hpn-18.3.1/contrib/hpnssh-copy-id
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # Copyright (c) 1999-2023 Philip Hands <phil@hands.com>
 #               2021 Carlos Rodríguez Gili <carlos.rodriguez-gili@upc.edu>
components/network/hpn-ssh/patches/2000-sshd_config-default.patch
New file
@@ -0,0 +1,28 @@
sshd_config customizations for OpenIndiana.
--- hpn-ssh-hpn-18.3.1/sshd_config.orig
+++ hpn-ssh-hpn-18.3.1/sshd_config
@@ -34,6 +34,7 @@
 #LoginGraceTime 2m
 #PermitRootLogin prohibit-password
+PermitRootLogin no
 #StrictModes yes
 #MaxAuthTries 6
 #MaxSessions 10
@@ -78,10 +79,15 @@
 #AllowTcpForwarding yes
 #GatewayPorts no
 #X11Forwarding no
+X11Forwarding yes
 #X11DisplayOffset 10
 #X11UseLocalhost yes
 #PermitTTY yes
+
 #PrintMotd yes
+# On OpenIndiana it is assumed that the login shell will print /etc/motd
+PrintMotd no
+
 #PrintLastLog yes
 #TCPKeepAlive yes
 #PermitUserEnvironment no
components/network/hpn-ssh/pkg5
New file
@@ -0,0 +1,20 @@
{
    "dependencies": [
        "SUNWcs",
        "library/libedit",
        "library/security/openssl-31",
        "library/zlib",
        "network/ssh-askpass",
        "service/security/kerberos-5",
        "shell/bash",
        "shell/ksh93",
        "system/library",
        "system/library/security/gss",
        "x11/session/xauth"
    ],
    "fmris": [
        "network/hpn-ssh",
        "service/network/hpn-ssh"
    ],
    "name": "hpn-ssh"
}
doc/reserved_uids_and_gids.md
@@ -23,6 +23,7 @@
19    | minidlna
21    | ftp
22    | sshd
24    | hpnsshd
25    | smmsp
27    | postfix
30    | opendkim
@@ -96,6 +97,7 @@
20    | games
21    | ftp
22    | sshd
24    | hpnsshd
25    | smmsp
27    | postfix
28    | postdrop