Index: auth-pam.c =================================================================== --- auth-pam.c +++ auth-pam.c @@ -101,6 +101,7 @@ #endif #include "monitor_wrap.h" #include "srclimit.h" +#include "blacklist_client.h" extern ServerOptions options; extern struct sshbuf *loginmsg; @@ -936,6 +937,8 @@ sshbuf_free(buffer); return (0); } + BLACKLIST_NOTIFY(NULL, BLACKLIST_BAD_USER, + sshpam_authctxt->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 @@ -75,6 +75,7 @@ #include "monitor_wrap.h" #include "ssherr.h" #include "channels.h" +#include "blacklist_client.h" /* import */ extern ServerOptions options; @@ -285,8 +286,11 @@ authmsg = "Postponed"; else if (partial) authmsg = "Partial"; - else + else { authmsg = authenticated ? "Accepted" : "Failed"; + if (authenticated) + BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_OK, "ssh"); + } if ((extra = format_method_key(authctxt)) == NULL) { if (authctxt->auth_method_info != NULL) @@ -493,6 +497,7 @@ aix_restoreauthdb(); #endif if (pw == NULL) { + BLACKLIST_NOTIFY(ssh, BLACKLIST_BAD_USER, user); logit("Invalid user %.100s from %.100s port %d", user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); #ifdef CUSTOM_FAILED_LOGIN Index: auth2.c =================================================================== --- auth2.c +++ auth2.c @@ -52,6 +52,7 @@ #include "dispatch.h" #include "pathnames.h" #include "ssherr.h" +#include "blacklist_client.h" #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -442,8 +443,10 @@ } else { /* Allow initial try of "none" auth without failure penalty */ if (!partial && !authctxt->server_caused_failure && - (authctxt->attempt > 1 || strcmp(method, "none") != 0)) + (authctxt->attempt > 1 || strcmp(method, "none") != 0)) { authctxt->failures++; + BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, "ssh"); + } if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS mm_audit_event(ssh, SSH_LOGIN_EXCEED_MAXTRIES); Index: blacklist.c =================================================================== --- /dev/null +++ blacklist.c @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * Copyright (c) 2016 The FreeBSD Foundation, Inc. + * All rights reserved. + * + * Portions of this software were developed by Kurt Lidl + * under sponsorship from the FreeBSD Foundation. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "ssh.h" +#include "packet.h" +#include "log.h" +#include "misc.h" +#include "servconf.h" +#include +#include "blacklist_client.h" + +static struct blacklist *blstate = NULL; + +/* import */ +extern ServerOptions options; + +/* internal definition from bl.h */ +struct blacklist *bl_create(bool, char *, void (*)(int, const char *, va_list)); + +/* impedence match vsyslog() to sshd's internal logging levels */ +void +im_log(int priority, const char *message, va_list args) +{ + LogLevel imlevel; + + switch (priority) { + case LOG_ERR: + imlevel = SYSLOG_LEVEL_ERROR; + break; + case LOG_DEBUG: + imlevel = SYSLOG_LEVEL_DEBUG1; + break; + case LOG_INFO: + imlevel = SYSLOG_LEVEL_INFO; + break; + default: + imlevel = SYSLOG_LEVEL_DEBUG2; + } + do_log2(imlevel, message, args); +} + +void +blacklist_init(void) +{ + + if (options.use_blacklist) + blstate = bl_create(false, NULL, im_log); +} + +void +blacklist_notify(struct ssh *ssh, int action, const char *msg) +{ + + if (blstate != NULL && ssh_packet_connection_is_on_socket(ssh)) + (void)blacklist_r(blstate, action, + ssh_packet_get_connection_in(ssh), msg); +} Index: blacklist_client.h =================================================================== --- /dev/null +++ blacklist_client.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * Copyright (c) 2016 The FreeBSD Foundation, Inc. + * All rights reserved. + * + * Portions of this software were developed by Kurt Lidl + * under sponsorship from the FreeBSD Foundation. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BLACKLIST_CLIENT_H +#define BLACKLIST_CLIENT_H + +#ifndef BLACKLIST_API_ENUM +enum { + BLACKLIST_AUTH_OK = 0, + BLACKLIST_AUTH_FAIL, + BLACKLIST_ABUSIVE_BEHAVIOR, + BLACKLIST_BAD_USER +}; +#endif + +#ifdef USE_BLACKLIST +void blacklist_init(void); +void blacklist_notify(struct ssh *, int, const char *); + +#define BLACKLIST_INIT() blacklist_init() +#define BLACKLIST_NOTIFY(ssh,x,msg) blacklist_notify(ssh,x,msg) + +#else + +#define BLACKLIST_INIT() +#define BLACKLIST_NOTIFY(ssh,x,msg) + +#endif + + +#endif /* BLACKLIST_CLIENT_H */ Index: packet.c =================================================================== --- packet.c +++ packet.c @@ -96,6 +96,7 @@ #include "packet.h" #include "ssherr.h" #include "sshbuf.h" +#include "blacklist_client.h" #ifdef PACKET_DEBUG #define DBG(x) x @@ -2014,6 +2015,7 @@ case SSH_ERR_NO_KEX_ALG_MATCH: case SSH_ERR_NO_HOSTKEY_ALG_MATCH: if (ssh->kex && ssh->kex->failed_choice) { + BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, "ssh"); ssh_packet_clear_keys(ssh); errno = oerrno; logdie("Unable to negotiate with %s: %s. " Index: servconf.h =================================================================== --- servconf.h +++ servconf.h @@ -248,6 +248,8 @@ int unused_connection_timeout; char *sshd_session_path; + + int use_blacklist; } ServerOptions; /* Information about the incoming connection as used by Match */ Index: servconf.c =================================================================== --- servconf.c +++ servconf.c @@ -214,6 +214,7 @@ options->num_channel_timeouts = 0; options->unused_connection_timeout = -1; options->sshd_session_path = NULL; + options->use_blacklist = -1; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ @@ -496,6 +497,8 @@ options->unused_connection_timeout = 0; if (options->sshd_session_path == NULL) options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION); + if (options->use_blacklist == -1) + options->use_blacklist = 0; assemble_algorithms(options); @@ -579,6 +582,7 @@ sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, sSshdSessionPath, + sUseBlacklist, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; @@ -746,6 +750,9 @@ { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, + { "useblacklist", sUseBlacklist, SSHCFG_GLOBAL }, + { "useblocklist", sUseBlacklist, SSHCFG_GLOBAL }, /* alias */ + { NULL, sBadOption, 0 } }; @@ -2665,6 +2672,10 @@ charptr = &options->sshd_session_path; goto parse_filename; + case sUseBlacklist: + intptr = &options->use_blacklist; + goto parse_flag; + case sDeprecated: case sIgnore: case sUnsupported: @@ -3210,6 +3221,7 @@ dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); + dump_cfg_fmtint(sUseBlacklist, o->use_blacklist); /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); Index: sshd-session.c =================================================================== --- sshd-session.c +++ sshd-session.c @@ -110,6 +110,7 @@ #include "sk-api.h" #include "srclimit.h" #include "dh.h" +#include "blacklist_client.h" /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) @@ -204,6 +205,8 @@ static void grace_alarm_handler(int sig) { + BLACKLIST_NOTIFY(the_active_state, BLACKLIST_AUTH_FAIL, "ssh"); + /* * Try to kill any processes that we have spawned, E.g. authorized * keys command helpers or privsep children. Index: sshd.c =================================================================== --- sshd.c +++ sshd.c @@ -92,6 +92,7 @@ #include "sk-api.h" #include "addr.h" #include "srclimit.h" +#include "blacklist_client.h" #ifdef LIBWRAP #include @@ -313,6 +314,7 @@ } if (child->pid == -1 || force_final) child_finish(child); + } /* Record a child exit. Safe to call from signal handlers */ @@ -1838,6 +1840,8 @@ fatal("rexec of %s failed: %s", rexec_argv[0], strerror(errno)); + BLACKLIST_INIT(); + } /* server specific fatal cleanup */ Index: sshd_config =================================================================== --- sshd_config +++ sshd_config @@ -103,6 +103,7 @@ #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none +#UseBlacklist no #VersionAddendum FreeBSD-2023XXXX # no default banner path Index: sshd_config.5 =================================================================== --- sshd_config.5 +++ sshd_config.5 @@ -1981,6 +1981,20 @@ is to never expire connections for having no open channels. This option may be useful in conjunction with .Cm ChannelTimeout . +.It Cm UseBlacklist +Specifies whether +.Xr sshd 8 +attempts to send authentication success and failure messages +to the +.Xr blacklistd 8 +daemon. +The default is +.Dq no . +For forward compatibility with an upcoming +.Xr blacklistd +rename, the +.Cm UseBlocklist +alias can be used instead. .It Cm UseDNS Specifies whether .Xr sshd 8