Skip to content

Commit d651f5c

Browse files
committed
upstream: let ssh-keygen and ssh-keyscan accept
-Ohashalg=sha1|sha256 when outputting SSHFP fingerprints to allow algorithm selection. bz3493 ok dtucker@ OpenBSD-Commit-ID: e6e07fe21318a873bd877f333e189eb963a11b3d
1 parent 18938d1 commit d651f5c

File tree

6 files changed

+77
-24
lines changed

6 files changed

+77
-24
lines changed

dns.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: dns.c,v 1.42 2022/02/01 23:32:51 djm Exp $ */
1+
/* $OpenBSD: dns.c,v 1.43 2023/02/10 04:56:30 djm Exp $ */
22

33
/*
44
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -301,7 +301,8 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
301301
* Export the fingerprint of a key as a DNS resource record
302302
*/
303303
int
304-
export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic)
304+
export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic,
305+
int alg)
305306
{
306307
u_int8_t rdata_pubkey_algorithm = 0;
307308
u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
@@ -311,6 +312,8 @@ export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic)
311312
int success = 0;
312313

313314
for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
315+
if (alg != -1 && dtype != alg)
316+
continue;
314317
rdata_digest_type = dtype;
315318
if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
316319
&rdata_digest, &rdata_digest_len, key)) {

dns.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: dns.h,v 1.19 2021/07/19 03:13:28 dtucker Exp $ */
1+
/* $OpenBSD: dns.h,v 1.20 2023/02/10 04:56:30 djm Exp $ */
22

33
/*
44
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -54,6 +54,6 @@ enum sshfp_hashes {
5454

5555
int verify_host_key_dns(const char *, struct sockaddr *,
5656
struct sshkey *, int *);
57-
int export_dns_rr(const char *, struct sshkey *, FILE *, int);
57+
int export_dns_rr(const char *, struct sshkey *, FILE *, int, int);
5858

5959
#endif /* DNS_H */

ssh-keygen.1

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.\" $OpenBSD: ssh-keygen.1,v 1.226 2022/09/10 08:50:53 jsg Exp $
1+
.\" $OpenBSD: ssh-keygen.1,v 1.227 2023/02/10 04:56:30 djm Exp $
22
.\"
33
.\" Author: Tatu Ylonen <[email protected]>
44
.\" Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -35,7 +35,7 @@
3535
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3636
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737
.\"
38-
.Dd $Mdocdate: September 10 2022 $
38+
.Dd $Mdocdate: February 10 2023 $
3939
.Dt SSH-KEYGEN 1
4040
.Os
4141
.Sh NAME
@@ -518,6 +518,21 @@ suffixed with a Z character, which causes them to be interpreted in the
518518
UTC time zone.
519519
.El
520520
.Pp
521+
When generating SSHFP DNS records from public keys using the
522+
.Fl r
523+
flag, the following options are accepted:
524+
.Bl -tag -width Ds
525+
.It Cm hashalg Ns = Ns Ar algorithm
526+
Selects a hash algorithm to use when printing SSHFP records using the
527+
.Fl D
528+
flag.
529+
Valid algorithms are
530+
.Dq sha1
531+
and
532+
.Dq sha256.
533+
The default is to print both.
534+
.El
535+
.Pp
521536
The
522537
.Fl O
523538
option may be specified multiple times.

ssh-keygen.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ssh-keygen.c,v 1.461 2022/12/04 23:50:49 cheloha Exp $ */
1+
/* $OpenBSD: ssh-keygen.c,v 1.462 2023/02/10 04:56:30 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1994 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -1479,13 +1479,23 @@ do_change_passphrase(struct passwd *pw)
14791479
*/
14801480
static int
14811481
do_print_resource_record(struct passwd *pw, char *fname, char *hname,
1482-
int print_generic)
1482+
int print_generic, char * const *opts, size_t nopts)
14831483
{
14841484
struct sshkey *public;
14851485
char *comment = NULL;
14861486
struct stat st;
1487-
int r;
1487+
int r, hash = -1;
1488+
size_t i;
14881489

1490+
for (i = 0; i < nopts; i++) {
1491+
if (strncasecmp(opts[i], "hashalg=", 8) == 0) {
1492+
if ((hash = ssh_digest_alg_by_name(opts[i] + 8)) == -1)
1493+
fatal("Unsupported hash algorithm");
1494+
} else {
1495+
error("Invalid option \"%s\"", opts[i]);
1496+
return SSH_ERR_INVALID_ARGUMENT;
1497+
}
1498+
}
14891499
if (fname == NULL)
14901500
fatal_f("no filename");
14911501
if (stat(fname, &st) == -1) {
@@ -1495,7 +1505,7 @@ do_print_resource_record(struct passwd *pw, char *fname, char *hname,
14951505
}
14961506
if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
14971507
fatal_r(r, "Failed to read v2 public key from \"%s\"", fname);
1498-
export_dns_rr(hname, public, stdout, print_generic);
1508+
export_dns_rr(hname, public, stdout, print_generic, hash);
14991509
sshkey_free(public);
15001510
free(comment);
15011511
return 1;
@@ -3725,27 +3735,27 @@ main(int argc, char **argv)
37253735

37263736
if (have_identity) {
37273737
n = do_print_resource_record(pw, identity_file,
3728-
rr_hostname, print_generic);
3738+
rr_hostname, print_generic, opts, nopts);
37293739
if (n == 0)
37303740
fatal("%s: %s", identity_file, strerror(errno));
37313741
exit(0);
37323742
} else {
37333743

37343744
n += do_print_resource_record(pw,
37353745
_PATH_HOST_RSA_KEY_FILE, rr_hostname,
3736-
print_generic);
3746+
print_generic, opts, nopts);
37373747
n += do_print_resource_record(pw,
37383748
_PATH_HOST_DSA_KEY_FILE, rr_hostname,
3739-
print_generic);
3749+
print_generic, opts, nopts);
37403750
n += do_print_resource_record(pw,
37413751
_PATH_HOST_ECDSA_KEY_FILE, rr_hostname,
3742-
print_generic);
3752+
print_generic, opts, nopts);
37433753
n += do_print_resource_record(pw,
37443754
_PATH_HOST_ED25519_KEY_FILE, rr_hostname,
3745-
print_generic);
3755+
print_generic, opts, nopts);
37463756
n += do_print_resource_record(pw,
37473757
_PATH_HOST_XMSS_KEY_FILE, rr_hostname,
3748-
print_generic);
3758+
print_generic, opts, nopts);
37493759
if (n == 0)
37503760
fatal("no keys found.");
37513761
exit(0);

