From 6f72280553cb6918859ebcacc717f2d2fafc1a27 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 20 Oct 2017 12:52:50 +1100 Subject: upstream commit Apply missing commit 1.127 to servconf.h Upstream-ID: f14c4bac74a2b7cf1e3cff6bea5c447f192a7d15 --- servconf.h | 52 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) (limited to 'servconf.h') diff --git a/servconf.h b/servconf.h index 1dca702e6..1ff3bc5a1 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.126 2017/10/02 19:33:20 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.127 2017/10/05 15:52:03 djm Exp $ */ /* * Author: Tatu Ylonen @@ -18,17 +18,7 @@ #define MAX_PORTS 256 /* Max # ports. */ -#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ -#define MAX_DENY_USERS 256 /* Max # users on deny list. */ -#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ -#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ -#define MAX_HOSTKEYS 256 /* Max # hostkeys. */ -#define MAX_HOSTCERTS 256 /* Max # host certificates. */ -#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */ -#define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */ -#define MAX_AUTHKEYS_FILES 256 /* Max # of authorized_keys files. */ -#define MAX_AUTH_METHODS 256 /* Max # of AuthenticationMethods. */ /* permit_root_login */ #define PERMIT_NOT_SET -1 @@ -68,14 +58,16 @@ typedef struct { 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. */ - int num_host_key_files; /* Number of files for host keys. */ - char *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */ - int num_host_cert_files; /* Number of files for host certs. */ - char *host_key_agent; /* ssh-agent socket for host keys. */ - char *pid_file; /* Where to put our pid */ + struct addrinfo *listen_addrs; /* Addresses for server to listen. */ + int address_family; /* Address family used by the server. */ + + char **host_key_files; /* Files containing host keys. */ + u_int num_host_key_files; /* Number of files for host keys. */ + char **host_cert_files; /* Files containing host certs. */ + u_int num_host_cert_files; /* Number of files for host certs. */ + + char *host_key_agent; /* ssh-agent socket for host keys. */ + char *pid_file; /* Where to put our pid */ int login_grace_time; /* Disconnect if no auth in this time * (sec). */ int permit_root_login; /* PERMIT_*, see above */ @@ -134,13 +126,13 @@ typedef struct { int allow_agent_forwarding; int disable_forwarding; u_int num_allow_users; - char *allow_users[MAX_ALLOW_USERS]; + char **allow_users; u_int num_deny_users; - char *deny_users[MAX_DENY_USERS]; + char **deny_users; u_int num_allow_groups; - char *allow_groups[MAX_ALLOW_GROUPS]; + char **allow_groups; u_int num_deny_groups; - char *deny_groups[MAX_DENY_GROUPS]; + char **deny_groups; u_int num_subsystems; char *subsystem_name[MAX_SUBSYSTEMS]; @@ -148,7 +140,7 @@ typedef struct { char *subsystem_args[MAX_SUBSYSTEMS]; u_int num_accept_env; - char *accept_env[MAX_ACCEPT_ENV]; + char **accept_env; int max_startups_begin; int max_startups_rate; @@ -167,8 +159,8 @@ typedef struct { * disconnect the session */ - u_int num_authkeys_files; /* Files containing public keys */ - char *authorized_keys_files[MAX_AUTHKEYS_FILES]; + u_int num_authkeys_files; /* Files containing public keys */ + char **authorized_keys_files; char *adm_forced_command; @@ -194,7 +186,7 @@ typedef struct { char *version_addendum; /* Appended to SSH banner */ u_int num_auth_methods; - char *auth_methods[MAX_AUTH_METHODS]; + char **auth_methods; int fingerprint_hash; int expose_userauth_info; @@ -237,7 +229,7 @@ struct connection_info { M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \ M_CP_STRARRAYOPT(accept_env, num_accept_env); \ M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ - M_CP_STRARRAYOPT_ALLOC(permitted_opens, num_permitted_opens); \ + M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ } while (0) struct connection_info *get_connection_info(int, int); @@ -255,5 +247,9 @@ 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 *); +void servconf_add_hostkey(const char *, const int, + ServerOptions *, const char *path); +void servconf_add_hostcert(const char *, const int, + ServerOptions *, const char *path); #endif /* SERVCONF_H */ -- cgit v1.2.3 From acf559e1cffbd1d6167cc1742729fc381069f06b Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Wed, 25 Oct 2017 00:15:35 +0000 Subject: upstream commit Add optional rdomain qualifier to sshd_config's ListenAddress option to allow listening on a different rdomain(4), e.g. ListenAddress 0.0.0.0 rdomain 4 Upstream-ID: 24b6622c376feeed9e9be8b9605e593695ac9091 --- channels.c | 19 +---- misc.c | 40 +++++++++- misc.h | 4 +- servconf.c | 229 +++++++++++++++++++++++++++++++++++++++++----------------- servconf.h | 25 ++++++- sshd.c | 45 ++++++++---- sshd_config.5 | 29 ++++++-- 7 files changed, 283 insertions(+), 108 deletions(-) (limited to 'servconf.h') diff --git a/channels.c b/channels.c index 83442be06..07dc9577a 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.375 2017/09/24 13:45:34 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.376 2017/10/25 00:15:35 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1668,19 +1668,6 @@ port_open_helper(struct ssh *ssh, Channel *c, char *rtype) free(local_ipaddr); } -static void -channel_set_reuseaddr(int fd) -{ - int on = 1; - - /* - * Set socket options. - * Allow local port reuse in TIME_WAIT. - */ - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) - error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno)); -} - void channel_set_x11_refuse_time(struct ssh *ssh, u_int refuse_time) { @@ -3368,7 +3355,7 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, continue; } - channel_set_reuseaddr(sock); + set_reuseaddr(sock); if (ai->ai_family == AF_INET6) sock_set_v6only(sock); @@ -4439,7 +4426,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, if (ai->ai_family == AF_INET6) sock_set_v6only(sock); if (x11_use_localhost) - channel_set_reuseaddr(sock); + set_reuseaddr(sock); if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { debug2("%s: bind port %d: %.100s", __func__, port, strerror(errno)); diff --git a/misc.c b/misc.c index cb8bf5c14..cc22fbef4 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.116 2017/10/24 19:41:45 millert Exp $ */ +/* $OpenBSD: misc.c,v 1.117 2017/10/25 00:15:35 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -167,6 +167,44 @@ set_nodelay(int fd) error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); } +/* Allow local port reuse in TIME_WAIT */ +int +set_reuseaddr(int fd) +{ + int on = 1; + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { + error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno)); + return -1; + } + return 0; +} + +/* Set routing table */ +int +set_rdomain(int fd, const char *name) +{ + int rtable; + const char *errstr; + + if (name == NULL) + return 0; /* default table */ + + rtable = (int)strtonum(name, 0, 255, &errstr); + if (errstr != NULL) { + /* Shouldn't happen */ + error("Invalid routing domain \"%s\": %s", name, errstr); + return -1; + } + if (setsockopt(fd, SOL_SOCKET, SO_RTABLE, + &rtable, sizeof(rtable)) == -1) { + error("Failed to set routing domain %d on fd %d: %s", + rtable, fd, strerror(errno)); + return -1; + } + return 0; +} + /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" #define QUOTE "\"" diff --git a/misc.h b/misc.h index 19fdf5c84..f36081f5d 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.65 2017/10/23 05:08:00 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.66 2017/10/25 00:15:35 djm Exp $ */ /* * Author: Tatu Ylonen @@ -48,6 +48,8 @@ char *strdelim(char **); int set_nonblock(int); int unset_nonblock(int); void set_nodelay(int); +int set_reuseaddr(int); +int set_rdomain(int, const char *); int a2port(const char *); int a2tun(const char *, int *); char *put_host_port(const char *, u_short); diff --git a/servconf.c b/servconf.c index a96df4f67..68db047f2 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.314 2017/10/05 15:52:03 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.315 2017/10/25 00:15:35 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -15,10 +15,16 @@ #include #include +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif #include #include #include +#ifdef HAVE_NET_ROUTE_H +#include +#endif #include #include @@ -58,8 +64,10 @@ #include "myproposal.h" #include "digest.h" -static void add_listen_addr(ServerOptions *, char *, int); -static void add_one_listen_addr(ServerOptions *, char *, int); +static void add_listen_addr(ServerOptions *, const char *, + const char *, int); +static void add_one_listen_addr(ServerOptions *, const char *, + const char *, int); /* Use of privilege separation or not */ extern int use_privsep; @@ -81,6 +89,7 @@ initialize_server_options(ServerOptions *options) options->queued_listen_addrs = NULL; options->num_queued_listens = 0; options->listen_addrs = NULL; + options->num_listen_addrs = 0; options->address_family = -1; options->num_host_key_files = 0; options->num_host_cert_files = 0; @@ -252,7 +261,7 @@ fill_default_server_options(ServerOptions *options) if (options->address_family == -1) options->address_family = AF_UNSPEC; if (options->listen_addrs == NULL) - add_listen_addr(options, NULL, 0); + add_listen_addr(options, NULL, NULL, 0); if (options->pid_file == NULL) options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); if (options->login_grace_time == -1) @@ -658,23 +667,51 @@ derelativise_path(const char *path) } static void -add_listen_addr(ServerOptions *options, char *addr, int port) +add_listen_addr(ServerOptions *options, const char *addr, + const char *rdomain, int port) { u_int i; - if (port == 0) - for (i = 0; i < options->num_ports; i++) - add_one_listen_addr(options, addr, options->ports[i]); - else - add_one_listen_addr(options, addr, port); + if (port > 0) + add_one_listen_addr(options, addr, rdomain, port); + else { + for (i = 0; i < options->num_ports; i++) { + add_one_listen_addr(options, addr, rdomain, + options->ports[i]); + } + } } static void -add_one_listen_addr(ServerOptions *options, char *addr, int port) +add_one_listen_addr(ServerOptions *options, const char *addr, + const char *rdomain, int port) { struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr; + u_int i; + + /* Find listen_addrs entry for this rdomain */ + for (i = 0; i < options->num_listen_addrs; i++) { + if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL) + break; + if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL) + continue; + if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0) + break; + } + if (i >= options->num_listen_addrs) { + /* No entry for this rdomain; allocate one */ + if (i >= INT_MAX) + fatal("%s: too many listen addresses", __func__); + options->listen_addrs = xrecallocarray(options->listen_addrs, + options->num_listen_addrs, options->num_listen_addrs + 1, + sizeof(*options->listen_addrs)); + i = options->num_listen_addrs++; + if (rdomain != NULL) + options->listen_addrs[i].rdomain = xstrdup(rdomain); + } + /* options->listen_addrs[i] points to the addresses for this rdomain */ memset(&hints, 0, sizeof(hints)); hints.ai_family = options->address_family; @@ -687,8 +724,37 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) ssh_gai_strerror(gaierr)); for (ai = aitop; ai->ai_next; ai = ai->ai_next) ; - ai->ai_next = options->listen_addrs; - options->listen_addrs = aitop; + ai->ai_next = options->listen_addrs[i].addrs; + options->listen_addrs[i].addrs = aitop; +} + +/* Returns nonzero if the routing domain name is valid */ +static int +valid_rdomain(const char *name) +{ + const char *errstr; + long long num; + struct rt_tableinfo info; + int mib[6]; + size_t miblen = sizeof(mib); + + if (name == NULL) + return 1; + + num = strtonum(name, 0, 255, &errstr); + if (errstr != NULL) + return 0; + + /* Check whether the table actually exists */ + memset(mib, 0, sizeof(mib)); + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[4] = NET_RT_TABLE; + mib[5] = (int)num; + if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1) + return 0; + + return 1; } /* @@ -696,18 +762,19 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) * and AddressFamily options. */ static void -queue_listen_addr(ServerOptions *options, char *addr, int port) +queue_listen_addr(ServerOptions *options, const char *addr, + const char *rdomain, 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++; + struct queued_listenaddr *qla; + + options->queued_listen_addrs = xrecallocarray( + options->queued_listen_addrs, + options->num_queued_listens, options->num_queued_listens + 1, + sizeof(*options->queued_listen_addrs)); + qla = &options->queued_listen_addrs[options->num_queued_listens++]; + qla->addr = xstrdup(addr); + qla->port = port; + qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain); } /* @@ -717,6 +784,7 @@ static void process_queued_listen_addrs(ServerOptions *options) { u_int i; + struct queued_listenaddr *qla; if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; @@ -724,15 +792,13 @@ process_queued_listen_addrs(ServerOptions *options) 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; + qla = &options->queued_listen_addrs[i]; + add_listen_addr(options, qla->addr, qla->rdomain, qla->port); + free(qla->addr); + free(qla->rdomain); } 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; } @@ -1127,20 +1193,33 @@ 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) { - queue_listen_addr(options, arg, 0); - break; - } - p = hpdelim(&arg); - if (p == NULL) - fatal("%s line %d: bad address:port usage", - filename, linenum); - p = cleanhostname(p); - if (arg == NULL) port = 0; - else if ((port = a2port(arg)) <= 0) - fatal("%s line %d: bad port number", filename, linenum); + p = arg; + } else { + p = hpdelim(&arg); + if (p == NULL) + fatal("%s line %d: bad address:port usage", + filename, linenum); + p = cleanhostname(p); + if (arg == NULL) + port = 0; + else if ((port = a2port(arg)) <= 0) + fatal("%s line %d: bad port number", + filename, linenum); + } + /* Optional routing table */ + arg2 = NULL; + if ((arg = strdelim(&cp)) != NULL) { + if (strcmp(arg, "rdomain") != 0 || + (arg2 = strdelim(&cp)) == NULL) + fatal("%s line %d: bad ListenAddress syntax", + filename, linenum); + if (!valid_rdomain(arg2)) + fatal("%s line %d: bad routing domain", + filename, linenum); + } - queue_listen_addr(options, p, port); + queue_listen_addr(options, p, arg2, port); break; @@ -2251,45 +2330,61 @@ dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) printf("\n"); } -void -dump_config(ServerOptions *o) +static char * +format_listen_addrs(struct listenaddr *la) { - u_int i; - int ret; + int r; struct addrinfo *ai; - char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL; + char addr[NI_MAXHOST], port[NI_MAXSERV]; char *laddr1 = xstrdup(""), *laddr2 = NULL; - /* these are usually at the top of the config */ - for (i = 0; i < o->num_ports; i++) - printf("port %d\n", o->ports[i]); - dump_cfg_fmtint(sAddressFamily, o->address_family); - /* * ListenAddress must be after Port. add_one_listen_addr pushes * addresses onto a stack, so to maintain ordering we need to * print these in reverse order. */ - for (ai = o->listen_addrs; ai; ai = ai->ai_next) { - if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, + for (ai = la->addrs; ai; ai = ai->ai_next) { + if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { - error("getnameinfo failed: %.100s", - (ret != EAI_SYSTEM) ? gai_strerror(ret) : - strerror(errno)); + error("getnameinfo: %.100s", ssh_gai_strerror(r)); + continue; + } + laddr2 = laddr1; + if (ai->ai_family == AF_INET6) { + xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s", + addr, port, + la->rdomain == NULL ? "" : " rdomain ", + la->rdomain == NULL ? "" : la->rdomain, + laddr2); } else { - laddr2 = laddr1; - if (ai->ai_family == AF_INET6) - xasprintf(&laddr1, "listenaddress [%s]:%s\n%s", - addr, port, laddr2); - else - xasprintf(&laddr1, "listenaddress %s:%s\n%s", - addr, port, laddr2); - free(laddr2); + xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s", + addr, port, + la->rdomain == NULL ? "" : " rdomain ", + la->rdomain == NULL ? "" : la->rdomain, + laddr2); } + free(laddr2); + } + return laddr1; +} + +void +dump_config(ServerOptions *o) +{ + char *s; + u_int i; + + /* these are usually at the top of the config */ + for (i = 0; i < o->num_ports; i++) + printf("port %d\n", o->ports[i]); + dump_cfg_fmtint(sAddressFamily, o->address_family); + + for (i = 0; i < o->num_listen_addrs; i++) { + s = format_listen_addrs(&o->listen_addrs[i]); + printf("%s", s); + free(s); } - printf("%s", laddr1); - free(laddr1); /* integer arguments */ #ifdef USE_PAM diff --git a/servconf.h b/servconf.h index 1ff3bc5a1..3d0a0653f 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.127 2017/10/05 15:52:03 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.128 2017/10/25 00:15:35 djm Exp $ */ /* * Author: Tatu Ylonen @@ -51,14 +51,31 @@ struct ssh; struct fwd_perm_list; +/* + * Used to store addresses from ListenAddr directives. These may be + * incomplete, as they may specify addresses that need to be merged + * with any ports requested by ListenPort. + */ +struct queued_listenaddr { + char *addr; + int port; /* <=0 if unspecified */ + char *rdomain; +}; + +/* Resolved listen addresses, grouped by optional routing domain */ +struct listenaddr { + char *rdomain; + struct addrinfo *addrs; +}; + typedef struct { u_int num_ports; u_int ports_from_cmdline; int ports[MAX_PORTS]; /* Port number to listen on. */ + struct queued_listenaddr *queued_listen_addrs; u_int num_queued_listens; - char **queued_listen_addrs; - int *queued_listen_ports; - struct addrinfo *listen_addrs; /* Addresses for server to listen. */ + struct listenaddr *listen_addrs; + u_int num_listen_addrs; int address_family; /* Address family used by the server. */ char **host_key_files; /* Files containing host keys. */ diff --git a/sshd.c b/sshd.c index 0e3ac26db..93b02b6c8 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.493 2017/10/05 15:52:03 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.494 2017/10/25 00:15:35 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1015,13 +1015,13 @@ server_accept_inetd(int *sock_in, int *sock_out) * Listen for TCP connections */ static void -server_listen(void) +listen_on_addrs(struct listenaddr *la) { - int ret, listen_sock, on = 1; + int ret, listen_sock; struct addrinfo *ai; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; - for (ai = options.listen_addrs; ai; ai = ai->ai_next) { + for (ai = la->addrs; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; if (num_listen_socks >= MAX_LISTEN_SOCKS) @@ -1051,13 +1051,13 @@ server_listen(void) close(listen_sock); continue; } - /* - * Set socket options. - * Allow local port reuse in TIME_WAIT. - */ - if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)) == -1) - error("setsockopt SO_REUSEADDR: %s", strerror(errno)); + /* Socket options */ + set_reuseaddr(listen_sock); + if (la->rdomain != NULL && + set_rdomain(listen_sock, la->rdomain) == -1) { + close(listen_sock); + continue; + } /* Only communicate in IPv6 over AF_INET6 sockets. */ if (ai->ai_family == AF_INET6) @@ -1079,9 +1079,28 @@ server_listen(void) if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0) fatal("listen on [%s]:%s: %.100s", ntop, strport, strerror(errno)); - logit("Server listening on %s port %s.", ntop, strport); + logit("Server listening on %s port %s%s%s.", + ntop, strport, + la->rdomain == NULL ? "" : " rdomain ", + la->rdomain == NULL ? "" : la->rdomain); + } +} + +static void +server_listen(void) +{ + u_int i; + + for (i = 0; i < options.num_listen_addrs; i++) { + listen_on_addrs(&options.listen_addrs[i]); + freeaddrinfo(options.listen_addrs[i].addrs); + free(options.listen_addrs[i].rdomain); + memset(&options.listen_addrs[i], 0, + sizeof(options.listen_addrs[i])); } - freeaddrinfo(options.listen_addrs); + free(options.listen_addrs); + options.listen_addrs = NULL; + options.num_listen_addrs = 0; if (!num_listen_socks) fatal("Cannot bind any address."); diff --git a/sshd_config.5 b/sshd_config.5 index 77a8354ab..b63a022b7 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.255 2017/10/13 16:50:45 jmc Exp $ -.Dd $Mdocdate: October 13 2017 $ +.\" $OpenBSD: sshd_config.5,v 1.256 2017/10/25 00:15:35 djm Exp $ +.Dd $Mdocdate: October 25 2017 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -909,31 +909,48 @@ The following forms may be used: .It .Cm ListenAddress .Sm off -.Ar host | Ar IPv4_addr | Ar IPv6_addr +.Ar hostname | Ar address .Sm on +.Oo rdomain Ar domain Oc .It .Cm ListenAddress .Sm off -.Ar host | Ar IPv4_addr : Ar port +.Ar hostname : Ar port .Sm on +.Oo rdomain Ar domain Oc +.It +.Cm ListenAddress +.Sm off +.Ar IPv4_address : Ar port +.Sm on +.Oo rdomain Ar domain Oc .It .Cm ListenAddress .Sm off .Oo -.Ar host | Ar IPv6_addr Oc : Ar port +.Ar hostname | address Oc : Ar port .Sm on +.Oo rdomain Ar domain Oc .El .Pp +The optional +.Cm rdomain +qualifier requests +.Xr sshd 8 +listen in an explicit routing domain. If .Ar port is not specified, sshd will listen on the address and all .Cm Port options specified. -The default is to listen on all local addresses. +The default is to listen on all local addresses on the current default +routing domain. Multiple .Cm ListenAddress options are permitted. +For more information on routing domains, see +.Xr rdomain 4. .It Cm LoginGraceTime The server disconnects after this time if the user has not successfully logged in. -- cgit v1.2.3 From 35eb33fb957979e3fcbe6ea0eaee8bf4a217421a Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Wed, 25 Oct 2017 00:17:08 +0000 Subject: upstream commit add sshd_config RDomain keyword to place sshd and the subsequent user session (including the shell and any TCP/IP forwardings) into the specified rdomain(4) ok markus@ Upstream-ID: be2358e86346b5cacf20d90f59f980b87d1af0f5 --- misc.c | 20 ++++++++++++++++++-- misc.h | 3 ++- packet.c | 14 +++++++++++++- packet.h | 4 +++- servconf.c | 21 +++++++++++++++++++-- servconf.h | 5 ++++- sshd.c | 30 +++++++++++++++++++++++++++++- sshd_config.5 | 17 ++++++++++++++++- 8 files changed, 104 insertions(+), 10 deletions(-) (limited to 'servconf.h') diff --git a/misc.c b/misc.c index cc22fbef4..9b1ea4fa6 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.117 2017/10/25 00:15:35 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.118 2017/10/25 00:17:08 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -180,7 +180,23 @@ set_reuseaddr(int fd) return 0; } -/* Set routing table */ +/* Get/set routing domain */ +char * +get_rdomain(int fd) +{ + int rtable; + char *ret; + socklen_t len = sizeof(rtable); + + if (getsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, &len) == -1) { + error("Failed to get routing domain for fd %d: %s", + fd, strerror(errno)); + return NULL; + } + xasprintf(&ret, "%d", rtable); + return ret; +} + int set_rdomain(int fd, const char *name) { diff --git a/misc.h b/misc.h index f36081f5d..5ad30ce3b 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.66 2017/10/25 00:15:35 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.67 2017/10/25 00:17:08 djm Exp $ */ /* * Author: Tatu Ylonen @@ -49,6 +49,7 @@ int set_nonblock(int); int unset_nonblock(int); void set_nodelay(int); int set_reuseaddr(int); +char *get_rdomain(int); int set_rdomain(int, const char *); int a2port(const char *); int a2tun(const char *, int *); diff --git a/packet.c b/packet.c index 85638cb2a..448da0964 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.265 2017/10/13 21:13:54 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.266 2017/10/25 00:17:08 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -557,6 +557,18 @@ ssh_local_port(struct ssh *ssh) return ssh->local_port; } +/* Returns the routing domain of the input socket, or NULL if unavailable */ +const char * +ssh_packet_rdomain_in(struct ssh *ssh) +{ + if (ssh->rdomain_in != NULL) + return ssh->rdomain_in; + if (!ssh_packet_connection_is_on_socket(ssh)) + return NULL; + ssh->rdomain_in = get_rdomain(ssh->state->connection_in); + return ssh->rdomain_in; +} + /* Closes the connection and clears and frees internal data structures. */ static void diff --git a/packet.h b/packet.h index 40837e9db..55f07fc90 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.82 2017/09/12 06:32:07 djm Exp $ */ +/* $OpenBSD: packet.h,v 1.83 2017/10/25 00:17:08 djm Exp $ */ /* * Author: Tatu Ylonen @@ -61,6 +61,7 @@ struct ssh { int remote_port; char *local_ipaddr; int local_port; + char *rdomain_in; /* Optional preamble for log messages (e.g. username) */ char *log_preamble; @@ -162,6 +163,7 @@ const char *ssh_remote_ipaddr(struct ssh *); int ssh_remote_port(struct ssh *); const char *ssh_local_ipaddr(struct ssh *); int ssh_local_port(struct ssh *); +const char *ssh_packet_rdomain_in(struct ssh *); void ssh_packet_set_rekey_limits(struct ssh *, u_int64_t, u_int32_t); time_t ssh_packet_get_rekey_timeout(struct ssh *); diff --git a/servconf.c b/servconf.c index 68db047f2..51139c31c 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.315 2017/10/25 00:15:35 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.316 2017/10/25 00:17:08 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -91,6 +91,7 @@ initialize_server_options(ServerOptions *options) options->listen_addrs = NULL; options->num_listen_addrs = 0; options->address_family = -1; + options->routing_domain = NULL; options->num_host_key_files = 0; options->num_host_cert_files = 0; options->host_key_agent = NULL; @@ -406,6 +407,7 @@ fill_default_server_options(ServerOptions *options) CLEAR_ON_NONE(options->authorized_principals_file); CLEAR_ON_NONE(options->adm_forced_command); CLEAR_ON_NONE(options->chroot_directory); + CLEAR_ON_NONE(options->routing_domain); for (i = 0; i < options->num_host_key_files; i++) CLEAR_ON_NONE(options->host_key_files[i]); for (i = 0; i < options->num_host_cert_files; i++) @@ -469,7 +471,7 @@ typedef enum { sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sStreamLocalBindMask, sStreamLocalBindUnlink, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, - sExposeAuthInfo, + sExposeAuthInfo, sRDomain, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; @@ -614,6 +616,7 @@ static struct { { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, + { "rdomain", sRDomain, SSHCFG_ALL }, { NULL, sBadOption, 0 } }; @@ -1984,6 +1987,19 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->expose_userauth_info; goto parse_flag; + case sRDomain: + charptr = &options->routing_domain; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", + filename, linenum); + if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 && + !valid_rdomain(arg)) + fatal("%s line %d: bad routing domain", + filename, linenum); + if (*activep && *charptr == NULL) + *charptr = xstrdup(arg); + case sDeprecated: case sIgnore: case sUnsupported: @@ -2473,6 +2489,7 @@ dump_config(ServerOptions *o) o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG); dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ? o->pubkey_key_types : KEX_DEFAULT_PK_ALG); + dump_cfg_string(sRDomain, o->routing_domain); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); diff --git a/servconf.h b/servconf.h index 3d0a0653f..1f042e872 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.128 2017/10/25 00:15:35 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.129 2017/10/25 00:17:08 djm Exp $ */ /* * Author: Tatu Ylonen @@ -78,6 +78,8 @@ typedef struct { u_int num_listen_addrs; int address_family; /* Address family used by the server. */ + char *routing_domain; /* Bind session to routing domain */ + char **host_key_files; /* Files containing host keys. */ u_int num_host_key_files; /* Number of files for host keys. */ char **host_cert_files; /* Files containing host certs. */ @@ -239,6 +241,7 @@ struct connection_info { M_CP_STROPT(authorized_principals_command_user); \ M_CP_STROPT(hostbased_key_types); \ M_CP_STROPT(pubkey_key_types); \ + M_CP_STROPT(routing_domain); \ M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ M_CP_STRARRAYOPT(allow_users, num_allow_users); \ M_CP_STRARRAYOPT(deny_users, num_deny_users); \ diff --git a/sshd.c b/sshd.c index 93b02b6c8..3ad106f72 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.494 2017/10/25 00:15:35 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.495 2017/10/25 00:17:08 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1368,6 +1368,31 @@ check_ip_options(struct ssh *ssh) #endif /* IP_OPTIONS */ } +/* Set the routing domain for this process */ +static void +set_process_rdomain(struct ssh *ssh, const char *name) +{ + int rtable, ortable = getrtable(); + const char *errstr; + + if (name == NULL) + return; /* default */ + + if (strcmp(name, "%D") == 0) { + /* "expands" to routing domain of connection */ + if ((name = ssh_packet_rdomain_in(ssh)) == NULL) + return; + } + + rtable = (int)strtonum(name, 0, 255, &errstr); + if (errstr != NULL) /* Shouldn't happen */ + fatal("Invalid routing domain \"%s\": %s", name, errstr); + if (rtable != ortable && setrtable(rtable) != 0) + fatal("Unable to set routing domain %d: %s", + rtable, strerror(errno)); + debug("%s: set routing domain %d (was %d)", __func__, rtable, ortable); +} + /* * Main program for the daemon. */ @@ -1983,6 +2008,9 @@ main(int ac, char **av) cleanup_exit(255); } + if (options.routing_domain != NULL) + set_process_rdomain(ssh, options.routing_domain); + /* * The rest of the code depends on the fact that * ssh_remote_ipaddr() caches the remote ip, even if diff --git a/sshd_config.5 b/sshd_config.5 index b63a022b7..c216fb75b 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,7 +33,7 @@ .\" (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.256 2017/10/25 00:15:35 djm Exp $ +.\" $OpenBSD: sshd_config.5,v 1.257 2017/10/25 00:17:08 djm Exp $ .Dd $Mdocdate: October 25 2017 $ .Dt SSHD_CONFIG 5 .Os @@ -1118,6 +1118,7 @@ Available keywords are .Cm PubkeyAuthentication , .Cm RekeyLimit , .Cm RevokedKeys , +.Cm RDomain , .Cm StreamLocalBindMask , .Cm StreamLocalBindUnlink , .Cm TrustedUserCAKeys , @@ -1378,6 +1379,15 @@ an OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . +.It Cm RDomain +Specifies an explicit routing domain that is applied after authentication +has completed. +The user session, as well and any forwarded or listening IP sockets will +be bound to this +.Xr rdomain 4 . +If the routing domain is set to +.Cm \&%D , +then the domain in which the incoming connection was recieved will be applied. .It Cm StreamLocalBindMask Sets the octal file creation mode mask .Pq umask @@ -1643,6 +1653,8 @@ which are expanded at runtime: .It %% A literal .Sq % . +.It \&%D +The routing domain in which the incoming connection was received. .It %F The fingerprint of the CA key. .It %f @@ -1679,6 +1691,9 @@ accepts the tokens %%, %h, and %u. .Pp .Cm ChrootDirectory accepts the tokens %%, %h, and %u. +.Pp +.Cm RoutingDomain +accepts the token %D. .Sh FILES .Bl -tag -width Ds .It Pa /etc/ssh/sshd_config -- cgit v1.2.3 From 68af80e6fdeaeb79432209db614386ff0f37e75f Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Wed, 25 Oct 2017 00:19:47 +0000 Subject: upstream commit add a "rdomain" criteria for the sshd_config Match keyword to allow conditional configuration that depends on which rdomain(4) a connection was recevied on. ok markus@ Upstream-ID: 27d8fd5a3f1bae18c9c6e533afdf99bff887a4fb --- servconf.c | 15 ++++++++++++++- servconf.h | 3 ++- sshd.8 | 5 +++-- sshd.c | 12 ++++++++---- sshd_config.5 | 11 +++++++++-- 5 files changed, 36 insertions(+), 10 deletions(-) (limited to 'servconf.h') diff --git a/servconf.c b/servconf.c index 51139c31c..64a865180 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.316 2017/10/25 00:17:08 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.317 2017/10/25 00:19:47 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -855,6 +855,7 @@ get_connection_info(int populate, int use_dns) ci.address = ssh_remote_ipaddr(ssh); ci.laddress = ssh_local_ipaddr(ssh); ci.lport = ssh_local_port(ssh); + ci.rdomain = ssh_packet_rdomain_in(ssh); return &ci; } @@ -1038,6 +1039,16 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) ci->laddress, port, line); else result = 0; + } else if (strcasecmp(attrib, "rdomain") == 0) { + if (ci == NULL || ci->rdomain == NULL) { + result = 0; + continue; + } + if (match_pattern_list(ci->rdomain, arg, 0) != 1) + result = 0; + else + debug("user %.100s matched 'RDomain %.100s' at " + "line %d", ci->rdomain, arg, line); } else { error("Unsupported Match attribute %s", attrib); return -1; @@ -2080,6 +2091,8 @@ int parse_server_match_testspec(struct connection_info *ci, char *spec) ci->user = xstrdup(p + 5); } else if (strncmp(p, "laddr=", 6) == 0) { ci->laddress = xstrdup(p + 6); + } else if (strncmp(p, "rdomain=", 8) == 0) { + ci->rdomain = xstrdup(p + 8); } else if (strncmp(p, "lport=", 6) == 0) { ci->lport = a2port(p + 6); if (ci->lport == -1) { diff --git a/servconf.h b/servconf.h index 1f042e872..37a0fb1a3 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.129 2017/10/25 00:17:08 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.130 2017/10/25 00:19:47 djm Exp $ */ /* * Author: Tatu Ylonen @@ -218,6 +218,7 @@ struct connection_info { const char *address; /* remote address */ const char *laddress; /* local address */ int lport; /* local port */ + const char *rdomain; /* routing domain if available */ }; diff --git a/sshd.8 b/sshd.8 index a4201146b..c16c433ef 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.291 2017/06/24 06:28:50 jmc Exp $ -.Dd $Mdocdate: June 24 2017 $ +.\" $OpenBSD: sshd.8,v 1.292 2017/10/25 00:19:47 djm Exp $ +.Dd $Mdocdate: October 25 2017 $ .Dt SSHD 8 .Os .Sh NAME @@ -109,6 +109,7 @@ The keywords are .Dq host , .Dq laddr , .Dq lport , +.Dq rdomain 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 3ad106f72..1220309d7 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.495 2017/10/25 00:17:08 djm Exp $ */ +/* $OpenBSD: sshd.c,v 1.496 2017/10/25 00:19:47 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1404,7 +1404,7 @@ main(int ac, char **av) extern int optind; int r, opt, on = 1, already_daemon, remote_port; int sock_in = -1, sock_out = -1, newsock = -1; - const char *remote_ip; + const char *remote_ip, *rdomain; char *fp, *line, *laddr, *logfile = NULL; int config_s[2] = { -1 , -1 }; u_int i, j; @@ -2022,10 +2022,14 @@ main(int ac, char **av) audit_connection_from(remote_ip, remote_port); #endif + rdomain = ssh_packet_rdomain_in(ssh); + /* Log the connection. */ laddr = get_local_ipaddr(sock_in); - verbose("Connection from %s port %d on %s port %d", - remote_ip, remote_port, laddr, ssh_local_port(ssh)); + verbose("Connection from %s port %d on %s port %d%s%s", + remote_ip, remote_port, laddr, ssh_local_port(ssh), + rdomain == NULL ? "" : " rdomain ", + rdomain == NULL ? "" : rdomain); free(laddr); /* diff --git a/sshd_config.5 b/sshd_config.5 index c216fb75b..0b91f9f74 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,7 +33,7 @@ .\" (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.257 2017/10/25 00:17:08 djm Exp $ +.\" $OpenBSD: sshd_config.5,v 1.258 2017/10/25 00:19:47 djm Exp $ .Dd $Mdocdate: October 25 2017 $ .Dt SSHD_CONFIG 5 .Os @@ -1054,8 +1054,15 @@ The available criteria are .Cm Host , .Cm LocalAddress , .Cm LocalPort , +.Cm RDomain , and -.Cm Address . +.Cm Address +(with +.Cm RDomain +representing the +.Xr rdomain 4 +on which the connection was received.) +.Pp The match patterns may consist of single entries or comma-separated lists and may use the wildcard and negation operators described in the .Sx PATTERNS -- cgit v1.2.3