[openssh-commits] [openssh] 01/02: upstream: allow ssh-keyscan(1) to accept CIDR address ranges, e.g.

git+noreply at mindrot.org git+noreply at mindrot.org
Fri Oct 28 13:49:08 AEDT 2022


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 1192588546c29ceec10775125f396555ea71850f
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Fri Oct 28 02:29:34 2022 +0000

    upstream: allow ssh-keyscan(1) to accept CIDR address ranges, e.g.
    
    ssh-keyscan 192.168.0.0/24
    
    If a CIDR range is passed, then it will be expanded to all possible
    addresses in the range including the all-0s and all-1s addresses.
    
    bz#976 feedback/ok markus@
    
    OpenBSD-Commit-ID: ce6c5211f936ac0053fd4a2ddb415277931e6c4b
---
 addr.c        | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 addr.h        |  4 ++++
 ssh-keyscan.1 | 24 ++++++++++++++++----
 ssh-keyscan.c | 43 ++++++++++++++++++++++++++++++++---
 4 files changed, 136 insertions(+), 8 deletions(-)

diff --git a/addr.c b/addr.c
index abf3e3d9..db9ab7ac 100644
--- a/addr.c
+++ b/addr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: addr.c,v 1.5 2022/04/29 04:55:07 djm Exp $ */
+/* $OpenBSD: addr.c,v 1.6 2022/10/28 02:29:34 djm Exp $ */
 
 /*
  * Copyright (c) 2004-2008 Damien Miller <djm at mindrot.org>
@@ -227,6 +227,28 @@ addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
 	}
 }
 
+int
+addr_or(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
+{
+	int i;
+
+	if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
+		return (-1);
+
+	memcpy(dst, a, sizeof(*dst));
+	switch (a->af) {
+	case AF_INET:
+		dst->v4.s_addr |= b->v4.s_addr;
+		return (0);
+	case AF_INET6:
+		for (i = 0; i < 4; i++)
+			dst->addr32[i] |= b->addr32[i];
+		return (0);
+	default:
+		return (-1);
+	}
+}
+
 int
 addr_cmp(const struct xaddr *a, const struct xaddr *b)
 {
@@ -278,6 +300,29 @@ addr_is_all0s(const struct xaddr *a)
 	}
 }
 
+/* Increment the specified address. Note, does not do overflow checking */
+void
+addr_increment(struct xaddr *a)
+{
+	int i;
+	uint32_t n;
+
+	switch (a->af) {
+	case AF_INET:
+		a->v4.s_addr = htonl(ntohl(a->v4.s_addr) + 1);
+		break;
+	case AF_INET6:
+		for (i = 0; i < 4; i++) {
+			/* Increment with carry */
+			n = ntohl(a->addr32[3 - i]) + 1;
+			a->addr32[3 - i] = htonl(n);
+			if (n != 0)
+				break;
+		}
+		break;
+	}
+}
+
 /*
  * Test whether host portion of address 'a', as determined by 'masklen'
  * is all zeros.
@@ -297,6 +342,32 @@ addr_host_is_all0s(const struct xaddr *a, u_int masklen)
 	return addr_is_all0s(&tmp_result);
 }
 
+#if 0
+int
+addr_host_to_all0s(struct xaddr *a, u_int masklen)
+{
+	struct xaddr tmp_mask;
+
+	if (addr_netmask(a->af, masklen, &tmp_mask) == -1)
+		return (-1);
+	if (addr_and(a, a, &tmp_mask) == -1)
+		return (-1);
+	return (0);
+}
+#endif
+
+int
+addr_host_to_all1s(struct xaddr *a, u_int masklen)
+{
+	struct xaddr tmp_mask;
+
+	if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
+		return (-1);
+	if (addr_or(a, a, &tmp_mask) == -1)
+		return (-1);
+	return (0);
+}
+
 /*
  * Parse string address 'p' into 'n'.
  * Returns 0 on success, -1 on failure.
diff --git a/addr.h b/addr.h
index 5eff0262..180e9fdc 100644
--- a/addr.h
+++ b/addr.h
@@ -52,9 +52,13 @@ int addr_sa_pton(const char *h, const char *s, struct sockaddr *sa,
 int addr_pton_cidr(const char *p, struct xaddr *n, u_int *l);
 int addr_ntop(const struct xaddr *n, char *p, size_t len);
 int addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b);
+int addr_or(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b);
 int addr_cmp(const struct xaddr *a, const struct xaddr *b);
 int addr_is_all0s(const struct xaddr *n);
 int addr_host_is_all0s(const struct xaddr *n, u_int masklen);
+int addr_host_to_all0s(struct xaddr *a, u_int masklen);
+int addr_host_to_all1s(struct xaddr *a, u_int masklen);
 int addr_netmatch(const struct xaddr *host, const struct xaddr *net,
     u_int masklen);
+void addr_increment(struct xaddr *a);
 #endif /* _ADDR_H */