ssh-keyscan.1

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
.\" $OpenBSD: ssh-keyscan.1,v 1.47 2022/10/28 02:29:34 djm Exp $
1+
.\" $OpenBSD: ssh-keyscan.1,v 1.48 2023/02/10 04:56:30 djm Exp $
22
.\"
33
.\" Copyright 1995, 1996 by David Mazieres <[email protected]>.
44
.\"
55
.\" Modification and redistribution in source and binary forms is
66
.\" permitted provided that due credit is given to the author and the
77
.\" OpenBSD project by leaving this copyright notice intact.
88
.\"
9-
.Dd $Mdocdate: October 28 2022 $
9+
.Dd $Mdocdate: February 10 2023 $
1010
.Dt SSH-KEYSCAN 1
1111
.Os
1212
.Sh NAME
@@ -16,6 +16,7 @@
1616
.Nm ssh-keyscan
1717
.Op Fl 46cDHv
1818
.Op Fl f Ar file
19+
.Op Fl O Ar option
1920
.Op Fl p Ar port
2021
.Op Fl T Ar timeout
2122
.Op Fl t Ar type
@@ -97,6 +98,20 @@ and
9798
.Xr sshd 8 ,
9899
but they do not reveal identifying information should the file's contents
99100
be disclosed.
101+
.It Fl O Ar option
102+
Specify a key/value option.
103+
At present, only a single option is supported:
104+
.Bl -tag -width Ds
105+
.It Cm hashalg Ns = Ns Ar algorithm
106+
Selects a hash algorithm to use when printing SSHFP records using the
107+
.Fl D
108+
flag.
109+
Valid algorithms are
110+
.Dq sha1
111+
and
112+
.Dq sha256.
113+
The default is to print both.
114+
.El
100115
.It Fl p Ar port
101116
Connect to
102117
.Ar port

ssh-keyscan.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: ssh-keyscan.c,v 1.149 2022/12/26 19:16:03 jmc Exp $ */
1+
/* $OpenBSD: ssh-keyscan.c,v 1.150 2023/02/10 04:56:30 djm Exp $ */
22
/*
33
* Copyright 1995, 1996 by David Mazieres <[email protected]>.
44
*
@@ -40,6 +40,7 @@
4040
#include "sshbuf.h"
4141
#include "sshkey.h"
4242
#include "cipher.h"
43+
#include "digest.h"
4344
#include "kex.h"
4445
#include "compat.h"
4546
#include "myproposal.h"
@@ -80,6 +81,8 @@ int print_sshfp = 0; /* Print SSHFP records instead of known_hosts */
8081

8182
int found_one = 0; /* Successfully found a key */
8283

84+
int hashalg = -1; /* Hash for SSHFP records or -1 for all */
85+
8386
#define MAXMAXFD 256
8487

8588
/* The number of seconds after which to give up on a TCP connection */
@@ -314,7 +317,7 @@ keyprint_one(const char *host, struct sshkey *key)
314317
found_one = 1;
315318

316319
if (print_sshfp) {
317-
export_dns_rr(host, key, stdout, 0);
320+
export_dns_rr(host, key, stdout, 0, hashalg);
318321
return;
319322
}
320323

@@ -698,9 +701,8 @@ static void
698701
usage(void)
699702
{
700703
fprintf(stderr,
701-
"usage: %s [-46cDHv] [-f file] [-p port] [-T timeout] [-t type]\n"
702-
"\t\t [host | addrlist namelist]\n",
703-
__progname);
704+
"usage: ssh-keyscan [-46cDHv] [-f file] [-p port] [-T timeout] [-t type]\n"
705+
" [-O option] [host | addrlist namelist]\n");
704706
exit(1);
705707
}
706708

@@ -726,7 +728,7 @@ main(int argc, char **argv)
726728
if (argc <= 1)
727729
usage();
728730

729-
while ((opt = getopt(argc, argv, "cDHv46p:T:t:f:")) != -1) {
731+
while ((opt = getopt(argc, argv, "cDHv46O:p:T:t:f:")) != -1) {
730732
switch (opt) {
731733
case 'H':
732734
hash_hosts = 1;
@@ -766,6 +768,14 @@ main(int argc, char **argv)
766768
optarg = NULL;
767769
argv[fopt_count++] = optarg;
768770
break;
771+
case 'O':
772+
/* Maybe other misc options in the future too */
773+
if (strncmp(optarg, "hashalg=", 8) != 0)
774+
fatal("Unsupported -O option");
775+
if ((hashalg = ssh_digest_alg_by_name(
776+
optarg + 8)) == -1)
777+
fatal("Unsupported hash algorithm");
778+
break;
769779
case 't':
770780
get_keytypes = 0;
771781
tname = strtok(optarg, ",");

0 commit comments

Comments
 (0)