diff -wpruN --no-dereference '--exclude=*.orig' a~/readconf.c a/readconf.c --- a~/readconf.c 1970-01-01 00:00:00 +++ a/readconf.c 1970-01-01 00:00:00 @@ -167,6 +167,9 @@ typedef enum { oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, +#ifdef DISABLE_BANNER + oDisableBanner, +#endif oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, oRemoteCommand, oVisualHostKey, @@ -294,6 +297,9 @@ static struct { { "controlpersist", oControlPersist }, { "hashknownhosts", oHashKnownHosts }, { "include", oInclude }, +#ifdef DISABLE_BANNER + { "disablebanner", oDisableBanner }, +#endif { "tunnel", oTunnel }, { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, @@ -1054,6 +1060,17 @@ parse_multistate_value(const char *arg, 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. @@ -2422,6 +2439,13 @@ parse_pubkey_algos: } 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); @@ -2660,6 +2684,9 @@ initialize_options(Options * options) 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; @@ -2867,6 +2894,10 @@ fill_default_options(Options * options) 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 diff -wpruN --no-dereference '--exclude=*.orig' a~/readconf.h a/readconf.h --- a~/readconf.h 1970-01-01 00:00:00 +++ a/readconf.h 1970-01-01 00:00:00 @@ -186,6 +186,9 @@ typedef struct { 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 @@ -231,6 +234,12 @@ typedef struct { #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); diff -wpruN --no-dereference '--exclude=*.orig' a~/ssh_config.5 a/ssh_config.5 --- a~/ssh_config.5 1970-01-01 00:00:00 +++ a/ssh_config.5 1970-01-01 00:00:00 @@ -710,6 +710,14 @@ If set to a time in seconds, or a time i 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 DynamicForward Specifies that a TCP port on the local machine be forwarded over the secure channel, and the application diff -wpruN --no-dereference '--exclude=*.orig' a~/sshconnect2.c a/sshconnect2.c --- a~/sshconnect2.c 1970-01-01 00:00:00 +++ a/sshconnect2.c 1970-01-01 00:00:00 @@ -82,6 +82,10 @@ /* import */ extern Options options; +#ifdef DISABLE_BANNER +extern struct sshbuf *command; +#endif + /* * SSH2 key exchange */ @@ -576,8 +580,28 @@ input_userauth_banner(int type, u_int32_ 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);