diff --git a/ssh-keyscan.1 b/ssh-keyscan.1
index 4eb0bea0..ca4feea2 100644
--- a/ssh-keyscan.1
+++ b/ssh-keyscan.1
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: ssh-keyscan.1,v 1.46 2022/06/03 04:00:15 dtucker Exp $
+.\"	$OpenBSD: ssh-keyscan.1,v 1.47 2022/10/28 02:29:34 djm Exp $
 .\"
 .\" Copyright 1995, 1996 by David Mazieres <dm at lcs.mit.edu>.
 .\"
@@ -6,7 +6,7 @@
 .\" permitted provided that due credit is given to the author and the
 .\" OpenBSD project by leaving this copyright notice intact.
 .\"
-.Dd $Mdocdate: June 3 2022 $
+.Dd $Mdocdate: October 28 2022 $
 .Dt SSH-KEYSCAN 1
 .Os
 .Sh NAME
@@ -44,6 +44,11 @@ For scanning, one does not need
 login access to the machines that are being scanned, nor does the
 scanning process involve any encryption.
 .Pp
+Hosts to be scanned may be specified by hostname, address or by CIDR
+network range (e.g. 192.168.16/28).
+If a network range is specified, then all addresses in that range will
+be scanned.
+.Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl 4
@@ -73,9 +78,16 @@ If
 is supplied instead of a filename,
 .Nm
 will read from the standard input.
-Input is expected in the format:
+Names read from a file must start with an address, hostname or CIDR network
+range to be scanned.
+Addresses and hostnames may optionally be followed by comma-separated name
+or address aliases that will be copied to the output.
+For example:
 .Bd -literal
-1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4
+192.168.11.0/24
+10.20.1.1
+happy.example.org
+10.0.0.1,sad.example.org
 .Ed
 .It Fl H
 Hash all hostnames and addresses in the output.
@@ -138,6 +150,10 @@ Print the RSA host key for machine
 .Pp
 .Dl $ ssh-keyscan -t rsa hostname
 .Pp
+Search a network range, printing all supported key types:
+.Pp
+.Dl $ ssh-keyscan 192.168.0.64/25
+.Pp
 Find all hosts from the file
 .Pa ssh_hosts
 which have new or different keys from those in the sorted file
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index d7283136..a8ab932b 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.146 2022/08/19 04:02:46 dtucker Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.147 2022/10/28 02:29:34 djm Exp $ */
 /*
  * Copyright 1995, 1996 by David Mazieres <dm at lcs.mit.edu>.
  *
@@ -52,6 +52,7 @@
 #include "ssherr.h"
 #include "ssh_api.h"
 #include "dns.h"
+#include "addr.h"
 
 /* Flag indicating whether IPv4 or IPv6.  This can be set on the command line.
    Default value is AF_UNSPEC means both IPv4 and IPv6. */
@@ -384,7 +385,7 @@ tcpconnect(char *host)
 }
 
 static int
-conalloc(char *iname, char *oname, int keytype)
+conalloc(const char *iname, const char *oname, int keytype)
 {
 	char *namebase, *name, *namelist;
 	int s;
@@ -629,7 +630,7 @@ conloop(void)
 }
 
 static void
-do_host(char *host)
+do_one_host(char *host)
 {
 	char *name = strnnsep(&host, " \t\n");
 	int j;
@@ -645,6 +646,42 @@ do_host(char *host)
 	}
 }
 
+static void
+do_host(char *host)
+{
+	char daddr[128];
+	struct xaddr addr, end_addr;
+	u_int masklen;
+
+	if (host == NULL)
+		return;
+	if (addr_pton_cidr(host, &addr, &masklen) != 0) {
+		/* Assume argument is a hostname */
+		do_one_host(host);
+	} else {
+		/* Argument is a CIDR range */
+		debug("CIDR range %s", host);
+		end_addr = addr;
+		if (addr_host_to_all1s(&end_addr, masklen) != 0)
+			goto badaddr;
+		/*
+		 * Note: we deliberately include the all-zero/ones addresses.
+		 */
+		for (;;) {
+			if (addr_ntop(&addr, daddr, sizeof(daddr)) != 0) {
+ badaddr:
+				error("Invalid address %s", host);
+				return;
+			}
+			debug("CIDR expand: address %s", daddr);
+			do_one_host(daddr);
+			if (addr_cmp(&addr, &end_addr) == 0)
+				break;
+			addr_increment(&addr);
+		};
+	}
+}
+
 void
 sshfatal(const char *file, const char *func, int line, int showfunc,
     LogLevel level, const char *suffix, const char *fmt, ...)

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list