From a116d13c4daeb5416766bc506065eb495409977e Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 22 Apr 2012 11:23:46 +1000 Subject: - djm@cvs.openbsd.org 2012/04/11 13:26:40 [sshd.c] don't spin in accept() when out of fds (ENFILE/ENFILE) - back off for a while; ok deraadt@ markus@ --- sshd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'sshd.c') diff --git a/sshd.c b/sshd.c index b63aaa428..fddbc9d37 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.388 2011/09/30 21:22:49 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.389 2012/04/11 13:26:40 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1174,7 +1174,10 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) if (*newsock < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) - error("accept: %.100s", strerror(errno)); + error("accept: %.100s", + strerror(errno)); + if (errno == EMFILE || errno == ENFILE) + usleep(100 * 1000); continue; } if (unset_nonblock(*newsock) == -1) { -- cgit v1.2.3 From 23528816dc10165b3bc009f2ab5fdf1653db418c Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 22 Apr 2012 11:24:43 +1000 Subject: - djm@cvs.openbsd.org 2012/04/12 02:42:32 [servconf.c servconf.h sshd.c sshd_config sshd_config.5] VersionAddendum option to allow server operators to append some arbitrary text to the SSH-... banner; ok deraadt@ "don't care" markus@ --- ChangeLog | 4 ++++ servconf.c | 26 +++++++++++++++++++++++--- servconf.h | 4 +++- sshd.c | 10 ++++++---- sshd_config | 3 ++- sshd_config.5 | 9 +++++++-- 6 files changed, 45 insertions(+), 11 deletions(-) (limited to 'sshd.c') diff --git a/ChangeLog b/ChangeLog index 9c9b3fd0c..a8312a5ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -33,6 +33,10 @@ [ssh-keyscan.1 ssh-keyscan.c] now that sshd defaults to offering ECDSA keys, ssh-keyscan should also look for them by default; bz#1971 + - djm@cvs.openbsd.org 2012/04/12 02:42:32 + [servconf.c servconf.h sshd.c sshd_config sshd_config.5] + VersionAddendum option to allow server operators to append some arbitrary + text to the SSH-... banner; ok deraadt@ "don't care" markus@ 20120420 - (djm) [contrib/caldera/openssh.spec contrib/redhat/openssh.spec] diff --git a/servconf.c b/servconf.c index 6de77164e..a8a40f97e 100644 --- a/servconf.c +++ b/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.224 2012/03/29 23:54:36 dtucker Exp $ */ +/* $OpenBSD: servconf.c,v 1.225 2012/04/12 02:42:32 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -138,6 +138,7 @@ initialize_server_options(ServerOptions *options) options->authorized_principals_file = NULL; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; + options->version_addendum = NULL; } void @@ -277,7 +278,8 @@ fill_default_server_options(ServerOptions *options) options->ip_qos_interactive = IPTOS_LOWDELAY; if (options->ip_qos_bulk == -1) options->ip_qos_bulk = IPTOS_THROUGHPUT; - + if (options->version_addendum == NULL) + options->version_addendum = xstrdup(""); /* Turn privilege separation on by default */ if (use_privsep == -1) use_privsep = PRIVSEP_ON; @@ -323,7 +325,7 @@ typedef enum { sUsePrivilegeSeparation, sAllowAgentForwarding, sZeroKnowledgePasswordAuthentication, sHostCertificate, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, - sKexAlgorithms, sIPQoS, + sKexAlgorithms, sIPQoS, sVersionAddendum, sDeprecated, sUnsupported } ServerOpCodes; @@ -448,6 +450,7 @@ static struct { { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, { "ipqos", sIPQoS, SSHCFG_ALL }, + { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, { NULL, sBadOption, 0 } }; @@ -1403,6 +1406,22 @@ process_server_config_line(ServerOptions *options, char *line, } break; + case sVersionAddendum: + if (cp == NULL) + fatal("%.200s line %d: Missing argument.", filename, + linenum); + len = strspn(cp, WHITESPACE); + if (*activep && options->version_addendum == NULL) { + if (strcasecmp(cp + len, "none") == 0) + options->version_addendum = xstrdup(""); + else if (strchr(cp + len, '\r') != NULL) + fatal("%.200s line %d: Invalid argument", + filename, linenum); + else + options->version_addendum = xstrdup(cp + len); + } + return 0; + case sDeprecated: logit("%s line %d: Deprecated option %s", filename, linenum, arg); @@ -1766,6 +1785,7 @@ dump_config(ServerOptions *o) dump_cfg_string(sRevokedKeys, o->revoked_keys_file); dump_cfg_string(sAuthorizedPrincipalsFile, o->authorized_principals_file); + dump_cfg_string(sVersionAddendum, o->version_addendum); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); diff --git a/servconf.h b/servconf.h index 89f38e20f..66ba387dd 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.99 2011/06/22 21:57:01 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.100 2012/04/12 02:42:32 djm Exp $ */ /* * Author: Tatu Ylonen @@ -166,6 +166,8 @@ typedef struct { char *revoked_keys_file; char *trusted_user_ca_keys; char *authorized_principals_file; + + char *version_addendum; /* Appended to SSH banner */ } ServerOptions; /* diff --git a/sshd.c b/sshd.c index fddbc9d37..b7066df5c 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.389 2012/04/11 13:26:40 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.390 2012/04/12 02:42:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -419,9 +419,11 @@ sshd_exchange_identification(int sock_in, int sock_out) major = PROTOCOL_MAJOR_1; minor = PROTOCOL_MINOR_1; } - snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor, - SSH_VERSION, newline); - server_version_string = xstrdup(buf); + + xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", + major, minor, SSH_VERSION, + *options.version_addendum == '\0' ? "" : " ", + options.version_addendum, newline); /* Send our protocol version identification. */ if (roaming_atomicio(vwrite, sock_out, server_version_string, diff --git a/sshd_config b/sshd_config index 473e86654..99dbd8580 100644 --- a/sshd_config +++ b/sshd_config @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $ +# $OpenBSD: sshd_config,v 1.85 2012/04/12 02:42:32 djm Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -107,6 +107,7 @@ AuthorizedKeysFile .ssh/authorized_keys #MaxStartups 10 #PermitTunnel no #ChrootDirectory none +#VersionAddendum none # no default banner path #Banner none diff --git a/sshd_config.5 b/sshd_config.5 index 4ef8b9e6d..1522355a8 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.136 2011/09/09 00:43:00 djm Exp $ -.Dd $Mdocdate: September 9 2011 $ +.\" $OpenBSD: sshd_config.5,v 1.137 2012/04/12 02:42:32 djm Exp $ +.Dd $Mdocdate: April 12 2012 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -1079,6 +1079,11 @@ is set to .Dq sandbox then the pre-authentication unprivileged process is subject to additional restrictions. +.It Cm VersionAddendum +Optionally specifies additional text to append to the SSH protocol banner +sent by the server upon connection. +The default is +.Dq none . .It Cm X11DisplayOffset Specifies the first display number available for .Xr sshd 8 Ns 's -- cgit v1.2.3 From fbcf827559b38f7992e1bd0bcdc4b4ccdf63bc74 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Sat, 19 May 2012 19:37:01 +1000 Subject: - (dtucker) OpenBSD CVS Sync - dtucker@cvs.openbsd.org 2012/05/13 01:42:32 [servconf.h servconf.c sshd.8 sshd.c auth.c sshd_config.5] Add "Match LocalAddress" and "Match LocalPort" to sshd and adjust tests to match. Feedback and ok djm@ markus@. --- ChangeLog | 5 ++ auth.c | 7 +-- servconf.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++---------- servconf.h | 22 ++++++-- sshd.8 | 6 ++- sshd.c | 39 +++++--------- sshd_config.5 | 6 ++- 7 files changed, 181 insertions(+), 67 deletions(-) (limited to 'sshd.c') diff --git a/ChangeLog b/ChangeLog index 9cdce589f..1ed4b228c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,11 @@ - (dtucker) [configure.ac contrib/Makefile] bz#1996: use AC_PATH_TOOL to find pkg-config so it does the right thing when cross-compiling. Patch from cjwatson at debian org. +- (dtucker) OpenBSD CVS Sync + - dtucker@cvs.openbsd.org 2012/05/13 01:42:32 + [servconf.h servconf.c sshd.8 sshd.c auth.c sshd_config.5] + Add "Match LocalAddress" and "Match LocalPort" to sshd and adjust tests + to match. Feedback and ok djm@ markus@. 20120504 - (dtucker) [configure.ac] Include rather than diff --git a/auth.c b/auth.c index 976932887..a8cffd5c1 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.95 2012/04/11 13:17:54 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.96 2012/05/13 01:42:32 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -545,9 +545,10 @@ getpwnamallow(const char *user) #endif #endif struct passwd *pw; + struct connection_info *ci = get_connection_info(1, options.use_dns); - parse_server_match_config(&options, user, - get_canonical_hostname(options.use_dns), get_remote_ipaddr()); + ci->user = user; + parse_server_match_config(&options, ci); #if defined(_AIX) && defined(HAVE_SETAUTHDB) aix_setauthdb(user); diff --git a/servconf.c b/servconf.c index a8a40f97e..12f43c91e 100644 --- a/servconf.c +++ b/servconf.c @@ -1,4 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.225 2012/04/12 02:42:32 djm Exp $ */ + +/* $OpenBSD: servconf.c,v 1.226 2012/05/13 01:42:32 dtucker Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -45,6 +46,8 @@ #include "match.h" #include "channels.h" #include "groupaccess.h" +#include "canohost.h" +#include "packet.h" static void add_listen_addr(ServerOptions *, char *, int); static void add_one_listen_addr(ServerOptions *, char *, int); @@ -539,6 +542,20 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) options->listen_addrs = aitop; } +struct connection_info * +get_connection_info(int populate, int use_dns) +{ + static struct connection_info ci; + + if (!populate) + return &ci; + ci.host = get_canonical_hostname(use_dns); + ci.address = get_remote_ipaddr(); + ci.laddress = get_local_ipaddr(packet_get_connection_in()); + ci.lport = get_local_port(); + return &ci; +} + /* * The strategy for the Match blocks is that the config file is parsed twice. * @@ -600,20 +617,25 @@ out: return result; } +/* + * All of the attributes on a single Match line are ANDed together, so we need to check every + * attribute and set the result to zero if any attribute does not match. + */ static int -match_cfg_line(char **condition, int line, const char *user, const char *host, - const char *address) +match_cfg_line(char **condition, int line, struct connection_info *ci) { - int result = 1; + int result = 1, port; char *arg, *attrib, *cp = *condition; size_t len; - if (user == NULL) + if (ci == NULL) debug3("checking syntax for 'Match %s'", cp); else - debug3("checking match for '%s' user %s host %s addr %s", cp, - user ? user : "(null)", host ? host : "(null)", - address ? address : "(null)"); + debug3("checking match for '%s' user %s host %s addr %s " + "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", + ci->host ? ci->host : "(null)", + ci->address ? ci->address : "(null)", + ci->laddress ? ci->laddress : "(null)", ci->lport); while ((attrib = strdelim(&cp)) && *attrib != '\0') { if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { @@ -622,37 +644,45 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, } len = strlen(arg); if (strcasecmp(attrib, "user") == 0) { - if (!user) { + if (ci == NULL || ci->user == NULL) { result = 0; continue; } - if (match_pattern_list(user, arg, len, 0) != 1) + if (match_pattern_list(ci->user, arg, len, 0) != 1) result = 0; else debug("user %.100s matched 'User %.100s' at " - "line %d", user, arg, line); + "line %d", ci->user, arg, line); } else if (strcasecmp(attrib, "group") == 0) { - switch (match_cfg_line_group(arg, line, user)) { + if (ci == NULL || ci->user == NULL) { + result = 0; + continue; + } + switch (match_cfg_line_group(arg, line, ci->user)) { case -1: return -1; case 0: result = 0; } } else if (strcasecmp(attrib, "host") == 0) { - if (!host) { + if (ci == NULL || ci->host == NULL) { result = 0; continue; } - if (match_hostname(host, arg, len) != 1) + if (match_hostname(ci->host, arg, len) != 1) result = 0; else debug("connection from %.100s matched 'Host " - "%.100s' at line %d", host, arg, line); + "%.100s' at line %d", ci->host, arg, line); } else if (strcasecmp(attrib, "address") == 0) { - switch (addr_match_list(address, arg)) { + if (ci == NULL || ci->address == NULL) { + result = 0; + continue; + } + switch (addr_match_list(ci->address, arg)) { case 1: debug("connection from %.100s matched 'Address " - "%.100s' at line %d", address, arg, line); + "%.100s' at line %d", ci->address, arg, line); break; case 0: case -1: @@ -661,12 +691,47 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, case -2: return -1; } + } else if (strcasecmp(attrib, "localaddress") == 0){ + if (ci == NULL || ci->laddress == NULL) { + result = 0; + continue; + } + switch (addr_match_list(ci->laddress, arg)) { + case 1: + debug("connection from %.100s matched " + "'LocalAddress %.100s' at line %d", + ci->laddress, arg, line); + break; + case 0: + case -1: + result = 0; + break; + case -2: + return -1; + } + } else if (strcasecmp(attrib, "localport") == 0) { + if ((port = a2port(arg)) == -1) { + error("Invalid LocalPort '%s' on Match line", + arg); + return -1; + } + if (ci == NULL || ci->lport == 0) { + result = 0; + continue; + } + /* TODO support port lists */ + if (port == ci->lport) + debug("connection from %.100s matched " + "'LocalPort %d' at line %d", + ci->laddress, port, line); + else + result = 0; } else { error("Unsupported Match attribute %s", attrib); return -1; } } - if (user != NULL) + if (ci != NULL) debug3("match %sfound", result ? "" : "not "); *condition = cp; return result; @@ -713,8 +778,8 @@ static const struct multistate multistate_privsep[] = { int process_server_config_line(ServerOptions *options, char *line, - const char *filename, int linenum, int *activep, const char *user, - const char *host, const char *address) + const char *filename, int linenum, int *activep, + struct connection_info *connectinfo) { char *cp, **charptr, *arg, *p; int cmdline = 0, *intptr, value, value2, n; @@ -745,7 +810,7 @@ process_server_config_line(ServerOptions *options, char *line, if (*activep && opcode != sMatch) debug3("%s:%d setting %s %s", filename, linenum, arg, cp); if (*activep == 0 && !(flags & SSHCFG_MATCH)) { - if (user == NULL) { + if (connectinfo == NULL) { fatal("%s line %d: Directive '%s' is not allowed " "within a Match block", filename, linenum, arg); } else { /* this is a directive we have already processed */ @@ -1316,7 +1381,7 @@ process_server_config_line(ServerOptions *options, char *line, if (cmdline) fatal("Match directive not supported as a command-line " "option"); - value = match_cfg_line(&cp, linenum, user, host, address); + value = match_cfg_line(&cp, linenum, connectinfo); if (value < 0) fatal("%s line %d: Bad Match condition", filename, linenum); @@ -1478,16 +1543,58 @@ load_server_config(const char *filename, Buffer *conf) } void -parse_server_match_config(ServerOptions *options, const char *user, - const char *host, const char *address) +parse_server_match_config(ServerOptions *options, + struct connection_info *connectinfo) { ServerOptions mo; initialize_server_options(&mo); - parse_server_config(&mo, "reprocess config", &cfg, user, host, address); + parse_server_config(&mo, "reprocess config", &cfg, connectinfo); copy_set_server_options(options, &mo, 0); } +int parse_server_match_testspec(struct connection_info *ci, char *spec) +{ + char *p; + + while ((p = strsep(&spec, ",")) && *p != '\0') { + if (strncmp(p, "addr=", 5) == 0) { + ci->address = xstrdup(p + 5); + } else if (strncmp(p, "host=", 5) == 0) { + ci->host = xstrdup(p + 5); + } else if (strncmp(p, "user=", 5) == 0) { + ci->user = xstrdup(p + 5); + } else if (strncmp(p, "laddr=", 6) == 0) { + ci->laddress = xstrdup(p + 6); + } else if (strncmp(p, "lport=", 6) == 0) { + ci->lport = a2port(p + 6); + if (ci->lport == -1) { + fprintf(stderr, "Invalid port '%s' in test mode" + " specification %s\n", p+6, p); + return -1; + } + } else { + fprintf(stderr, "Invalid test mode specification %s\n", + p); + return -1; + } + } + return 0; +} + +/* + * returns 1 for a complete spec, 0 for partial spec and -1 for an + * empty spec. + */ +int server_match_spec_complete(struct connection_info *ci) +{ + if (ci->user && ci->host && ci->address) + return 1; /* complete */ + if (!ci->user && !ci->host && !ci->address) + return -1; /* empty */ + return 0; /* partial */ +} + /* Helper macros */ #define M_CP_INTOPT(n) do {\ if (src->n != -1) \ @@ -1561,7 +1668,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) void parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, - const char *user, const char *host, const char *address) + struct connection_info *connectinfo) { int active, linenum, bad_options = 0; char *cp, *obuf, *cbuf; @@ -1569,11 +1676,11 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); obuf = cbuf = xstrdup(buffer_ptr(conf)); - active = user ? 0 : 1; + active = connectinfo ? 0 : 1; linenum = 1; while ((cp = strsep(&cbuf, "\n")) != NULL) { if (process_server_config_line(options, cp, filename, - linenum++, &active, user, host, address) != 0) + linenum++, &active, connectinfo) != 0) bad_options++; } xfree(obuf); diff --git a/servconf.h b/servconf.h index 66ba387dd..2ffaecdcd 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.100 2012/04/12 02:42:32 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.101 2012/05/13 01:42:32 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -170,6 +170,16 @@ typedef struct { char *version_addendum; /* Appended to SSH banner */ } ServerOptions; +/* Information about the incoming connection as used by Match */ +struct connection_info { + const char *user; + const char *host; /* possibly resolved hostname */ + const char *address; /* remote address */ + const char *laddress; /* local address */ + int lport; /* local port */ +}; + + /* * These are string config options that must be copied between the * Match sub-config and the main config, and must be sent from the @@ -184,15 +194,17 @@ typedef struct { M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ } while (0) +struct connection_info *get_connection_info(int, int); void initialize_server_options(ServerOptions *); void fill_default_server_options(ServerOptions *); int process_server_config_line(ServerOptions *, char *, const char *, int, - int *, const char *, const char *, const char *); + int *, struct connection_info *); void load_server_config(const char *, Buffer *); void parse_server_config(ServerOptions *, const char *, Buffer *, - const char *, const char *, const char *); -void parse_server_match_config(ServerOptions *, const char *, const char *, - const char *); + struct connection_info *); +void parse_server_match_config(ServerOptions *, struct connection_info *); +int parse_server_match_testspec(struct connection_info *, char *); +int server_match_spec_complete(struct connection_info *); void copy_set_server_options(ServerOptions *, ServerOptions *, int); void dump_config(ServerOptions *); char *derelativise_path(const char *); diff --git a/sshd.8 b/sshd.8 index 721015709..6d79c7dda 100644 --- a/sshd.8 +++ b/sshd.8 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.264 2011/09/23 00:22:04 dtucker Exp $ -.Dd $Mdocdate: September 23 2011 $ +.\" $OpenBSD: sshd.8,v 1.265 2012/05/13 01:42:32 dtucker Exp $ +.Dd $Mdocdate: May 13 2012 $ .Dt SSHD 8 .Os .Sh NAME @@ -114,6 +114,8 @@ The connection parameters are supplied as keyword=value pairs. The keywords are .Dq user , .Dq host , +.Dq laddr , +.Dq lport , and .Dq addr . All are required and may be supplied in any order, either with multiple diff --git a/sshd.c b/sshd.c index b7066df5c..7cc7044be 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.390 2012/04/12 02:42:32 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.391 2012/05/13 01:42:32 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1325,14 +1325,14 @@ main(int ac, char **av) int opt, i, j, on = 1; int sock_in = -1, sock_out = -1, newsock = -1; const char *remote_ip; - char *test_user = NULL, *test_host = NULL, *test_addr = NULL; int remote_port; - char *line, *p, *cp; + char *line; int config_s[2] = { -1 , -1 }; u_int64_t ibytes, obytes; mode_t new_umask; Key *key; Authctxt *authctxt; + struct connection_info *connection_info = get_connection_info(0, 0); #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); @@ -1454,20 +1454,9 @@ main(int ac, char **av) test_flag = 2; break; case 'C': - cp = optarg; - while ((p = strsep(&cp, ",")) && *p != '\0') { - if (strncmp(p, "addr=", 5) == 0) - test_addr = xstrdup(p + 5); - else if (strncmp(p, "host=", 5) == 0) - test_host = xstrdup(p + 5); - else if (strncmp(p, "user=", 5) == 0) - test_user = xstrdup(p + 5); - else { - fprintf(stderr, "Invalid test " - "mode specification %s\n", p); - exit(1); - } - } + if (parse_server_match_testspec(connection_info, + optarg) == -1) + exit(1); break; case 'u': utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL); @@ -1479,7 +1468,7 @@ main(int ac, char **av) case 'o': line = xstrdup(optarg); if (process_server_config_line(&options, line, - "command-line", 0, NULL, NULL, NULL, NULL) != 0) + "command-line", 0, NULL, NULL) != 0) exit(1); xfree(line); break; @@ -1535,13 +1524,10 @@ main(int ac, char **av) * the parameters we need. If we're not doing an extended test, * do not silently ignore connection test params. */ - if (test_flag >= 2 && - (test_user != NULL || test_host != NULL || test_addr != NULL) - && (test_user == NULL || test_host == NULL || test_addr == NULL)) + if (test_flag >= 2 && server_match_spec_complete(connection_info) == 0) fatal("user, host and addr are all required when testing " "Match configs"); - if (test_flag < 2 && (test_user != NULL || test_host != NULL || - test_addr != NULL)) + if (test_flag < 2 && server_match_spec_complete(connection_info) >= 0) fatal("Config test connection parameter (-C) provided without " "test mode (-T)"); @@ -1553,7 +1539,7 @@ main(int ac, char **av) load_server_config(config_file_name, &cfg); parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - &cfg, NULL, NULL, NULL); + &cfg, NULL); seed_rng(); @@ -1715,9 +1701,8 @@ main(int ac, char **av) } if (test_flag > 1) { - if (test_user != NULL && test_addr != NULL && test_host != NULL) - parse_server_match_config(&options, test_user, - test_host, test_addr); + if (server_match_spec_complete(connection_info) == 1) + parse_server_match_config(&options, connection_info); dump_config(&options); } diff --git a/sshd_config.5 b/sshd_config.5 index 27ee19146..17df9e6cd 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.138 2012/04/12 02:43:55 djm Exp $ -.Dd $Mdocdate: April 12 2012 $ +.\" $OpenBSD: sshd_config.5,v 1.139 2012/05/13 01:42:32 dtucker Exp $ +.Dd $Mdocdate: May 13 2012 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -677,6 +677,8 @@ The available criteria are .Cm User , .Cm Group , .Cm Host , +.Cm LocalAddress , +.Cm LocalPort , and .Cm Address . The match patterns may consist of single entries or comma-separated -- cgit v1.2.3 From 3b4b2d30219d2ecb1426d2f9339239d32bad7bf6 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Mon, 2 Jul 2012 18:54:31 +1000 Subject: - markus@cvs.openbsd.org 2012/06/30 14:35:09 [sandbox-systrace.c sshd.c] fix a during the load of the sandbox policies (child can still make the read-syscall and wait forever for systrace-answers) by replacing the read/write synchronisation with SIGSTOP/SIGCONT; report and help hshoexer@; ok djm@, dtucker@ --- ChangeLog | 6 ++++++ sandbox-systrace.c | 55 +++++++++++++++++++++++++++--------------------------- sshd.c | 4 ++-- 3 files changed, 35 insertions(+), 30 deletions(-) (limited to 'sshd.c') diff --git a/ChangeLog b/ChangeLog index 5608909da..66c4ef574 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,12 @@ [ssh_config.5 sshd_config.5] match the documented MAC order of preference to the actual one; ok dtucker@ + - markus@cvs.openbsd.org 2012/06/30 14:35:09 + [sandbox-systrace.c sshd.c] + fix a during the load of the sandbox policies (child can still make + the read-syscall and wait forever for systrace-answers) by replacing + the read/write synchronisation with SIGSTOP/SIGCONT; + report and help hshoexer@; ok djm@, dtucker@ 20120629 - OpenBSD CVS Sync diff --git a/sandbox-systrace.c b/sandbox-systrace.c index 199b69f44..2d16a627f 100644 --- a/sandbox-systrace.c +++ b/sandbox-systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sandbox-systrace.c,v 1.5 2012/06/26 11:02:30 dtucker Exp $ */ +/* $OpenBSD: sandbox-systrace.c,v 1.6 2012/06/30 14:35:09 markus Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -24,12 +24,14 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -69,26 +71,21 @@ static const struct sandbox_policy preauth_policy[] = { }; struct ssh_sandbox { - int child_sock; - int parent_sock; int systrace_fd; pid_t child_pid; + void (*osigchld)(int); }; struct ssh_sandbox * ssh_sandbox_init(void) { struct ssh_sandbox *box; - int s[2]; debug3("%s: preparing systrace sandbox", __func__); box = xcalloc(1, sizeof(*box)); - if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) - fatal("%s: socketpair: %s", __func__, strerror(errno)); - box->child_sock = s[0]; - box->parent_sock = s[1]; box->systrace_fd = -1; box->child_pid = 0; + box->osigchld = signal(SIGCHLD, SIG_IGN); return box; } @@ -96,35 +93,38 @@ ssh_sandbox_init(void) void ssh_sandbox_child(struct ssh_sandbox *box) { - char whatever = 0; - - close(box->parent_sock); - /* Signal parent that we are ready */ debug3("%s: ready", __func__); - if (atomicio(vwrite, box->child_sock, &whatever, 1) != 1) - fatal("%s: write: %s", __func__, strerror(errno)); - /* Wait for parent to signal for us to go */ - if (atomicio(read, box->child_sock, &whatever, 1) != 1) - fatal("%s: read: %s", __func__, strerror(errno)); + signal(SIGCHLD, box->osigchld); + if (kill(getpid(), SIGSTOP) != 0) + fatal("%s: kill(%d, SIGSTOP)", __func__, getpid()); debug3("%s: started", __func__); - close(box->child_sock); } static void ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid, const struct sandbox_policy *allowed_syscalls) { - int dev_systrace, i, j, found; - char whatever = 0; + int dev_systrace, i, j, found, status; + pid_t pid; struct systrace_policy policy; + /* Wait for the child to send itself a SIGSTOP */ debug3("%s: wait for child %ld", __func__, (long)child_pid); + do { + pid = waitpid(child_pid, &status, WUNTRACED); + } while (pid == -1 && errno == EINTR); + signal(SIGCHLD, box->osigchld); + if (!WIFSTOPPED(status)) { + if (WIFSIGNALED(status)) + fatal("%s: child terminated with signal %d", + __func__, WTERMSIG(status)); + if (WIFEXITED(status)) + fatal("%s: child exited with status %d", + __func__, WEXITSTATUS(status)); + fatal("%s: child not stopped", __func__); + } + debug3("%s: child %ld stopped", __func__, (long)child_pid); box->child_pid = child_pid; - close(box->child_sock); - /* Wait for child to signal that it is ready */ - if (atomicio(read, box->parent_sock, &whatever, 1) != 1) - fatal("%s: read: %s", __func__, strerror(errno)); - debug3("%s: child %ld ready", __func__, (long)child_pid); /* Set up systracing of child */ if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1) @@ -175,9 +175,8 @@ ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid, /* Signal the child to start running */ debug3("%s: start child %ld", __func__, (long)child_pid); - if (atomicio(vwrite, box->parent_sock, &whatever, 1) != 1) - fatal("%s: write: %s", __func__, strerror(errno)); - close(box->parent_sock); + if (kill(box->child_pid, SIGCONT) != 0) + fatal("%s: kill(%d, SIGCONT)", __func__, box->child_pid); } void diff --git a/sshd.c b/sshd.c index 7cc7044be..64b846f6c 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.391 2012/05/13 01:42:32 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.392 2012/06/30 14:35:09 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -643,9 +643,9 @@ privsep_preauth(Authctxt *authctxt) } else if (pid != 0) { debug2("Network child is on pid %ld", (long)pid); + pmonitor->m_pid = pid; if (box != NULL) ssh_sandbox_parent_preauth(box, pid); - pmonitor->m_pid = pid; monitor_child_preauth(authctxt, pmonitor); /* Sync memory */ -- cgit v1.2.3 From 5a5c2b9063fc3d7315424702b01527ccb0d4c0c9 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 31 Jul 2012 12:21:34 +1000 Subject: - djm@cvs.openbsd.org 2012/07/10 02:19:15 [servconf.c servconf.h sshd.c sshd_config] Turn on systrace sandboxing of pre-auth sshd by default for new installs by shipping a config that overrides the current UsePrivilegeSeparation=yes default. Make it easier to flip the default in the future by adding too. --- ChangeLog | 5 +++++ servconf.c | 9 +++++---- servconf.h | 4 ++-- sshd.c | 4 ++-- sshd_config | 4 ++-- 5 files changed, 16 insertions(+), 10 deletions(-) (limited to 'sshd.c') diff --git a/ChangeLog b/ChangeLog index 885a721ff..911b4b114 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ - jmc@cvs.openbsd.org 2012/07/06 06:38:03 [ssh-keygen.c] missing full stop in usage(); + - djm@cvs.openbsd.org 2012/07/10 02:19:15 + [servconf.c servconf.h sshd.c sshd_config] + Turn on systrace sandboxing of pre-auth sshd by default for new installs + by shipping a config that overrides the current UsePrivilegeSeparation=yes + default. Make it easier to flip the default in the future by adding too. 20120720 - (dtucker) Import regened moduli file. diff --git a/servconf.c b/servconf.c index eccfbad48..427bdeef1 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.227 2012/06/19 18:25:27 markus Exp $ */ +/* $OpenBSD: servconf.c,v 1.228 2012/07/10 02:19:15 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -285,7 +285,7 @@ fill_default_server_options(ServerOptions *options) options->version_addendum = xstrdup(""); /* Turn privilege separation on by default */ if (use_privsep == -1) - use_privsep = PRIVSEP_ON; + use_privsep = PRIVSEP_NOSANDBOX; #ifndef HAVE_MMAP if (use_privsep && options->compression == 1) { @@ -770,8 +770,9 @@ static const struct multistate multistate_gatewayports[] = { { NULL, -1 } }; static const struct multistate multistate_privsep[] = { - { "sandbox", PRIVSEP_SANDBOX }, - { "yes", PRIVSEP_ON }, + { "yes", PRIVSEP_NOSANDBOX }, + { "sandbox", PRIVSEP_ON }, + { "nosandbox", PRIVSEP_NOSANDBOX }, { "no", PRIVSEP_OFF }, { NULL, -1 } }; diff --git a/servconf.h b/servconf.h index c2eeed665..096d596d7 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.102 2012/06/19 18:25:28 markus Exp $ */ +/* $OpenBSD: servconf.h,v 1.103 2012/07/10 02:19:15 djm Exp $ */ /* * Author: Tatu Ylonen @@ -39,7 +39,7 @@ /* use_privsep */ #define PRIVSEP_OFF 0 #define PRIVSEP_ON 1 -#define PRIVSEP_SANDBOX 2 +#define PRIVSEP_NOSANDBOX 2 #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ diff --git a/sshd.c b/sshd.c index 64b846f6c..9aff5e8af 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.392 2012/06/30 14:35:09 markus Exp $ */ +/* $OpenBSD: sshd.c,v 1.393 2012/07/10 02:19:15 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -635,7 +635,7 @@ privsep_preauth(Authctxt *authctxt) /* Store a pointer to the kex for later rekeying */ pmonitor->m_pkex = &xxx_kex; - if (use_privsep == PRIVSEP_SANDBOX) + if (use_privsep == PRIVSEP_ON) box = ssh_sandbox_init(); pid = fork(); if (pid == -1) { diff --git a/sshd_config b/sshd_config index ec3ca2afc..9424ee2c6 100644 --- a/sshd_config +++ b/sshd_config @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.86 2012/04/12 02:43:55 djm Exp $ +# $OpenBSD: sshd_config,v 1.87 2012/07/10 02:19:15 djm Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -99,7 +99,7 @@ AuthorizedKeysFile .ssh/authorized_keys #PrintLastLog yes #TCPKeepAlive yes #UseLogin no -#UsePrivilegeSeparation yes +UsePrivilegeSeparation sandbox # Default for new installations. #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 -- cgit v1.2.3