mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-02-18 14:56:55 +00:00
upstream: add a "match localnetwork" predicate.
This allows matching on the addresses of available network interfaces and may be used to vary the effective client configuration based on network location (e.g. to use a ProxyJump when not on a particular network). ok markus@ OpenBSD-Commit-ID: cffb6ff9a3803abfc52b5cad0aa190c5e424c139
This commit is contained in:
parent
beec17bb31
commit
3071d85a47
77
readconf.c
77
readconf.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: readconf.c,v 1.377 2023/06/21 05:10:26 djm Exp $ */
|
||||
/* $OpenBSD: readconf.c,v 1.378 2023/07/17 04:04:36 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -20,6 +20,7 @@
|
||||
#include <sys/wait.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
@ -28,6 +29,9 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
# include <ifaddrs.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#ifdef HAVE_PATHS_H
|
||||
@ -576,6 +580,60 @@ execute_in_shell(const char *cmd)
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a local network interface address appears in CIDR pattern-
|
||||
* list 'addrlist'. Returns 1 if matched or 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
check_match_ifaddrs(const char *addrlist)
|
||||
{
|
||||
struct ifaddrs *ifa, *ifaddrs = NULL;
|
||||
int r, found = 0;
|
||||
char addr[NI_MAXHOST];
|
||||
socklen_t salen;
|
||||
|
||||
if (getifaddrs(&ifaddrs) != 0) {
|
||||
error("match localnetwork: getifaddrs failed: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
|
||||
(ifa->ifa_flags & IFF_UP) == 0)
|
||||
continue;
|
||||
switch (ifa->ifa_addr->sa_family) {
|
||||
case AF_INET:
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
salen = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
case AF_LINK:
|
||||
/* ignore */
|
||||
continue;
|
||||
default:
|
||||
debug2_f("interface %s: unsupported address family %d",
|
||||
ifa->ifa_name, ifa->ifa_addr->sa_family);
|
||||
continue;
|
||||
}
|
||||
if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr),
|
||||
NULL, 0, NI_NUMERICHOST)) != 0) {
|
||||
debug2_f("interface %s getnameinfo failed: %s",
|
||||
ifa->ifa_name, gai_strerror(r));
|
||||
continue;
|
||||
}
|
||||
debug3_f("interface %s addr %s", ifa->ifa_name, addr);
|
||||
if (addr_match_cidr_list(addr, addrlist) == 1) {
|
||||
debug3_f("matched interface %s: address %s in %s",
|
||||
ifa->ifa_name, addr, addrlist);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddrs);
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and execute a Match directive.
|
||||
*/
|
||||
@ -680,6 +738,15 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
|
||||
r = match_pattern_list(pw->pw_name, arg, 0) == 1;
|
||||
if (r == (negate ? 1 : 0))
|
||||
this_result = result = 0;
|
||||
} else if (strcasecmp(attrib, "localnetwork") == 0) {
|
||||
if (addr_match_cidr_list(NULL, arg) == -1) {
|
||||
/* Error already printed */
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
r = check_match_ifaddrs(arg) == 1;
|
||||
if (r == (negate ? 1 : 0))
|
||||
this_result = result = 0;
|
||||
} else if (strcasecmp(attrib, "exec") == 0) {
|
||||
char *conn_hash_hex, *keyalias;
|
||||
|
||||
@ -733,9 +800,11 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
|
||||
filename, linenum, this_result ? "": "not ",
|
||||
oattrib, criteria);
|
||||
debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
|
||||
filename, linenum, this_result ? "": "not ", oattrib,
|
||||
criteria == NULL ? "" : " \"",
|
||||
criteria == NULL ? "" : criteria,
|
||||
criteria == NULL ? "" : "\"");
|
||||
free(criteria);
|
||||
}
|
||||
if (attributes == 0) {
|
||||
|
16
ssh_config.5
16
ssh_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: ssh_config.5,v 1.380 2023/03/27 03:56:11 dtucker Exp $
|
||||
.Dd $Mdocdate: March 27 2023 $
|
||||
.\" $OpenBSD: ssh_config.5,v 1.381 2023/07/17 04:04:36 djm Exp $
|
||||
.Dd $Mdocdate: July 17 2023 $
|
||||
.Dt SSH_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -141,6 +141,7 @@ The available criteria keywords are:
|
||||
.Cm canonical ,
|
||||
.Cm final ,
|
||||
.Cm exec ,
|
||||
.Cm localnetwork ,
|
||||
.Cm host ,
|
||||
.Cm originalhost ,
|
||||
.Cm user ,
|
||||
@ -195,6 +196,17 @@ accept the tokens described in the
|
||||
.Sx TOKENS
|
||||
section.
|
||||
.Pp
|
||||
The
|
||||
.Cm localnetwork
|
||||
keyword matches the addresses of active local network interfaces against the
|
||||
supplied list of networks in CIDR format.
|
||||
This may be convenient for varying the effective configuration on devices that
|
||||
roam between networks.
|
||||
Note that network address is not a trustworthy criteria in many
|
||||
situations (e.g. when the network is automatically configured using DHCP)
|
||||
and so caution should be applied if using it to control security-sensitive
|
||||
configuration.
|
||||
.Pp
|
||||
The other keywords' criteria must be single entries or comma-separated
|
||||
lists and may use the wildcard and negation operators described in the
|
||||
.Sx PATTERNS
|
||||
|
Loading…
Reference in New Issue
Block a user