From 608b009282d598aa865148d83ca1fbc1fd10f065 Mon Sep 17 00:00:00 2001 From: dtucker Date: Wed, 29 Apr 2015 03:48:56 +0000 Subject: [PATCH] Allow ListenAddress, Port and AddressFamily in any order. bz#68, ok djm@, jmc@ (for the man page bit). --- usr.bin/ssh/servconf.c | 66 +++++++++++++++++++++++++++++++-------- usr.bin/ssh/servconf.h | 6 ++-- usr.bin/ssh/sshd_config.5 | 9 ++---- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c index 82605130fa6..68956c4d988 100644 --- a/usr.bin/ssh/servconf.c +++ b/usr.bin/ssh/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.265 2015/04/27 21:42:48 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.266 2015/04/29 03:48:56 dtucker Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -68,6 +68,8 @@ initialize_server_options(ServerOptions *options) memset(options, 0, sizeof(*options)); options->num_ports = 0; options->ports_from_cmdline = 0; + options->queued_listen_addrs = NULL; + options->num_queued_listens = 0; options->listen_addrs = NULL; options->address_family = -1; options->num_host_key_files = 0; @@ -188,6 +190,8 @@ fill_default_server_options(ServerOptions *options) /* No certificates by default */ if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; + if (options->address_family == -1) + options->address_family = AF_UNSPEC; if (options->listen_addrs == NULL) add_listen_addr(options, NULL, 0); if (options->pid_file == NULL) @@ -549,10 +553,6 @@ add_listen_addr(ServerOptions *options, char *addr, int port) { u_int i; - if (options->num_ports == 0) - options->ports[options->num_ports++] = SSH_DEFAULT_PORT; - if (options->address_family == -1) - options->address_family = AF_UNSPEC; if (port == 0) for (i = 0; i < options->num_ports; i++) add_one_listen_addr(options, addr, options->ports[i]); @@ -582,6 +582,51 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) options->listen_addrs = aitop; } +/* + * Queue a ListenAddress to be processed once we have all of the Ports + * and AddressFamily options. + */ +static void +queue_listen_addr(ServerOptions *options, char *addr, int port) +{ + options->queued_listen_addrs = xreallocarray( + options->queued_listen_addrs, options->num_queued_listens + 1, + sizeof(addr)); + options->queued_listen_ports = xreallocarray( + options->queued_listen_ports, options->num_queued_listens + 1, + sizeof(port)); + options->queued_listen_addrs[options->num_queued_listens] = + xstrdup(addr); + options->queued_listen_ports[options->num_queued_listens] = port; + options->num_queued_listens++; +} + +/* + * Process queued (text) ListenAddress entries. + */ +static void +process_queued_listen_addrs(ServerOptions *options) +{ + u_int i; + + if (options->num_ports == 0) + options->ports[options->num_ports++] = SSH_DEFAULT_PORT; + if (options->address_family == -1) + options->address_family = AF_UNSPEC; + + for (i = 0; i < options->num_queued_listens; i++) { + add_listen_addr(options, options->queued_listen_addrs[i], + options->queued_listen_ports[i]); + free(options->queued_listen_addrs[i]); + options->queued_listen_addrs[i] = NULL; + } + free(options->queued_listen_addrs); + options->queued_listen_addrs = NULL; + free(options->queued_listen_ports); + options->queued_listen_ports = NULL; + options->num_queued_listens = 0; +} + struct connection_info * get_connection_info(int populate, int use_dns) { @@ -892,9 +937,6 @@ process_server_config_line(ServerOptions *options, char *line, /* ignore ports from configfile if cmdline specifies ports */ if (options->ports_from_cmdline) return 0; - if (options->listen_addrs != NULL) - fatal("%s line %d: ports must be specified before " - "ListenAddress.", filename, linenum); if (options->num_ports >= MAX_PORTS) fatal("%s line %d: too many ports.", filename, linenum); @@ -946,7 +988,7 @@ process_server_config_line(ServerOptions *options, char *line, /* check for bare IPv6 address: no "[]" and 2 or more ":" */ if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL && strchr(p+1, ':') != NULL) { - add_listen_addr(options, arg, 0); + queue_listen_addr(options, arg, 0); break; } p = hpdelim(&arg); @@ -959,16 +1001,13 @@ process_server_config_line(ServerOptions *options, char *line, else if ((port = a2port(arg)) <= 0) fatal("%s line %d: bad port number", filename, linenum); - add_listen_addr(options, p, port); + queue_listen_addr(options, p, port); break; case sAddressFamily: intptr = &options->address_family; multistate_ptr = multistate_addressfamily; - if (options->listen_addrs != NULL) - fatal("%s line %d: address family must be specified " - "before ListenAddress.", filename, linenum); parse_multistate: arg = strdelim(&cp); if (!arg || *arg == '\0') @@ -1903,6 +1942,7 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", filename, bad_options); + process_queued_listen_addrs(options); } static const char * diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h index 447a2cec867..6886e351ae5 100644 --- a/usr.bin/ssh/servconf.h +++ b/usr.bin/ssh/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.116 2015/01/13 07:39:19 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.117 2015/04/29 03:48:56 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -58,7 +58,9 @@ typedef struct { u_int num_ports; u_int ports_from_cmdline; int ports[MAX_PORTS]; /* Port number to listen on. */ - char *listen_addr; /* Address on which the server listens. */ + u_int num_queued_listens; + char **queued_listen_addrs; + int *queued_listen_ports; struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ int address_family; /* Address family used by the server. */ char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */ diff --git a/usr.bin/ssh/sshd_config.5 b/usr.bin/ssh/sshd_config.5 index 0e0952cd653..b748e17e782 100644 --- a/usr.bin/ssh/sshd_config.5 +++ b/usr.bin/ssh/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.199 2015/04/28 13:47:38 jmc Exp $ -.Dd $Mdocdate: April 28 2015 $ +.\" $OpenBSD: sshd_config.5,v 1.200 2015/04/29 03:48:56 dtucker Exp $ +.Dd $Mdocdate: April 29 2015 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -831,16 +831,13 @@ The following forms may be used: If .Ar port is not specified, -sshd will listen on the address and all prior +sshd will listen on the address and all .Cm Port options specified. The default is to listen on all local addresses. Multiple .Cm ListenAddress options are permitted. -Additionally, any -.Cm Port -options must precede this option for non-port qualified addresses. .It Cm LoginGraceTime The server disconnects after this time if the user has not successfully logged in. -- 2.20.1