Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162308877
D58083.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
36 KB
Referenced Files
None
Subscribers
None
D58083.diff
View Options
Index: INSTALL
===================================================================
--- INSTALL
+++ INSTALL
@@ -81,6 +81,15 @@
http://www.jmknoble.net/software/x11-ssh-askpass/
+TCP Wrappers:
+
+If you wish to use the TCP wrappers functionality you will need at least
+tcpd.h and libwrap.a, either in the standard include and library paths,
+or in the directory specified by --with-tcp-wrappers. Version 7.6 is
+known to work.
+
+http://ftp.porcupine.org/pub/security/index.html
+
LibEdit:
sftp supports command-line editing via NetBSD's libedit. If your platform
@@ -199,6 +208,9 @@
--with-osfsia, --without-osfsia will enable or disable OSF1's Security
Integration Architecture. The default for OSF1 machines is enable.
+--with-tcp-wrappers will enable TCP Wrappers (/etc/hosts.allow|deny)
+support.
+
--with-utmpx enables utmpx support. utmpx support is automatic for
some platforms.
Index: auth-pam.c
===================================================================
--- auth-pam.c
+++ auth-pam.c
@@ -100,6 +100,7 @@
#endif
#include "monitor_wrap.h"
#include "srclimit.h"
+#include "blocklist_client.h"
extern ServerOptions options;
extern struct sshbuf *loginmsg;
@@ -916,6 +917,8 @@
sshbuf_free(buffer);
return (0);
}
+ BLOCKLIST_NOTIFY(NULL, BLOCKLIST_AUTH_FAIL,
+ "PAM illegal user");
error("PAM: %s for %s%.100s from %.100s", msg,
sshpam_authctxt->valid ? "" : "illegal user ",
sshpam_authctxt->user, sshpam_rhost);
Index: auth.c
===================================================================
--- auth.c
+++ auth.c
@@ -73,6 +73,7 @@
#include "monitor_wrap.h"
#include "ssherr.h"
#include "channels.h"
+#include "blocklist_client.h"
/* import */
extern ServerOptions options;
@@ -283,8 +284,12 @@
authmsg = "Postponed";
else if (partial)
authmsg = "Partial";
- else
+ else {
authmsg = authenticated ? "Accepted" : "Failed";
+ if (authenticated)
+ BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_OK,
+ "Authenticated");
+ }
if ((extra = format_method_key(authctxt)) == NULL) {
if (authctxt->auth_method_info != NULL)
@@ -332,6 +337,7 @@
{
Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Maximum attempts exceeded");
error("maximum authentication attempts exceeded for "
"%s%.100s from %.200s port %d ssh2",
authctxt->valid ? "" : "invalid user ",
@@ -492,6 +498,7 @@
aix_restoreauthdb();
#endif
if (pw == NULL) {
+ BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Invalid user");
logit("Invalid user %.100s from %.100s port %d",
user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
#ifdef CUSTOM_FAILED_LOGIN
Index: configure.ac
===================================================================
--- configure.ac
+++ configure.ac
@@ -1148,6 +1148,7 @@
[NetBSD read function is sometimes redirected, breaking atomicio comparisons against it])
;;
*-*-freebsd*)
+ SKIP_DISABLE_LASTLOG_DEFINE=yes
AC_DEFINE([LOCKED_PASSWD_PREFIX], ["*LOCKED*"], [Account locked with pw(1)])
AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
AC_DEFINE([SSH_TUN_COMPAT_AF], [1],
@@ -1833,6 +1834,61 @@
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,
@@ -3482,11 +3538,11 @@
LIBFIDO2=`$PKGCONFIG --libs libfido2`
CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libfido2`"
else
- LIBFIDO2="-lfido2 -lcbor"
+ LIBFIDO2="-lprivatefido2 -lprivatecbor"
fi
OTHERLIBS=`echo $LIBFIDO2 | sed 's/-lfido2//'`
fido2_error=
- AC_CHECK_LIB([fido2], [fido_init],
+ AC_CHECK_LIB([privatefido2], [fido_init],
[ ],
[ fido2_error="missing/unusable libfido2" ],
[ $OTHERLIBS ]
@@ -5936,6 +5992,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"
Index: monitor.c
===================================================================
--- monitor.c
+++ monitor.c
@@ -75,6 +75,8 @@
#include "misc.h"
#include "servconf.h"
#include "monitor.h"
+#include "blocklist_client.h"
+
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
@@ -348,16 +350,24 @@
}
}
if (authctxt->failures > options.max_authtries) {
+ BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL,
+ "Too many authentication attempts");
/* Shouldn't happen */
fatal_f("privsep child made too many authentication "
"attempts");
}
}
- if (!authctxt->valid)
+ if (!authctxt->valid) {
+ BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL,
+ "Authenticated invalid user");
fatal_f("authenticated invalid user");
- if (strcmp(auth_method, "unknown") == 0)
+ }
+ if (strcmp(auth_method, "unknown") == 0) {
+ BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL,
+ "Authentication method name unknown");
fatal_f("authentication method name unknown");
+ }
debug_f("user %s authenticated by privileged process", authctxt->user);
auth_attempted = 0;
Index: openbsd-compat/libressl-api-compat.c
===================================================================
--- openbsd-compat/libressl-api-compat.c
+++ openbsd-compat/libressl-api-compat.c
@@ -26,6 +26,7 @@
#include <openssl/evp.h>
#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
+# ifndef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV
int
EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len)
{
@@ -44,14 +45,15 @@
if (len != 0) {
if (iv == NULL)
return 0;
-# ifdef HAVE_EVP_CIPHER_CTX_IV
+# ifdef HAVE_EVP_CIPHER_CTX_IV
memcpy(iv, EVP_CIPHER_CTX_iv(ctx), len);
-# else
+# else
memcpy(iv, ctx->iv, len);
-# endif /* HAVE_EVP_CIPHER_CTX_IV */
+# endif /* HAVE_EVP_CIPHER_CTX_IV */
}
return 1;
}
+# endif /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */
#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
#ifndef HAVE_EVP_CIPHER_CTX_SET_IV
Index: pathnames.h
===================================================================
--- pathnames.h
+++ pathnames.h
@@ -134,7 +134,7 @@
* Default location of askpass
*/
#ifndef _PATH_SSH_ASKPASS_DEFAULT
-#define _PATH_SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass"
+#define _PATH_SSH_ASKPASS_DEFAULT "/usr/local/bin/ssh-askpass"
#endif
/* Location of ssh-keysign for hostbased authentication */
@@ -154,7 +154,7 @@
/* xauth for X11 forwarding */
#ifndef _PATH_XAUTH
-#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
+#define _PATH_XAUTH "/usr/local/bin/xauth"
#endif
/* UNIX domain socket for X11 server; displaynum will replace %u */
Index: regress/unittests/sshkey/test_sshkey.c
===================================================================
--- regress/unittests/sshkey/test_sshkey.c
+++ regress/unittests/sshkey/test_sshkey.c
@@ -8,6 +8,7 @@
#include "includes.h"
#include <sys/types.h>
+#include <paths.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -79,7 +80,7 @@
critopts = sshbuf_new();
ASSERT_PTR_NE(critopts, NULL);
- put_opt(critopts, "force-command", "/usr/local/bin/nethack");
+ put_opt(critopts, "force-command", _PATH_LOCALBASE "/bin/nethack");
put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1");
exts = sshbuf_new();
Index: servconf.h
===================================================================
--- servconf.h
+++ servconf.h
@@ -166,7 +166,7 @@
SSHCONF_STRING(pid_file, PidFile, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \
SSHCONF_STRING(moduli_file, ModuliFile, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \
SSHCONF_INT(login_grace_time, LoginGraceTime, SSHCFG_GLOBAL, NULL, SSHD_DEFAULT_LOGIN_GRACE_TIME, SSHCFG_COPY_NONE) \
-SSHCONF_INT(permit_root_login, PermitRootLogin, SSHCFG_ALL, multistate_permitrootlogin, PERMIT_NO_PASSWD, SSHCFG_COPY_MATCH) \
+SSHCONF_INT(permit_root_login, PermitRootLogin, SSHCFG_ALL, multistate_permitrootlogin, PERMIT_NO, SSHCFG_COPY_MATCH) \
SSHCONF_INT(ignore_rhosts, IgnoreRhosts, SSHCFG_ALL, multistate_ignore_rhosts, 1, SSHCFG_COPY_MATCH) \
SSHCONF_INTFLAG(ignore_user_known_hosts, IgnoreUserKnownHosts, SSHCFG_GLOBAL, 0, SSHCFG_COPY_NONE) \
SSHCONF_INTFLAG(print_motd, PrintMotd, SSHCFG_GLOBAL, 1, SSHCFG_COPY_NONE) \
@@ -190,7 +190,7 @@
SSHCONF_INT(pubkey_auth_options, PubkeyAuthOptions, SSHCFG_ALL, NULL, 0, SSHCFG_COPY_MATCH) \
SSHCONF_INTFLAG(pubkey_authentication, PubkeyAuthentication, SSHCFG_ALL, 1, SSHCFG_COPY_MATCH) \
SSHCONF_STRING(pubkey_accepted_algos, PubkeyAcceptedAlgorithms, SSHCFG_ALL, SSHCFG_COPY_MATCH) \
-SSHCONF_INTFLAG(password_authentication, PasswordAuthentication, SSHCFG_ALL, 1, SSHCFG_COPY_MATCH) \
+SSHCONF_INTFLAG(password_authentication, PasswordAuthentication, SSHCFG_ALL, 0, SSHCFG_COPY_MATCH) \
SSHCONF_INTFLAG(kbd_interactive_authentication, KbdInteractiveAuthentication, SSHCFG_ALL, 1, SSHCFG_COPY_MATCH) \
SSHCONF_INTFLAG(permit_empty_passwd, PermitEmptyPasswords, SSHCFG_ALL, 0, SSHCFG_COPY_MATCH) \
SSHCONF_INT(compression, Compression, SSHCFG_GLOBAL, multistate_compression, SSHD_DEFAULT_COMPRESSION, SSHCFG_COPY_NONE) \
@@ -209,7 +209,7 @@
SSHCONF_INT(max_authtries, MaxAuthTries, SSHCFG_ALL, NULL, DEFAULT_AUTH_FAIL_MAX, SSHCFG_COPY_MATCH) \
SSHCONF_INT(max_sessions, MaxSessions, SSHCFG_ALL, NULL, DEFAULT_SESSIONS_MAX, SSHCFG_COPY_MATCH) \
SSHCONF_STRING(banner, Banner, SSHCFG_ALL, SSHCFG_COPY_MATCH) \
-SSHCONF_INTFLAG(use_dns, UseDNS, SSHCFG_GLOBAL, 0, SSHCFG_COPY_NONE) \
+SSHCONF_INTFLAG(use_dns, UseDNS, SSHCFG_GLOBAL, 1, SSHCFG_COPY_NONE) \
SSHCONF_INT(client_alive_interval, ClientAliveInterval, SSHCFG_ALL, NULL, 0, SSHCFG_COPY_MATCH) \
SSHCONF_INT(client_alive_count_max, ClientAliveCountMax, SSHCFG_ALL, NULL, 3, SSHCFG_COPY_MATCH) \
SSHCONF_STRARRAY(authorized_keys_files, num_authkeys_files, AuthorizedKeysFile, SSHCFG_ALL, SSHCFG_COPY_MATCH) \
@@ -235,7 +235,8 @@
SSHCONF_INT(unused_connection_timeout, UnusedConnectionTimeout, SSHCFG_ALL, NULL, 0, SSHCFG_COPY_MATCH) \
SSHCONF_STRING(sshd_session_path, SshdSessionPath, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \
SSHCONF_STRING(sshd_auth_path, SshdAuthPath, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \
-SSHCONF_INTFLAG(refuse_connection, RefuseConnection, SSHCFG_ALL, 0, SSHCFG_COPY_MATCH)
+SSHCONF_INTFLAG(refuse_connection, RefuseConnection, SSHCFG_ALL, 0, SSHCFG_COPY_MATCH) \
+SSHCONF_INTFLAG(use_blocklist, UseBlocklist, SSHCFG_ALL, 0, SSHCFG_COPY_MATCH)
#define SSHD_CONFIG_ENTRIES_LEGACY \
SSHCONF_DEPRECATE(ServerKeyBits, SSHCFG_GLOBAL, SSHCONF_DEPRECATED) \
@@ -260,7 +261,8 @@
SSHCONF_ALIAS(DSAAuthentication, PubkeyAuthentication, SSHCFG_GLOBAL) \
SSHCONF_ALIAS(ChallengeResponseAuthentication, KbdInteractiveAuthentication, SSHCFG_ALL) \
SSHCONF_ALIAS(SKeyAuthentication, KbdInteractiveAuthentication, SSHCFG_ALL) \
-SSHCONF_ALIAS(KeepAlive, TCPKeepAlive, SSHCFG_GLOBAL)
+SSHCONF_ALIAS(KeepAlive, TCPKeepAlive, SSHCFG_GLOBAL) \
+SSHCONF_ALIAS(UseBlacklist, UseBlocklist, SSHCFG_GLOBAL)
#define SSHD_CONFIG_ENTRIES_BASE \
SSHD_CONFIG_ENTRIES_CUSTOM \
@@ -272,7 +274,7 @@
#ifdef USE_PAM
#define SSHD_CONFIG_ENTRIES_PAM \
-SSHCONF_INTFLAG(use_pam, UsePAM, SSHCFG_GLOBAL, 0, SSHCFG_COPY_NONE) \
+SSHCONF_INTFLAG(use_pam, UsePAM, SSHCFG_GLOBAL, 1, SSHCFG_COPY_NONE) \
SSHCONF_STRING(pam_service_name, PAMServiceName, SSHCFG_GLOBAL, SSHCFG_COPY_NONE)
#else
#define SSHD_CONFIG_ENTRIES_PAM \
Index: servconf.c
===================================================================
--- servconf.c
+++ servconf.c
@@ -242,12 +242,18 @@
free(def_sig);
}
+static const char *defaultkey = "[default]";
+
void
servconf_add_hostkey(const char *file, const int line,
ServerOptions *options, const char *path, int userprovided)
{
char *apath = derelativise_path(path);
+ if (file == defaultkey && access(apath, R_OK) != 0) {
+ free(apath);
+ return;
+ }
opt_array_append2(file, line, "HostKey",
&options->host_key_files, &options->host_key_file_userprovided,
&options->num_host_key_files, apath, userprovided);
@@ -311,17 +317,19 @@
if (options->num_host_key_files == 0) {
/* fill default hostkeys */
- servconf_add_hostkey("[default]", 0, options,
+ servconf_add_hostkey(defaultkey, 0, options,
_PATH_HOST_RSA_KEY_FILE, 0);
#ifdef OPENSSL_HAS_ECC
- servconf_add_hostkey("[default]", 0, options,
+ servconf_add_hostkey(defaultkey, 0, options,
_PATH_HOST_ECDSA_KEY_FILE, 0);
#endif
- servconf_add_hostkey("[default]", 0, options,
+ servconf_add_hostkey(defaultkey, 0, options,
_PATH_HOST_ED25519_KEY_FILE, 0);
servconf_add_hostkey("[default]", 0, options,
_PATH_HOST_MLDSA44_ED25519_KEY_FILE, 0);
}
+ if (options->num_host_key_files == 0)
+ fatal("No host key files found");
/* No certificates by default */
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
@@ -384,11 +392,11 @@
if (options->per_source_penalty.penalty_max < 0.0)
options->per_source_penalty.penalty_max = 600.0;
if (options->num_authkeys_files == 0) {
- opt_array_append("[default]", 0, "AuthorizedKeysFiles",
+ opt_array_append(defaultkey, 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS);
- opt_array_append("[default]", 0, "AuthorizedKeysFiles",
+ opt_array_append(defaultkey, 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS2);
@@ -398,7 +406,7 @@
if (options->ip_qos_bulk == -1)
options->ip_qos_bulk = IPTOS_DSCP_CS0;
if (options->version_addendum == NULL)
- options->version_addendum = xstrdup("");
+ options->version_addendum = xstrdup(SSH_VERSION_FREEBSD);
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)
@@ -2554,6 +2562,10 @@
multistate_ptr = multistate_flag;
goto parse_multistate;
+ case sUseBlocklist:
+ intptr = &options->use_blocklist;
+ goto parse_flag;
+
case sDeprecated:
case sIgnore:
case sUnsupported:
@@ -4245,6 +4257,7 @@
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
dump_cfg_fmtint(sRefuseConnection, o->refuse_connection);
+ dump_cfg_fmtint(sUseBlocklist, o->use_blocklist);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
Index: session.c
===================================================================
--- session.c
+++ session.c
@@ -940,6 +940,9 @@
struct passwd *pw = s->pw;
#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
char *path = NULL;
+#else
+ extern char **environ;
+ char **senv, **var, *val;
#endif
/* Initialize the environment. */
@@ -961,6 +964,9 @@
}
#endif
+ if (getenv("TZ"))
+ child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+
#ifdef GSSAPI
/* Allow any GSSAPI methods that we've used to alter
* the child's environment as they see fit
@@ -978,11 +984,30 @@
child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
#endif
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
+ snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name);
+ child_set_env(&env, &envsize, "MAIL", buf);
#ifdef HAVE_LOGIN_CAP
- if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
- child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
- else
- child_set_env(&env, &envsize, "PATH", getenv("PATH"));
+ child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
+ child_set_env(&env, &envsize, "TERM", "su");
+ /*
+ * Temporarily swap out our real environment with an empty one,
+ * let setusercontext() apply any environment variables defined
+ * for the user's login class, copy those variables to the child,
+ * free the temporary environment, and restore the original.
+ */
+ senv = environ;
+ environ = xmalloc(sizeof(*environ));
+ *environ = NULL;
+ (void)setusercontext(lc, pw, pw->pw_uid, LOGIN_SETENV|LOGIN_SETPATH);
+ for (var = environ; *var != NULL; ++var) {
+ if ((val = strchr(*var, '=')) != NULL) {
+ *val++ = '\0';
+ child_set_env(&env, &envsize, *var, val);
+ }
+ free(*var);
+ }
+ free(environ);
+ environ = senv;
#else /* HAVE_LOGIN_CAP */
# ifndef HAVE_CYGWIN
/*
@@ -1002,17 +1027,9 @@
# endif /* HAVE_CYGWIN */
#endif /* HAVE_LOGIN_CAP */
- if (!options.use_pam) {
- snprintf(buf, sizeof buf, "%.200s/%.50s",
- _PATH_MAILDIR, pw->pw_name);
- child_set_env(&env, &envsize, "MAIL", buf);
- }
-
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
- if (getenv("TZ"))
- child_set_env(&env, &envsize, "TZ", getenv("TZ"));
#ifdef HAVE_LOGIN_CAP
if (getenv("XDG_RUNTIME_DIR")) {
child_set_env(&env, &envsize, "XDG_RUNTIME_DIR",
@@ -1232,7 +1249,8 @@
do_nologin(struct passwd *pw)
{
FILE *f = NULL;
- char buf[1024], *nl, *def_nl = _PATH_NOLOGIN;
+ const char *nl;
+ char buf[1024], *def_nl = _PATH_NOLOGIN;
struct stat sb;
#ifdef HAVE_LOGIN_CAP
@@ -1322,7 +1340,7 @@
if (platform_privileged_uidswap()) {
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid,
- (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
+ (LOGIN_SETALL & ~(LOGIN_SETENV|LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
perror("unable to set user context");
exit(1);
}
Index: ssh-agent.1
===================================================================
--- ssh-agent.1
+++ ssh-agent.1
@@ -43,7 +43,7 @@
.Sh SYNOPSIS
.Nm ssh-agent
.Op Fl c | s
-.Op Fl \&DdTU
+.Op Fl \&DdTUx
.Op Fl a Ar bind_address
.Op Fl E Ar fingerprint_hash
.Op Fl O Ar option
@@ -205,6 +205,8 @@
If this option is given twice,
.Nm
will delete stale agent sockets regardless of the host name that created them.
+.It Fl x
+Exit after the last client has disconnected.
.It Ar command Op Ar arg ...
If a command (and optional arguments) is given,
this is executed as a subprocess of the agent.
Index: ssh-agent.c
===================================================================
--- ssh-agent.c
+++ ssh-agent.c
@@ -196,11 +196,27 @@
static int restrict_websafe = 1;
static char *websafe_allowlist;
+/*
+ * Client connection count; incremented in new_socket() and decremented in
+ * close_socket(). When it reaches 0, ssh-agent will exit. Since it is
+ * normally initialized to 1, it will never reach 0. However, if the -x
+ * option is specified, it is initialized to 0 in main(); in that case,
+ * ssh-agent will exit as soon as it has had at least one client but no
+ * longer has any.
+ */
+static int xcount = 1;
+
static void
close_socket(SocketEntry *e)
{
size_t i;
+ int last = 0;
+ if (e->type == AUTH_CONNECTION) {
+ debug("xcount %d -> %d", xcount, xcount - 1);
+ if (--xcount == 0)
+ last = 1;
+ }
close(e->fd);
sshbuf_free(e->input);
sshbuf_free(e->output);
@@ -213,6 +229,8 @@
memset(e, '\0', sizeof(*e));
e->fd = -1;
e->type = AUTH_UNUSED;
+ if (last)
+ cleanup_exit(0);
}
static void
@@ -1932,6 +1950,10 @@
debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" :
(type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN"));
+ if (type == AUTH_CONNECTION) {
+ debug("xcount %d -> %d", xcount, xcount + 1);
+ ++xcount;
+ }
set_nonblock(fd);
if (fd > max_fd)
@@ -2225,7 +2247,7 @@
usage(void)
{
fprintf(stderr,
- "usage: ssh-agent [-c | -s] [-DdTU] [-a bind_address] [-E fingerprint_hash]\n"
+ "usage: ssh-agent [-c | -s] [-DdTUx] [-a bind_address] [-E fingerprint_hash]\n"
" [-O option] [-P allowed_providers] [-t life]\n"
" ssh-agent [-TU] [-a bind_address] [-E fingerprint_hash] [-O option]\n"
" [-P allowed_providers] [-t life] command [arg ...]\n"
@@ -2267,6 +2289,7 @@
/* drop */
(void)setegid(getgid());
(void)setgid(getgid());
+ setuid(geteuid());
platform_disable_tracing(0); /* strict=no */
@@ -2278,7 +2301,7 @@
__progname = ssh_get_progname(av[0]);
seed_rng();
- while ((ch = getopt(ac, av, "cDdksTuUVE:a:O:P:t:")) != -1) {
+ while ((ch = getopt(ac, av, "cDdksTuUVxE:a:O:P:t:")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
@@ -2348,6 +2371,9 @@
fprintf(stderr, "%s, %s\n",
SSH_VERSION, SSH_OPENSSL_VERSION);
exit(0);
+ case 'x':
+ xcount = 0;
+ break;
default:
usage();
}
Index: ssh-gss.h
===================================================================
--- ssh-gss.h
+++ ssh-gss.h
@@ -28,10 +28,10 @@
#ifdef GSSAPI
-#ifdef HAVE_GSSAPI_H
-#include <gssapi.h>
-#elif defined(HAVE_GSSAPI_GSSAPI_H)
+#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
+#elif defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
#endif
#ifdef KRB5
Index: ssh.c
===================================================================
--- ssh.c
+++ ssh.c
@@ -1445,6 +1445,26 @@
cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost,
cinfo->remhost, cinfo->portstr, cinfo->remuser, cinfo->jmphost);
+ /* Find canonic host name. */
+ if (strchr(host, '.') == NULL) {
+ struct addrinfo hints;
+ struct addrinfo *ai = NULL;
+ int errgai;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = options.address_family;
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_STREAM;
+ errgai = getaddrinfo(host, NULL, &hints, &ai);
+ if (errgai == 0) {
+ if (ai->ai_canonname != NULL) {
+ free(host);
+ host = xstrdup(ai->ai_canonname);
+ }
+ freeaddrinfo(ai);
+ }
+ }
+
/*
* Expand tokens in arguments. NB. LocalCommand is expanded later,
* after port-forwarding is set up, so it may pick up any local
Index: ssh_config.5
===================================================================
--- ssh_config.5
+++ ssh_config.5
@@ -2266,7 +2266,7 @@
.Xr xauth 1
program.
The default is
-.Pa /usr/X11R6/bin/xauth .
+.Pa /usr/local/bin/xauth .
.El
.Sh PATTERNS
A
Index: sshconnect.c
===================================================================
--- sshconnect.c
+++ sshconnect.c
@@ -487,6 +487,8 @@
memset(ntop, 0, sizeof(ntop));
memset(strport, 0, sizeof(strport));
+ int inet_supported = feature_present("inet");
+ int inet6_supported = feature_present("inet6");
for (attempt = 0; attempt < connection_attempts; attempt++) {
if (attempt > 0) {
/* Sleep a moment before retrying. */
@@ -511,6 +513,13 @@
errno = oerrno;
continue;
}
+ if ((ai->ai_family == AF_INET && !inet_supported) ||
+ (ai->ai_family == AF_INET6 && !inet6_supported)) {
+ debug2_f("skipping address [%s]:%s: "
+ "unsupported address family", ntop, strport);
+ errno = EAFNOSUPPORT;
+ continue;
+ }
if (options.address_family != AF_UNSPEC &&
ai->ai_family != options.address_family) {
debug2_f("skipping address [%s]:%s: "
Index: sshd-auth.c
===================================================================
--- sshd-auth.c
+++ sshd-auth.c
@@ -96,6 +96,7 @@
#include "srclimit.h"
#include "ssh-sandbox.h"
#include "dh.h"
+#include "blocklist_client.h"
/* Privsep fds */
#define PRIVSEP_MONITOR_FD (STDERR_FILENO + 1)
@@ -786,8 +787,10 @@
free(hkalgs);
if ((r = kex_exchange_identification(ssh, -1,
- options.version_addendum)) != 0)
+ options.version_addendum)) != 0) {
+ BLOCKLIST_NOTIFY(ssh, BLOCKLIST_AUTH_FAIL, "Banner exchange");
sshpkt_fatal(ssh, r, "banner exchange");
+ }
mm_sshkey_setcompat(ssh); /* tell monitor */
if ((ssh->compat & SSH_BUG_NOREKEY))
Index: sshd-session.c
===================================================================
--- sshd-session.c
+++ sshd-session.c
@@ -95,6 +95,7 @@
#include "sk-api.h"
#include "srclimit.h"
#include "dh.h"
+#include "blocklist_client.h"
/* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
@@ -1149,6 +1150,8 @@
ssh_signal(SIGCHLD, SIG_DFL);
ssh_signal(SIGINT, SIG_DFL);
+ BLOCKLIST_INIT();
+
/*
* Register our connection. This turns encryption off because we do
* not have a key.
@@ -1178,6 +1181,11 @@
cleanup_exit(255);
}
+#ifdef HAVE_LOGIN_CAP
+ /* Also caches remote hostname for sandboxed child. */
+ auth_get_canonical_hostname(ssh, options.use_dns);
+#endif
+
/*
* The rest of the code depends on the fact that
* ssh_remote_ipaddr() caches the remote ip, even if
@@ -1362,8 +1370,11 @@
audit_event(the_active_state, SSH_CONNECTION_ABANDON);
#endif
/* Override default fatal exit value when auth was attempted */
- if (i == 255 && monitor_auth_attempted())
+ if (i == 255 && monitor_auth_attempted()) {
+ BLOCKLIST_NOTIFY(the_active_state, BLOCKLIST_AUTH_FAIL,
+ "Fatal exit");
_exit(EXIT_AUTH_ATTEMPTED);
+ }
if (i == 255 && monitor_invalid_user())
_exit(EXIT_INVALID_USER);
_exit(i);
Index: sshd.8
===================================================================
--- sshd.8
+++ sshd.8
@@ -64,7 +64,7 @@
.Nm
listens for connections from clients.
It is normally started at boot from
-.Pa /etc/rc .
+.Pa /etc/rc.d/sshd .
It forks a new
daemon for each incoming connection.
The forked daemons handle
@@ -355,8 +355,9 @@
If the login is on a tty, records login time.
.It
Checks
-.Pa /etc/nologin ;
-if it exists, prints contents and quits
+.Pa /etc/nologin and
+.Pa /var/run/nologin ;
+if one exists, it prints the contents and quits
(unless root).
.It
Changes to run with normal user privileges.
@@ -925,6 +926,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 ssh 1 ) .
@@ -1027,6 +1034,7 @@
.Xr ssh-keygen 1 ,
.Xr ssh-keyscan 1 ,
.Xr chroot 2 ,
+.Xr hosts_access 5 ,
.Xr login.conf 5 ,
.Xr moduli 5 ,
.Xr sshd_config 5 ,
Index: sshd.c
===================================================================
--- sshd.c
+++ sshd.c
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
@@ -56,6 +57,15 @@
#include <prot.h>
#endif
+#ifdef __FreeBSD__
+#include <resolv.h>
+#if defined(GSSAPI) && defined(HAVE_GSSAPI_GSSAPI_H)
+#include <gssapi/gssapi.h>
+#elif defined(GSSAPI) && defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#endif
+#endif
+
#include "xmalloc.h"
#include "ssh.h"
#include "sshpty.h"
@@ -84,6 +94,11 @@
#endif
#include "monitor_wrap.h"
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+#endif /* LIBWRAP */
+
/* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 2)
@@ -640,7 +655,14 @@
static void
usage(void)
{
- fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION);
+ if (options.version_addendum != NULL &&
+ *options.version_addendum != '\0')
+ fprintf(stderr, "%s %s, %s\n",
+ SSH_RELEASE,
+ options.version_addendum, SSH_OPENSSL_VERSION);
+ else
+ fprintf(stderr, "%s, %s\n",
+ SSH_RELEASE, SSH_OPENSSL_VERSION);
fprintf(stderr,
"usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n"
" [-E log_file] [-f config_file] [-g login_grace_time]\n"
@@ -923,6 +945,11 @@
struct sshbuf *buf;
socklen_t fromlen;
sigset_t nsigset, osigset;
+#ifdef LIBWRAP
+ struct request_info req;
+
+ request_init(&req, RQ_DAEMON, __progname, 0);
+#endif
/* pipes connected to unauthenticated child sshd processes */
child_alloc();
@@ -1131,6 +1158,42 @@
usleep(100 * 1000);
continue;
}
+#ifdef LIBWRAP
+ /* Check whether logins are denied from this host. */
+ request_set(&req, RQ_FILE, *newsock,
+ RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0);
+ sock_host(&req);
+ if (!hosts_access(&req)) {
+ const struct linger l = { .l_onoff = 1,
+ .l_linger = 0 };
+
+ (void )setsockopt(*newsock, SOL_SOCKET,
+ SO_LINGER, &l, sizeof(l));
+ (void )close(*newsock);
+ /*
+ * Mimic message from libwrap's refuse() as
+ * precisely as we can afford. The authentic
+ * message prints the IP address and the
+ * hostname it resolves to in parentheses. If
+ * the IP address cannot be resolved to a
+ * hostname, the IP address will be repeated
+ * in parentheses. As name resolution in the
+ * main server loop could stall, and logging
+ * resolved names adds little or no value to
+ * incident investigation, this implementation
+ * only repeats the IP address in parentheses.
+ * This should resemble librwap's refuse()
+ * closely enough not to break auditing
+ * software like sshguard or custom scripts.
+ */
+ syslog(LOG_WARNING,
+ "refused connect from %s (%s)",
+ eval_hostaddr(req.client),
+ eval_hostaddr(req.client));
+ debug("Connection refused by tcp wrapper");
+ continue;
+ }
+#endif /* LIBWRAP */
if (unset_nonblock(*newsock) == -1) {
close(*newsock);
continue;
@@ -1818,6 +1881,10 @@
/* Reinitialize the log (because of the fork above). */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
+ /* Avoid killing the process in high-pressure swapping environments. */
+ if (!inetd_flag && madvise(NULL, 0, MADV_PROTECT) != 0)
+ debug("madvise(): %.200s", strerror(errno));
+
/*
* Chdir to the root directory so that the current disk can be
* unmounted if desired.
@@ -1903,6 +1970,28 @@
execv(rexec_argv[0], rexec_argv);
fatal("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
+#ifdef __FreeBSD__
+ /*
+ * Initialize the resolver. This may not happen automatically
+ * before privsep chroot().
+ */
+ if ((_res.options & RES_INIT) == 0) {
+ debug("res_init()");
+ res_init();
+ }
+#ifdef GSSAPI
+ /*
+ * Force GSS-API to parse its configuration and load any
+ * mechanism plugins.
+ */
+ {
+ gss_OID_set mechs;
+ OM_uint32 minor_status;
+ gss_indicate_mechs(&minor_status, &mechs);
+ gss_release_oid_set(&minor_status, &mechs);
+ }
+#endif
+#endif
}
/* server specific fatal cleanup */
Index: sshd_config
===================================================================
--- sshd_config
+++ sshd_config
@@ -10,6 +10,9 @@
# possible, but leave them commented. Uncommented options override the
# default value.
+# Note that some of FreeBSD's defaults differ from OpenBSD's, and
+# FreeBSD has a few additional options.
+
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
@@ -29,7 +32,7 @@
# Authentication:
#LoginGraceTime 2m
-#PermitRootLogin prohibit-password
+#PermitRootLogin no
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
@@ -53,13 +56,15 @@
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
-# To disable tunneled clear text passwords, change to "no" here!
-#PasswordAuthentication yes
+# Change to "yes" to enable built-in password authentication.
+# Note that passwords may also be accepted via KbdInteractiveAuthentication.
+#PasswordAuthentication no
#PermitEmptyPasswords no
# Change to "no" to disable keyboard-interactive authentication. Depending on
# the system's configuration, this may involve passwords, challenge-response,
# one-time passwords or some combination of these and other methods.
+# Keyboard interactive authentication is also used for PAM authentication.
#KbdInteractiveAuthentication yes
# Kerberos options
@@ -72,7 +77,7 @@
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
-# Set this to 'yes' to enable PAM authentication, account processing,
+# Set this to 'no' to disable 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,
@@ -81,7 +86,7 @@
# 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
+#UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
@@ -97,12 +102,13 @@
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
-#UseDNS no
+#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
-#VersionAddendum none
+#UseBlocklist no
+#VersionAddendum FreeBSD-20260514
# no default banner path
#Banner none
Index: sshd_config.5
===================================================================
--- sshd_config.5
+++ sshd_config.5
@@ -909,7 +909,7 @@
The system-wide
.Pa /etc/hosts.equiv
and
-.Pa /etc/shosts.equiv
+.Pa /etc/ssh/shosts.equiv
are still used regardless of this setting.
.Pp
Accepted values are
@@ -1423,8 +1423,12 @@
.Cm sshd .
.It Cm PasswordAuthentication
Specifies whether password authentication is allowed.
+Note that passwords may also be accepted via
+.Cm KbdInteractiveAuthentication .
+See also
+.Cm UsePAM .
The default is
-.Cm yes .
+.Cm no .
.It Cm PermitEmptyPasswords
When password authentication is allowed, it specifies whether the
server allows login to accounts with empty password strings.
@@ -1517,7 +1521,14 @@
or
.Cm no .
The default is
-.Cm prohibit-password .
+.Cm no .
+Note that if
+.Cm ChallengeResponseAuthentication
+and
+.Cm UsePAM
+are both
+.Cm yes ,
+this setting may be overridden by the PAM policy.
.Pp
If this option is set to
.Cm prohibit-password
@@ -2046,6 +2057,20 @@
is to never expire connections for having no open channels.
This option may be useful in conjunction with
.Cm ChannelTimeout .
+.It Cm UseBlocklist
+Specifies whether
+.Xr sshd 8
+attempts to send authentication success and failure messages
+to the
+.Xr blocklistd 8
+daemon.
+The default is
+.Cm no .
+For backward compatibility with
+.Xr blacklistd 8 ,
+the
+.Cm UseBlacklist
+alias can still be used.
.It Cm UseDNS
Specifies whether
.Xr sshd 8
@@ -2054,8 +2079,8 @@
very same IP address.
.Pp
If this option is set to
-.Cm no
-(the default) then only addresses and not host names may be used in
+.Cm no ,
+then only addresses and not host names may be used in
.Pa ~/.ssh/authorized_keys
.Cm from
and
@@ -2063,6 +2088,8 @@
.Cm Match
.Cm Host
directives.
+The default is
+.Dq yes .
.It Cm UsePAM
Enables the Pluggable Authentication Module interface.
If set to
@@ -2086,12 +2113,15 @@
.Xr sshd 8
as a non-root user.
The default is
-.Cm no .
+.Cm yes .
.It Cm VersionAddendum
Optionally specifies additional text to append to the SSH protocol banner
sent by the server upon connection.
The default is
-.Cm none .
+.Qq FreeBSD-20260514 .
+The value
+.Cm none
+may be used to disable this.
.It Cm X11DisplayOffset
Specifies the first display number available for
.Xr sshd 8 Ns 's
@@ -2161,7 +2191,7 @@
.Cm none
to not use one.
The default is
-.Pa /usr/X11R6/bin/xauth .
+.Pa /usr/local/bin/xauth .
.El
.Sh TIME FORMATS
.Xr sshd 8
Index: umac128.c
===================================================================
--- umac128.c
+++ umac128.c
@@ -1,5 +1,12 @@
/* $OpenBSD: umac128.c,v 1.2 2018/02/08 04:12:32 dtucker Exp $ */
+/* undo ssh_namespace.h munging */
+#undef umac_new
+#undef umac_update
+#undef umac_final
+#undef umac_delete
+#undef umac_ctx
+
#define UMAC_OUTPUT_LEN 16
#define umac_new umac128_new
#define umac_update umac128_update
Index: version.h
===================================================================
--- version.h
+++ version.h
@@ -4,3 +4,5 @@
#define SSH_PORTABLE "p1"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
+
+#define SSH_VERSION_FREEBSD "FreeBSD-20260514"
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jul 12, 10:22 PM (15 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34976121
Default Alt Text
D58083.diff (36 KB)
Attached To
Mode
D58083: OpenSSH 10.4p1 FreeBSD diff against upstream
Attached
Detach File
Event Timeline
Log In to Comment