[openssh-commits] [openssh] 04/05: upstream: add a "match localnetwork" predicate.
git+noreply at mindrot.org
git+noreply at mindrot.org
Mon Jul 17 14:54:06 AEST 2023
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit 3071d85a47061c1bdaf11a0ac233b501ecba862c
Author: djm at openbsd.org <djm at openbsd.org>
Date: Mon Jul 17 04:04:36 2023 +0000
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
---
readconf.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
ssh_config.5 | 16 +++++++++++--
2 files changed, 87 insertions(+), 6 deletions(-)
diff --git a/readconf.c b/readconf.c
index bb3bf767..28f6acce 100644
--- a/readconf.c
+++ b/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 at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at 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) {
diff --git a/ssh_config.5 b/ssh_config.5
index 0b7d4d19..3d18fb2a 100644
--- a/ssh_config.5
+++ b/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
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list