Bug Summary

File:src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c
Warning:line 753, column 8
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ssh-keygen.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ssh/ssh-keygen/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/ssh/ssh-keygen/.. -D WITH_OPENSSL -D WITH_ZLIB -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh-keygen/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c
1/* $OpenBSD: ssh-keygen.c,v 1.447 2022/01/05 21:54:37 djm Exp $ */
2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * Identity and host key generation and maintenance.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 */
14
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <sys/stat.h>
18
19#ifdef WITH_OPENSSL1
20#include <openssl/evp.h>
21#include <openssl/pem.h>
22#endif
23
24#include <stdint.h>
25#include <errno(*__errno()).h>
26#include <fcntl.h>
27#include <netdb.h>
28#include <pwd.h>
29#include <stdarg.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34#include <limits.h>
35#include <locale.h>
36
37#include "xmalloc.h"
38#include "sshkey.h"
39#include "authfile.h"
40#include "sshbuf.h"
41#include "pathnames.h"
42#include "log.h"
43#include "misc.h"
44#include "match.h"
45#include "hostfile.h"
46#include "dns.h"
47#include "ssh.h"
48#include "ssh2.h"
49#include "ssherr.h"
50#include "atomicio.h"
51#include "krl.h"
52#include "digest.h"
53#include "utf8.h"
54#include "authfd.h"
55#include "sshsig.h"
56#include "ssh-sk.h"
57#include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */
58#include "cipher.h"
59
60#ifdef ENABLE_PKCS111
61#include "ssh-pkcs11.h"
62#endif
63
64#ifdef WITH_OPENSSL1
65# define DEFAULT_KEY_TYPE_NAME"rsa" "rsa"
66#else
67# define DEFAULT_KEY_TYPE_NAME"rsa" "ed25519"
68#endif
69
70/*
71 * Default number of bits in the RSA, DSA and ECDSA keys. These value can be
72 * overridden on the command line.
73 *
74 * These values, with the exception of DSA, provide security equivalent to at
75 * least 128 bits of security according to NIST Special Publication 800-57:
76 * Recommendation for Key Management Part 1 rev 4 section 5.6.1.
77 * For DSA it (and FIPS-186-4 section 4.2) specifies that the only size for
78 * which a 160bit hash is acceptable is 1kbit, and since ssh-dss specifies only
79 * SHA1 we limit the DSA key size 1k bits.
80 */
81#define DEFAULT_BITS3072 3072
82#define DEFAULT_BITS_DSA1024 1024
83#define DEFAULT_BITS_ECDSA256 256
84
85static int quiet = 0;
86
87/* Flag indicating that we just want to see the key fingerprint */
88static int print_fingerprint = 0;
89static int print_bubblebabble = 0;
90
91/* Hash algorithm to use for fingerprints. */
92static int fingerprint_hash = SSH_FP_HASH_DEFAULT2;
93
94/* The identity file name, given on the command line or entered by the user. */
95static char identity_file[PATH_MAX1024];
96static int have_identity = 0;
97
98/* This is set to the passphrase if given on the command line. */
99static char *identity_passphrase = NULL((void*)0);
100
101/* This is set to the new passphrase if given on the command line. */
102static char *identity_new_passphrase = NULL((void*)0);
103
104/* Key type when certifying */
105static u_int cert_key_type = SSH2_CERT_TYPE_USER1;
106
107/* "key ID" of signed key */
108static char *cert_key_id = NULL((void*)0);
109
110/* Comma-separated list of principal names for certifying keys */
111static char *cert_principals = NULL((void*)0);
112
113/* Validity period for certificates */
114static u_int64_t cert_valid_from = 0;
115static u_int64_t cert_valid_to = ~0ULL;
116
117/* Certificate options */
118#define CERTOPT_X_FWD(1) (1)
119#define CERTOPT_AGENT_FWD(1<<1) (1<<1)
120#define CERTOPT_PORT_FWD(1<<2) (1<<2)
121#define CERTOPT_PTY(1<<3) (1<<3)
122#define CERTOPT_USER_RC(1<<4) (1<<4)
123#define CERTOPT_NO_REQUIRE_USER_PRESENCE(1<<5) (1<<5)
124#define CERTOPT_DEFAULT((1)|(1<<1)| (1<<2)|(1<<3)|(1<<4)) (CERTOPT_X_FWD(1)|CERTOPT_AGENT_FWD(1<<1)| \
125 CERTOPT_PORT_FWD(1<<2)|CERTOPT_PTY(1<<3)|CERTOPT_USER_RC(1<<4))
126static u_int32_t certflags_flags = CERTOPT_DEFAULT((1)|(1<<1)| (1<<2)|(1<<3)|(1<<4));
127static char *certflags_command = NULL((void*)0);
128static char *certflags_src_addr = NULL((void*)0);
129
130/* Arbitrary extensions specified by user */
131struct cert_ext {
132 char *key;
133 char *val;
134 int crit;
135};
136static struct cert_ext *cert_ext;
137static size_t ncert_ext;
138
139/* Conversion to/from various formats */
140enum {
141 FMT_RFC4716,
142 FMT_PKCS8,
143 FMT_PEM
144} convert_format = FMT_RFC4716;
145
146static char *key_type_name = NULL((void*)0);
147
148/* Load key from this PKCS#11 provider */
149static char *pkcs11provider = NULL((void*)0);
150
151/* FIDO/U2F provider to use */
152static char *sk_provider = NULL((void*)0);
153
154/* Format for writing private keys */
155static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
156
157/* Cipher for new-format private keys */
158static char *openssh_format_cipher = NULL((void*)0);
159
160/* Number of KDF rounds to derive new format keys. */
161static int rounds = 0;
162
163/* argv0 */
164extern char *__progname;
165
166static char hostname[NI_MAXHOST256];
167
168#ifdef WITH_OPENSSL1
169/* moduli.c */
170int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
171int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
172 unsigned long);
173#endif
174
175static void
176type_bits_valid(int type, const char *name, u_int32_t *bitsp)
177{
178 if (type == KEY_UNSPEC)
179 fatal("unknown key type %s", key_type_name)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 179, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "unknown key type %s"
, key_type_name)
;
180 if (*bitsp == 0) {
181#ifdef WITH_OPENSSL1
182 int nid;
183
184 switch(type) {
185 case KEY_DSA:
186 *bitsp = DEFAULT_BITS_DSA1024;
187 break;
188 case KEY_ECDSA:
189 if (name != NULL((void*)0) &&
190 (nid = sshkey_ecdsa_nid_from_name(name)) > 0)
191 *bitsp = sshkey_curve_nid_to_bits(nid);
192 if (*bitsp == 0)
193 *bitsp = DEFAULT_BITS_ECDSA256;
194 break;
195 case KEY_RSA:
196 *bitsp = DEFAULT_BITS3072;
197 break;
198 }
199#endif
200 }
201#ifdef WITH_OPENSSL1
202 switch (type) {
203 case KEY_DSA:
204 if (*bitsp != 1024)
205 fatal("Invalid DSA key length: must be 1024 bits")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 205, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid DSA key length: must be 1024 bits"
)
;
206 break;
207 case KEY_RSA:
208 if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE1024)
209 fatal("Invalid RSA key length: minimum is %d bits",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 210, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid RSA key length: minimum is %d bits"
, 1024)
210 SSH_RSA_MINIMUM_MODULUS_SIZE)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 210, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid RSA key length: minimum is %d bits"
, 1024)
;
211 else if (*bitsp > OPENSSL_RSA_MAX_MODULUS_BITS16384)
212 fatal("Invalid RSA key length: maximum is %d bits",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 213, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid RSA key length: maximum is %d bits"
, 16384)
213 OPENSSL_RSA_MAX_MODULUS_BITS)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 213, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid RSA key length: maximum is %d bits"
, 16384)
;
214 break;
215 case KEY_ECDSA:
216 if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
217 fatal("Invalid ECDSA key length: valid lengths are "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 218, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid ECDSA key length: valid lengths are "
"256, 384 or 521 bits")
218 "256, 384 or 521 bits")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 218, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid ECDSA key length: valid lengths are "
"256, 384 or 521 bits")
;
219 }
220#endif
221}
222
223/*
224 * Checks whether a file exists and, if so, asks the user whether they wish
225 * to overwrite it.
226 * Returns nonzero if the file does not already exist or if the user agrees to
227 * overwrite, or zero otherwise.
228 */
229static int
230confirm_overwrite(const char *filename)
231{
232 char yesno[3];
233 struct stat st;
234
235 if (stat(filename, &st) != 0)
236 return 1;
237 printf("%s already exists.\n", filename);
238 printf("Overwrite (y/n)? ");
239 fflush(stdout(&__sF[1]));
240 if (fgets(yesno, sizeof(yesno), stdin(&__sF[0])) == NULL((void*)0))
241 return 0;
242 if (yesno[0] != 'y' && yesno[0] != 'Y')
243 return 0;
244 return 1;
245}
246
247static void
248ask_filename(struct passwd *pw, const char *prompt)
249{
250 char buf[1024];
251 char *name = NULL((void*)0);
252
253 if (key_type_name == NULL((void*)0))
254 name = _PATH_SSH_CLIENT_ID_RSA".ssh" "/id_rsa";
255 else {
256 switch (sshkey_type_from_name(key_type_name)) {
257 case KEY_DSA_CERT:
258 case KEY_DSA:
259 name = _PATH_SSH_CLIENT_ID_DSA".ssh" "/id_dsa";
260 break;
261 case KEY_ECDSA_CERT:
262 case KEY_ECDSA:
263 name = _PATH_SSH_CLIENT_ID_ECDSA".ssh" "/id_ecdsa";
264 break;
265 case KEY_ECDSA_SK_CERT:
266 case KEY_ECDSA_SK:
267 name = _PATH_SSH_CLIENT_ID_ECDSA_SK".ssh" "/id_ecdsa_sk";
268 break;
269 case KEY_RSA_CERT:
270 case KEY_RSA:
271 name = _PATH_SSH_CLIENT_ID_RSA".ssh" "/id_rsa";
272 break;
273 case KEY_ED25519:
274 case KEY_ED25519_CERT:
275 name = _PATH_SSH_CLIENT_ID_ED25519".ssh" "/id_ed25519";
276 break;
277 case KEY_ED25519_SK:
278 case KEY_ED25519_SK_CERT:
279 name = _PATH_SSH_CLIENT_ID_ED25519_SK".ssh" "/id_ed25519_sk";
280 break;
281 case KEY_XMSS:
282 case KEY_XMSS_CERT:
283 name = _PATH_SSH_CLIENT_ID_XMSS".ssh" "/id_xmss";
284 break;
285 default:
286 fatal("bad key type")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 286, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "bad key type")
;
287 }
288 }
289 snprintf(identity_file, sizeof(identity_file),
290 "%s/%s", pw->pw_dir, name);
291 printf("%s (%s): ", prompt, identity_file);
292 fflush(stdout(&__sF[1]));
293 if (fgets(buf, sizeof(buf), stdin(&__sF[0])) == NULL((void*)0))
294 exit(1);
295 buf[strcspn(buf, "\n")] = '\0';
296 if (strcmp(buf, "") != 0)
297 strlcpy(identity_file, buf, sizeof(identity_file));
298 have_identity = 1;
299}
300
301static struct sshkey *
302load_identity(const char *filename, char **commentp)
303{
304 char *pass;
305 struct sshkey *prv;
306 int r;
307
308 if (commentp != NULL((void*)0))
309 *commentp = NULL((void*)0);
310 if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0)
311 return prv;
312 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE-43)
313 fatal_r(r, "Load key \"%s\"", filename)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 313, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Load key \"%s\"", filename
)
;
314 if (identity_passphrase)
315 pass = xstrdup(identity_passphrase);
316 else
317 pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN0x0002);
318 r = sshkey_load_private(filename, pass, &prv, commentp);
319 freezero(pass, strlen(pass));
320 if (r != 0)
321 fatal_r(r, "Load key \"%s\"", filename)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 321, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Load key \"%s\"", filename
)
;
322 return prv;
323}
324
325#define SSH_COM_PUBLIC_BEGIN"---- BEGIN SSH2 PUBLIC KEY ----" "---- BEGIN SSH2 PUBLIC KEY ----"
326#define SSH_COM_PUBLIC_END"---- END SSH2 PUBLIC KEY ----" "---- END SSH2 PUBLIC KEY ----"
327#define SSH_COM_PRIVATE_BEGIN"---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
328#define SSH_COM_PRIVATE_KEY_MAGIC0x3f6ff9eb 0x3f6ff9eb
329
330#ifdef WITH_OPENSSL1
331static void
332do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
333{
334 struct sshbuf *b;
335 char comment[61], *b64;
336 int r;
337
338 if ((b = sshbuf_new()) == NULL((void*)0))
339 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 339, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
340 if ((r = sshkey_putb(k, b)) != 0)
341 fatal_fr(r, "put key")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 341, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "put key")
;
342 if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL((void*)0))
343 fatal_f("sshbuf_dtob64_string failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 343, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_dtob64_string failed"
)
;
344
345 /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
346 snprintf(comment, sizeof(comment),
347 "%u-bit %s, converted by %s@%s from OpenSSH",
348 sshkey_size(k), sshkey_type(k),
349 pw->pw_name, hostname);
350
351 sshkey_free(k);
352 sshbuf_free(b);
353
354 fprintf(stdout(&__sF[1]), "%s\n", SSH_COM_PUBLIC_BEGIN"---- BEGIN SSH2 PUBLIC KEY ----");
355 fprintf(stdout(&__sF[1]), "Comment: \"%s\"\n%s", comment, b64);
356 fprintf(stdout(&__sF[1]), "%s\n", SSH_COM_PUBLIC_END"---- END SSH2 PUBLIC KEY ----");
357 free(b64);
358 exit(0);
359}
360
361static void
362do_convert_to_pkcs8(struct sshkey *k)
363{
364 switch (sshkey_type_plain(k->type)) {
365 case KEY_RSA:
366 if (!PEM_write_RSA_PUBKEY(stdout(&__sF[1]), k->rsa))
367 fatal("PEM_write_RSA_PUBKEY failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 367, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "PEM_write_RSA_PUBKEY failed"
)
;
368 break;
369 case KEY_DSA:
370 if (!PEM_write_DSA_PUBKEY(stdout(&__sF[1]), k->dsa))
371 fatal("PEM_write_DSA_PUBKEY failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 371, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "PEM_write_DSA_PUBKEY failed"
)
;
372 break;
373 case KEY_ECDSA:
374 if (!PEM_write_EC_PUBKEY(stdout(&__sF[1]), k->ecdsa))
375 fatal("PEM_write_EC_PUBKEY failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 375, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "PEM_write_EC_PUBKEY failed"
)
;
376 break;
377 default:
378 fatal_f("unsupported key type %s", sshkey_type(k))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 378, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unsupported key type %s"
, sshkey_type(k))
;
379 }
380 exit(0);
381}
382
383static void
384do_convert_to_pem(struct sshkey *k)
385{
386 switch (sshkey_type_plain(k->type)) {
387 case KEY_RSA:
388 if (!PEM_write_RSAPublicKey(stdout(&__sF[1]), k->rsa))
389 fatal("PEM_write_RSAPublicKey failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 389, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "PEM_write_RSAPublicKey failed"
)
;
390 break;
391 case KEY_DSA:
392 if (!PEM_write_DSA_PUBKEY(stdout(&__sF[1]), k->dsa))
393 fatal("PEM_write_DSA_PUBKEY failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 393, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "PEM_write_DSA_PUBKEY failed"
)
;
394 break;
395 case KEY_ECDSA:
396 if (!PEM_write_EC_PUBKEY(stdout(&__sF[1]), k->ecdsa))
397 fatal("PEM_write_EC_PUBKEY failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 397, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "PEM_write_EC_PUBKEY failed"
)
;
398 break;
399 default:
400 fatal_f("unsupported key type %s", sshkey_type(k))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 400, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unsupported key type %s"
, sshkey_type(k))
;
401 }
402 exit(0);
403}
404
405static void
406do_convert_to(struct passwd *pw)
407{
408 struct sshkey *k;
409 struct stat st;
410 int r;
411
412 if (!have_identity)
413 ask_filename(pw, "Enter file in which the key is");
414 if (stat(identity_file, &st) == -1)
415 fatal("%s: %s: %s", __progname, identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 415, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s: %s", __progname
, identity_file, strerror((*__errno())))
;
416 if ((r = sshkey_load_public(identity_file, &k, NULL((void*)0))) != 0)
417 k = load_identity(identity_file, NULL((void*)0));
418 switch (convert_format) {
419 case FMT_RFC4716:
420 do_convert_to_ssh2(pw, k);
421 break;
422 case FMT_PKCS8:
423 do_convert_to_pkcs8(k);
424 break;
425 case FMT_PEM:
426 do_convert_to_pem(k);
427 break;
428 default:
429 fatal_f("unknown key format %d", convert_format)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 429, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unknown key format %d"
, convert_format)
;
430 }
431 exit(0);
432}
433
434/*
435 * This is almost exactly the bignum1 encoding, but with 32 bit for length
436 * instead of 16.
437 */
438static void
439buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
440{
441 u_int bytes, bignum_bits;
442 int r;
443
444 if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0)
445 fatal_fr(r, "parse")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 445, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse")
;
446 bytes = (bignum_bits + 7) / 8;
447 if (sshbuf_len(b) < bytes)
448 fatal_f("input buffer too small: need %d have %zu",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 449, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "input buffer too small: need %d have %zu"
, bytes, sshbuf_len(b))
449 bytes, sshbuf_len(b))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 449, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "input buffer too small: need %d have %zu"
, bytes, sshbuf_len(b))
;
450 if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL((void*)0))
451 fatal_f("BN_bin2bn failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 451, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "BN_bin2bn failed")
;
452 if ((r = sshbuf_consume(b, bytes)) != 0)
453 fatal_fr(r, "consume")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 453, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "consume")
;
454}
455
456static struct sshkey *
457do_convert_private_ssh2(struct sshbuf *b)
458{
459 struct sshkey *key = NULL((void*)0);
460 char *type, *cipher;
461 u_char e1, e2, e3, *sig = NULL((void*)0), data[] = "abcde12345";
462 int r, rlen, ktype;
463 u_int magic, i1, i2, i3, i4;
464 size_t slen;
465 u_long e;
466 BIGNUM *dsa_p = NULL((void*)0), *dsa_q = NULL((void*)0), *dsa_g = NULL((void*)0);
467 BIGNUM *dsa_pub_key = NULL((void*)0), *dsa_priv_key = NULL((void*)0);
468 BIGNUM *rsa_n = NULL((void*)0), *rsa_e = NULL((void*)0), *rsa_d = NULL((void*)0);
469 BIGNUM *rsa_p = NULL((void*)0), *rsa_q = NULL((void*)0), *rsa_iqmp = NULL((void*)0);
470
471 if ((r = sshbuf_get_u32(b, &magic)) != 0)
472 fatal_fr(r, "parse magic")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 472, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse magic")
;
473
474 if (magic != SSH_COM_PRIVATE_KEY_MAGIC0x3f6ff9eb) {
475 error("bad magic 0x%x != 0x%x", magic,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 476, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "bad magic 0x%x != 0x%x"
, magic, 0x3f6ff9eb)
476 SSH_COM_PRIVATE_KEY_MAGIC)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 476, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "bad magic 0x%x != 0x%x"
, magic, 0x3f6ff9eb)
;
477 return NULL((void*)0);
478 }
479 if ((r = sshbuf_get_u32(b, &i1)) != 0 ||
480 (r = sshbuf_get_cstring(b, &type, NULL((void*)0))) != 0 ||
481 (r = sshbuf_get_cstring(b, &cipher, NULL((void*)0))) != 0 ||
482 (r = sshbuf_get_u32(b, &i2)) != 0 ||
483 (r = sshbuf_get_u32(b, &i3)) != 0 ||
484 (r = sshbuf_get_u32(b, &i4)) != 0)
485 fatal_fr(r, "parse")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 485, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse")
;
486 debug("ignore (%d %d %d %d)", i1, i2, i3, i4)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 486, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "ignore (%d %d %d %d)"
, i1, i2, i3, i4)
;
487 if (strcmp(cipher, "none") != 0) {
488 error("unsupported cipher %s", cipher)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 488, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "unsupported cipher %s"
, cipher)
;
489 free(cipher);
490 free(type);
491 return NULL((void*)0);
492 }
493 free(cipher);
494
495 if (strstr(type, "dsa")) {
496 ktype = KEY_DSA;
497 } else if (strstr(type, "rsa")) {
498 ktype = KEY_RSA;
499 } else {
500 free(type);
501 return NULL((void*)0);
502 }
503 if ((key = sshkey_new(ktype)) == NULL((void*)0))
504 fatal("sshkey_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 504, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new failed"
)
;
505 free(type);
506
507 switch (key->type) {
508 case KEY_DSA:
509 if ((dsa_p = BN_new()) == NULL((void*)0) ||
510 (dsa_q = BN_new()) == NULL((void*)0) ||
511 (dsa_g = BN_new()) == NULL((void*)0) ||
512 (dsa_pub_key = BN_new()) == NULL((void*)0) ||
513 (dsa_priv_key = BN_new()) == NULL((void*)0))
514 fatal_f("BN_new")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 514, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "BN_new")
;
515 buffer_get_bignum_bits(b, dsa_p);
516 buffer_get_bignum_bits(b, dsa_g);
517 buffer_get_bignum_bits(b, dsa_q);
518 buffer_get_bignum_bits(b, dsa_pub_key);
519 buffer_get_bignum_bits(b, dsa_priv_key);
520 if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g))
521 fatal_f("DSA_set0_pqg failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 521, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "DSA_set0_pqg failed"
)
;
522 dsa_p = dsa_q = dsa_g = NULL((void*)0); /* transferred */
523 if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key))
524 fatal_f("DSA_set0_key failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 524, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "DSA_set0_key failed"
)
;
525 dsa_pub_key = dsa_priv_key = NULL((void*)0); /* transferred */
526 break;
527 case KEY_RSA:
528 if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
529 (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
530 (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
531 fatal_fr(r, "parse RSA")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 531, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse RSA")
;
532 e = e1;
533 debug("e %lx", e)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 533, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "e %lx", e)
;
534 if (e < 30) {
535 e <<= 8;
536 e += e2;
537 debug("e %lx", e)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 537, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "e %lx", e)
;
538 e <<= 8;
539 e += e3;
540 debug("e %lx", e)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 540, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "e %lx", e)
;
541 }
542 if ((rsa_e = BN_new()) == NULL((void*)0))
543 fatal_f("BN_new")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 543, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "BN_new")
;
544 if (!BN_set_word(rsa_e, e)) {
545 BN_clear_free(rsa_e);
546 sshkey_free(key);
547 return NULL((void*)0);
548 }
549 if ((rsa_n = BN_new()) == NULL((void*)0) ||
550 (rsa_d = BN_new()) == NULL((void*)0) ||
551 (rsa_p = BN_new()) == NULL((void*)0) ||
552 (rsa_q = BN_new()) == NULL((void*)0) ||
553 (rsa_iqmp = BN_new()) == NULL((void*)0))
554 fatal_f("BN_new")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 554, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "BN_new")
;
555 buffer_get_bignum_bits(b, rsa_d);
556 buffer_get_bignum_bits(b, rsa_n);
557 buffer_get_bignum_bits(b, rsa_iqmp);
558 buffer_get_bignum_bits(b, rsa_q);
559 buffer_get_bignum_bits(b, rsa_p);
560 if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d))
561 fatal_f("RSA_set0_key failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 561, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "RSA_set0_key failed"
)
;
562 rsa_n = rsa_e = rsa_d = NULL((void*)0); /* transferred */
563 if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q))
564 fatal_f("RSA_set0_factors failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 564, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "RSA_set0_factors failed"
)
;
565 rsa_p = rsa_q = NULL((void*)0); /* transferred */
566 if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
567 fatal_fr(r, "generate RSA parameters")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 567, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "generate RSA parameters"
)
;
568 BN_clear_free(rsa_iqmp);
569 break;
570 }
571 rlen = sshbuf_len(b);
572 if (rlen != 0)
573 error_f("remaining bytes in key blob %d", rlen)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 573, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "remaining bytes in key blob %d"
, rlen)
;
574
575 /* try the key */
576 if (sshkey_sign(key, &sig, &slen, data, sizeof(data),
577 NULL((void*)0), NULL((void*)0), NULL((void*)0), 0) != 0 ||
578 sshkey_verify(key, sig, slen, data, sizeof(data),
579 NULL((void*)0), 0, NULL((void*)0)) != 0) {
580 sshkey_free(key);
581 free(sig);
582 return NULL((void*)0);
583 }
584 free(sig);
585 return key;
586}
587
588static int
589get_line(FILE *fp, char *line, size_t len)
590{
591 int c;
592 size_t pos = 0;
593
594 line[0] = '\0';
595 while ((c = fgetc(fp)) != EOF(-1)) {
596 if (pos >= len - 1)
597 fatal("input line too long.")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 597, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "input line too long."
)
;
598 switch (c) {
599 case '\r':
600 c = fgetc(fp);
601 if (c != EOF(-1) && c != '\n' && ungetc(c, fp) == EOF(-1))
602 fatal("unget: %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 602, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "unget: %s", strerror
((*__errno())))
;
603 return pos;
604 case '\n':
605 return pos;
606 }
607 line[pos++] = c;
608 line[pos] = '\0';
609 }
610 /* We reached EOF */
611 return -1;
612}
613
614static void
615do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
616{
617 int r, blen, escaped = 0;
618 u_int len;
619 char line[1024];
620 struct sshbuf *buf;
621 char encoded[8096];
622 FILE *fp;
623
624 if ((buf = sshbuf_new()) == NULL((void*)0))
625 fatal("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 625, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
626 if ((fp = fopen(identity_file, "r")) == NULL((void*)0))
627 fatal("%s: %s: %s", __progname, identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 627, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s: %s", __progname
, identity_file, strerror((*__errno())))
;
628 encoded[0] = '\0';
629 while ((blen = get_line(fp, line, sizeof(line))) != -1) {
630 if (blen > 0 && line[blen - 1] == '\\')
631 escaped++;
632 if (strncmp(line, "----", 4) == 0 ||
633 strstr(line, ": ") != NULL((void*)0)) {
634 if (strstr(line, SSH_COM_PRIVATE_BEGIN"---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----") != NULL((void*)0))
635 *private = 1;
636 if (strstr(line, " END ") != NULL((void*)0)) {
637 break;
638 }
639 /* fprintf(stderr, "ignore: %s", line); */
640 continue;
641 }
642 if (escaped) {
643 escaped--;
644 /* fprintf(stderr, "escaped: %s", line); */
645 continue;
646 }
647 strlcat(encoded, line, sizeof(encoded));
648 }
649 len = strlen(encoded);
650 if (((len % 4) == 3) &&
651 (encoded[len-1] == '=') &&
652 (encoded[len-2] == '=') &&
653 (encoded[len-3] == '='))
654 encoded[len-3] = '\0';
655 if ((r = sshbuf_b64tod(buf, encoded)) != 0)
656 fatal_fr(r, "base64 decode")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 656, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "base64 decode")
;
657 if (*private) {
658 if ((*k = do_convert_private_ssh2(buf)) == NULL((void*)0))
659 fatal_f("private key conversion failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 659, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "private key conversion failed"
)
;
660 } else if ((r = sshkey_fromb(buf, k)) != 0)
661 fatal_fr(r, "parse key")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 661, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse key")
;
662 sshbuf_free(buf);
663 fclose(fp);
664}
665
666static void
667do_convert_from_pkcs8(struct sshkey **k, int *private)
668{
669 EVP_PKEY *pubkey;
670 FILE *fp;
671
672 if ((fp = fopen(identity_file, "r")) == NULL((void*)0))
673 fatal("%s: %s: %s", __progname, identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 673, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s: %s", __progname
, identity_file, strerror((*__errno())))
;
674 if ((pubkey = PEM_read_PUBKEY(fp, NULL((void*)0), NULL((void*)0), NULL((void*)0))) == NULL((void*)0)) {
675 fatal_f("%s is not a recognised public key format",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 676, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "%s is not a recognised public key format"
, identity_file)
676 identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 676, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "%s is not a recognised public key format"
, identity_file)
;
677 }
678 fclose(fp);
679 switch (EVP_PKEY_base_id(pubkey)) {
680 case EVP_PKEY_RSA6:
681 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL((void*)0))
682 fatal("sshkey_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 682, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new failed"
)
;
683 (*k)->type = KEY_RSA;
684 (*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
685 break;
686 case EVP_PKEY_DSA116:
687 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL((void*)0))
688 fatal("sshkey_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 688, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new failed"
)
;
689 (*k)->type = KEY_DSA;
690 (*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
691 break;
692 case EVP_PKEY_EC408:
693 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL((void*)0))
694 fatal("sshkey_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 694, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new failed"
)
;
695 (*k)->type = KEY_ECDSA;
696 (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey);
697 (*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa);
698 break;
699 default:
700 fatal_f("unsupported pubkey type %d",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 701, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unsupported pubkey type %d"
, EVP_PKEY_base_id(pubkey))
701 EVP_PKEY_base_id(pubkey))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 701, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unsupported pubkey type %d"
, EVP_PKEY_base_id(pubkey))
;
702 }
703 EVP_PKEY_free(pubkey);
704 return;
705}
706
707static void
708do_convert_from_pem(struct sshkey **k, int *private)
709{
710 FILE *fp;
711 RSA *rsa;
712
713 if ((fp = fopen(identity_file, "r")) == NULL((void*)0))
714 fatal("%s: %s: %s", __progname, identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 714, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s: %s", __progname
, identity_file, strerror((*__errno())))
;
715 if ((rsa = PEM_read_RSAPublicKey(fp, NULL((void*)0), NULL((void*)0), NULL((void*)0))) != NULL((void*)0)) {
716 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL((void*)0))
717 fatal("sshkey_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 717, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new failed"
)
;
718 (*k)->type = KEY_RSA;
719 (*k)->rsa = rsa;
720 fclose(fp);
721 return;
722 }
723 fatal_f("unrecognised raw private key format")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 723, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unrecognised raw private key format"
)
;
724}
725
726static void
727do_convert_from(struct passwd *pw)
728{
729 struct sshkey *k = NULL((void*)0);
730 int r, private = 0, ok = 0;
731 struct stat st;
732
733 if (!have_identity)
734 ask_filename(pw, "Enter file in which the key is");
735 if (stat(identity_file, &st) == -1)
736 fatal("%s: %s: %s", __progname, identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 736, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s: %s", __progname
, identity_file, strerror((*__errno())))
;
737
738 switch (convert_format) {
739 case FMT_RFC4716:
740 do_convert_from_ssh2(pw, &k, &private);
741 break;
742 case FMT_PKCS8:
743 do_convert_from_pkcs8(&k, &private);
744 break;
745 case FMT_PEM:
746 do_convert_from_pem(&k, &private);
747 break;
748 default:
749 fatal_f("unknown key format %d", convert_format)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 749, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unknown key format %d"
, convert_format)
;
750 }
751
752 if (!private) {
753 if ((r = sshkey_write(k, stdout(&__sF[1]))) == 0)
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
754 ok = 1;
755 if (ok)
756 fprintf(stdout(&__sF[1]), "\n");
757 } else {
758 switch (k->type) {
759 case KEY_DSA:
760 ok = PEM_write_DSAPrivateKey(stdout(&__sF[1]), k->dsa, NULL((void*)0),
761 NULL((void*)0), 0, NULL((void*)0), NULL((void*)0));
762 break;
763 case KEY_ECDSA:
764 ok = PEM_write_ECPrivateKey(stdout(&__sF[1]), k->ecdsa, NULL((void*)0),
765 NULL((void*)0), 0, NULL((void*)0), NULL((void*)0));
766 break;
767 case KEY_RSA:
768 ok = PEM_write_RSAPrivateKey(stdout(&__sF[1]), k->rsa, NULL((void*)0),
769 NULL((void*)0), 0, NULL((void*)0), NULL((void*)0));
770 break;
771 default:
772 fatal_f("unsupported key type %s", sshkey_type(k))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 772, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "unsupported key type %s"
, sshkey_type(k))
;
773 }
774 }
775
776 if (!ok)
777 fatal("key write failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 777, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "key write failed")
;
778 sshkey_free(k);
779 exit(0);
780}
781#endif
782
783static void
784do_print_public(struct passwd *pw)
785{
786 struct sshkey *prv;
787 struct stat st;
788 int r;
789 char *comment = NULL((void*)0);
790
791 if (!have_identity)
792 ask_filename(pw, "Enter file in which the key is");
793 if (stat(identity_file, &st) == -1)
794 fatal("%s: %s", identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 794, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s", identity_file
, strerror((*__errno())))
;
795 prv = load_identity(identity_file, &comment);
796 if ((r = sshkey_write(prv, stdout(&__sF[1]))) != 0)
797 fatal_fr(r, "write key")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 797, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "write key")
;
798 if (comment != NULL((void*)0) && *comment != '\0')
799 fprintf(stdout(&__sF[1]), " %s", comment);
800 fprintf(stdout(&__sF[1]), "\n");
801 if (sshkey_is_sk(prv)) {
802 debug("sk_application: \"%s\", sk_flags 0x%02x",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 803, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "sk_application: \"%s\", sk_flags 0x%02x"
, prv->sk_application, prv->sk_flags)
803 prv->sk_application, prv->sk_flags)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 803, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "sk_application: \"%s\", sk_flags 0x%02x"
, prv->sk_application, prv->sk_flags)
;
804 }
805 sshkey_free(prv);
806 free(comment);
807 exit(0);
808}
809
810static void
811do_download(struct passwd *pw)
812{
813#ifdef ENABLE_PKCS111
814 struct sshkey **keys = NULL((void*)0);
815 int i, nkeys;
816 enum sshkey_fp_rep rep;
817 int fptype;
818 char *fp, *ra, **comments = NULL((void*)0);
819
820 fptype = print_bubblebabble ? SSH_DIGEST_SHA11 : fingerprint_hash;
821 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
822
823 pkcs11_init(1);
824 nkeys = pkcs11_add_provider(pkcs11provider, NULL((void*)0), &keys, &comments);
825 if (nkeys <= 0)
826 fatal("cannot read public key from pkcs11")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 826, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "cannot read public key from pkcs11"
)
;
827 for (i = 0; i < nkeys; i++) {
828 if (print_fingerprint) {
829 fp = sshkey_fingerprint(keys[i], fptype, rep);
830 ra = sshkey_fingerprint(keys[i], fingerprint_hash,
831 SSH_FP_RANDOMART);
832 if (fp == NULL((void*)0) || ra == NULL((void*)0))
833 fatal_f("sshkey_fingerprint fail")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 833, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint fail"
)
;
834 printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
835 fp, sshkey_type(keys[i]));
836 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
837 printf("%s\n", ra);
838 free(ra);
839 free(fp);
840 } else {
841 (void) sshkey_write(keys[i], stdout(&__sF[1])); /* XXX check */
842 fprintf(stdout(&__sF[1]), "%s%s\n",
843 *(comments[i]) == '\0' ? "" : " ", comments[i]);
844 }
845 free(comments[i]);
846 sshkey_free(keys[i]);
847 }
848 free(comments);
849 free(keys);
850 pkcs11_terminate();
851 exit(0);
852#else
853 fatal("no pkcs11 support")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 853, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "no pkcs11 support"
)
;
854#endif /* ENABLE_PKCS11 */
855}
856
857static struct sshkey *
858try_read_key(char **cpp)
859{
860 struct sshkey *ret;
861 int r;
862
863 if ((ret = sshkey_new(KEY_UNSPEC)) == NULL((void*)0))
864 fatal("sshkey_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 864, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new failed"
)
;
865 if ((r = sshkey_read(ret, cpp)) == 0)
866 return ret;
867 /* Not a key */
868 sshkey_free(ret);
869 return NULL((void*)0);
870}
871
872static void
873fingerprint_one_key(const struct sshkey *public, const char *comment)
874{
875 char *fp = NULL((void*)0), *ra = NULL((void*)0);
876 enum sshkey_fp_rep rep;
877 int fptype;
878
879 fptype = print_bubblebabble ? SSH_DIGEST_SHA11 : fingerprint_hash;
880 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
881 fp = sshkey_fingerprint(public, fptype, rep);
882 ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART);
883 if (fp == NULL((void*)0) || ra == NULL((void*)0))
884 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 884, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint failed"
)
;
885 mprintf("%u %s %s (%s)\n", sshkey_size(public), fp,
886 comment ? comment : "no comment", sshkey_type(public));
887 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
888 printf("%s\n", ra);
889 free(ra);
890 free(fp);
891}
892
893static void
894fingerprint_private(const char *path)
895{
896 struct stat st;
897 char *comment = NULL((void*)0);
898 struct sshkey *privkey = NULL((void*)0), *pubkey = NULL((void*)0);
899 int r;
900
901 if (stat(identity_file, &st) == -1)
902 fatal("%s: %s", path, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 902, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s", path, strerror
((*__errno())))
;
903 if ((r = sshkey_load_public(path, &pubkey, &comment)) != 0)
904 debug_r(r, "load public \"%s\"", path)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 904, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "load public \"%s\""
, path)
;
905 if (pubkey == NULL((void*)0) || comment == NULL((void*)0) || *comment == '\0') {
906 free(comment);
907 if ((r = sshkey_load_private(path, NULL((void*)0),
908 &privkey, &comment)) != 0)
909 debug_r(r, "load private \"%s\"", path)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 909, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "load private \"%s\""
, path)
;
910 }
911 if (pubkey == NULL((void*)0) && privkey == NULL((void*)0))
912 fatal("%s is not a key file.", path)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 912, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s is not a key file."
, path)
;
913
914 fingerprint_one_key(pubkey == NULL((void*)0) ? privkey : pubkey, comment);
915 sshkey_free(pubkey);
916 sshkey_free(privkey);
917 free(comment);
918}
919
920static void
921do_fingerprint(struct passwd *pw)
922{
923 FILE *f;
924 struct sshkey *public = NULL((void*)0);
925 char *comment = NULL((void*)0), *cp, *ep, *line = NULL((void*)0);
926 size_t linesize = 0;
927 int i, invalid = 1;
928 const char *path;
929 u_long lnum = 0;
930
931 if (!have_identity)
932 ask_filename(pw, "Enter file in which the key is");
933 path = identity_file;
934
935 if (strcmp(identity_file, "-") == 0) {
936 f = stdin(&__sF[0]);
937 path = "(stdin)";
938 } else if ((f = fopen(path, "r")) == NULL((void*)0))
939 fatal("%s: %s: %s", __progname, path, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 939, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s: %s", __progname
, path, strerror((*__errno())))
;
940
941 while (getline(&line, &linesize, f) != -1) {
942 lnum++;
943 cp = line;
944 cp[strcspn(cp, "\n")] = '\0';
945 /* Trim leading space and comments */
946 cp = line + strspn(line, " \t");
947 if (*cp == '#' || *cp == '\0')
948 continue;
949
950 /*
951 * Input may be plain keys, private keys, authorized_keys
952 * or known_hosts.
953 */
954
955 /*
956 * Try private keys first. Assume a key is private if
957 * "SSH PRIVATE KEY" appears on the first line and we're
958 * not reading from stdin (XXX support private keys on stdin).
959 */
960 if (lnum == 1 && strcmp(identity_file, "-") != 0 &&
961 strstr(cp, "PRIVATE KEY") != NULL((void*)0)) {
962 free(line);
963 fclose(f);
964 fingerprint_private(path);
965 exit(0);
966 }
967
968 /*
969 * If it's not a private key, then this must be prepared to
970 * accept a public key prefixed with a hostname or options.
971 * Try a bare key first, otherwise skip the leading stuff.
972 */
973 if ((public = try_read_key(&cp)) == NULL((void*)0)) {
974 i = strtol(cp, &ep, 10);
975 if (i == 0 || ep == NULL((void*)0) ||
976 (*ep != ' ' && *ep != '\t')) {
977 int quoted = 0;
978
979 comment = cp;
980 for (; *cp && (quoted || (*cp != ' ' &&
981 *cp != '\t')); cp++) {
982 if (*cp == '\\' && cp[1] == '"')
983 cp++; /* Skip both */
984 else if (*cp == '"')
985 quoted = !quoted;
986 }
987 if (!*cp)
988 continue;
989 *cp++ = '\0';
990 }
991 }
992 /* Retry after parsing leading hostname/key options */
993 if (public == NULL((void*)0) && (public = try_read_key(&cp)) == NULL((void*)0)) {
994 debug("%s:%lu: not a public key", path, lnum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 994, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "%s:%lu: not a public key"
, path, lnum)
;
995 continue;
996 }
997
998 /* Find trailing comment, if any */
999 for (; *cp == ' ' || *cp == '\t'; cp++)
1000 ;
1001 if (*cp != '\0' && *cp != '#')
1002 comment = cp;
1003
1004 fingerprint_one_key(public, comment);
1005 sshkey_free(public);
1006 invalid = 0; /* One good key in the file is sufficient */
1007 }
1008 fclose(f);
1009 free(line);
1010
1011 if (invalid)
1012 fatal("%s is not a public key file.", path)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1012, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s is not a public key file."
, path)
;
1013 exit(0);
1014}
1015
1016static void
1017do_gen_all_hostkeys(struct passwd *pw)
1018{
1019 struct {
1020 char *key_type;
1021 char *key_type_display;
1022 char *path;
1023 } key_types[] = {
1024#ifdef WITH_OPENSSL1
1025 { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE"/etc" "/ssh" "/ssh_host_rsa_key" },
1026 { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE"/etc" "/ssh" "/ssh_host_dsa_key" },
1027 { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE"/etc" "/ssh" "/ssh_host_ecdsa_key" },
1028#endif /* WITH_OPENSSL */
1029 { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE"/etc" "/ssh" "/ssh_host_ed25519_key" },
1030#ifdef WITH_XMSS
1031 { "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE"/etc" "/ssh" "/ssh_host_xmss_key" },
1032#endif /* WITH_XMSS */
1033 { NULL((void*)0), NULL((void*)0), NULL((void*)0) }
1034 };
1035
1036 u_int32_t bits = 0;
1037 int first = 0;
1038 struct stat st;
1039 struct sshkey *private, *public;
1040 char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
1041 int i, type, fd, r;
1042
1043 for (i = 0; key_types[i].key_type; i++) {
1044 public = private = NULL((void*)0);
1045 prv_tmp = pub_tmp = prv_file = pub_file = NULL((void*)0);
1046
1047 xasprintf(&prv_file, "%s%s",
1048 identity_file, key_types[i].path);
1049
1050 /* Check whether private key exists and is not zero-length */
1051 if (stat(prv_file, &st) == 0) {
1052 if (st.st_size != 0)
1053 goto next;
1054 } else if (errno(*__errno()) != ENOENT2) {
1055 error("Could not stat %s: %s", key_types[i].path,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1056, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Could not stat %s: %s"
, key_types[i].path, strerror((*__errno())))
1056 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1056, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Could not stat %s: %s"
, key_types[i].path, strerror((*__errno())))
;
1057 goto failnext;
1058 }
1059
1060 /*
1061 * Private key doesn't exist or is invalid; proceed with
1062 * key generation.
1063 */
1064 xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
1065 identity_file, key_types[i].path);
1066 xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
1067 identity_file, key_types[i].path);
1068 xasprintf(&pub_file, "%s%s.pub",
1069 identity_file, key_types[i].path);
1070
1071 if (first == 0) {
1072 first = 1;
1073 printf("%s: generating new host keys: ", __progname);
1074 }
1075 printf("%s ", key_types[i].key_type_display);
1076 fflush(stdout(&__sF[1]));
1077 type = sshkey_type_from_name(key_types[i].key_type);
1078 if ((fd = mkstemp(prv_tmp)) == -1) {
1079 error("Could not save your private key in %s: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1080, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Could not save your private key in %s: %s"
, prv_tmp, strerror((*__errno())))
1080 prv_tmp, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1080, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Could not save your private key in %s: %s"
, prv_tmp, strerror((*__errno())))
;
1081 goto failnext;
1082 }
1083 (void)close(fd); /* just using mkstemp() to reserve a name */
1084 bits = 0;
1085 type_bits_valid(type, NULL((void*)0), &bits);
1086 if ((r = sshkey_generate(type, bits, &private)) != 0) {
1087 error_r(r, "sshkey_generate failed")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1087, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshkey_generate failed"
)
;
1088 goto failnext;
1089 }
1090 if ((r = sshkey_from_private(private, &public)) != 0)
1091 fatal_fr(r, "sshkey_from_private")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1091, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshkey_from_private"
)
;
1092 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1093 hostname);
1094 if ((r = sshkey_save_private(private, prv_tmp, "",
1095 comment, private_key_format, openssh_format_cipher,
1096 rounds)) != 0) {
1097 error_r(r, "Saving key \"%s\" failed", prv_tmp)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1097, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Saving key \"%s\" failed"
, prv_tmp)
;
1098 goto failnext;
1099 }
1100 if ((fd = mkstemp(pub_tmp)) == -1) {
1101 error("Could not save your public key in %s: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1102, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Could not save your public key in %s: %s"
, pub_tmp, strerror((*__errno())))
1102 pub_tmp, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1102, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Could not save your public key in %s: %s"
, pub_tmp, strerror((*__errno())))
;
1103 goto failnext;
1104 }
1105 (void)fchmod(fd, 0644);
1106 (void)close(fd);
1107 if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) {
1108 error_r(r, "Unable to save public key to %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1109, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Unable to save public key to %s"
, identity_file)
1109 identity_file)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1109, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Unable to save public key to %s"
, identity_file)
;
1110 goto failnext;
1111 }
1112
1113 /* Rename temporary files to their permanent locations. */
1114 if (rename(pub_tmp, pub_file) != 0) {
1115 error("Unable to move %s into position: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1116, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unable to move %s into position: %s"
, pub_file, strerror((*__errno())))
1116 pub_file, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1116, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unable to move %s into position: %s"
, pub_file, strerror((*__errno())))
;
1117 goto failnext;
1118 }
1119 if (rename(prv_tmp, prv_file) != 0) {
1120 error("Unable to move %s into position: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1121, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unable to move %s into position: %s"
, key_types[i].path, strerror((*__errno())))
1121 key_types[i].path, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1121, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unable to move %s into position: %s"
, key_types[i].path, strerror((*__errno())))
;
1122 failnext:
1123 first = 0;
1124 goto next;
1125 }
1126 next:
1127 sshkey_free(private);
1128 sshkey_free(public);
1129 free(prv_tmp);
1130 free(pub_tmp);
1131 free(prv_file);
1132 free(pub_file);
1133 }
1134 if (first != 0)
1135 printf("\n");
1136}
1137
1138struct known_hosts_ctx {
1139 const char *host; /* Hostname searched for in find/delete case */
1140 FILE *out; /* Output file, stdout for find_hosts case */
1141 int has_unhashed; /* When hashing, original had unhashed hosts */
1142 int found_key; /* For find/delete, host was found */
1143 int invalid; /* File contained invalid items; don't delete */
1144 int hash_hosts; /* Hash hostnames as we go */
1145 int find_host; /* Search for specific hostname */
1146 int delete_host; /* Delete host from known_hosts */
1147};
1148
1149static int
1150known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
1151{
1152 struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1153 char *hashed, *cp, *hosts, *ohosts;
1154 int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts);
1155 int was_hashed = l->hosts && l->hosts[0] == HASH_DELIM'|';
1156
1157 switch (l->status) {
1158 case HKF_STATUS_OK0:
1159 case HKF_STATUS_MATCHED3:
1160 /*
1161 * Don't hash hosts already already hashed, with wildcard
1162 * characters or a CA/revocation marker.
1163 */
1164 if (was_hashed || has_wild || l->marker != MRK_NONE) {
1165 fprintf(ctx->out, "%s\n", l->line);
1166 if (has_wild && !ctx->find_host) {
1167 logit("%s:%lu: ignoring host name "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1169, 0, SYSLOG_LEVEL_INFO, ((void*)0), "%s:%lu: ignoring host name "
"with wildcard: %.64s", l->path, l->linenum, l->hosts
)
1168 "with wildcard: %.64s", l->path,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1169, 0, SYSLOG_LEVEL_INFO, ((void*)0), "%s:%lu: ignoring host name "
"with wildcard: %.64s", l->path, l->linenum, l->hosts
)
1169 l->linenum, l->hosts)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1169, 0, SYSLOG_LEVEL_INFO, ((void*)0), "%s:%lu: ignoring host name "
"with wildcard: %.64s", l->path, l->linenum, l->hosts
)
;
1170 }
1171 return 0;
1172 }
1173 /*
1174 * Split any comma-separated hostnames from the host list,
1175 * hash and store separately.
1176 */
1177 ohosts = hosts = xstrdup(l->hosts);
1178 while ((cp = strsep(&hosts, ",")) != NULL((void*)0) && *cp != '\0') {
1179 lowercase(cp);
1180 if ((hashed = host_hash(cp, NULL((void*)0), 0)) == NULL((void*)0))
1181 fatal("hash_host failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1181, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "hash_host failed"
)
;
1182 fprintf(ctx->out, "%s %s\n", hashed, l->rawkey);
1183 free(hashed);
1184 ctx->has_unhashed = 1;
1185 }
1186 free(ohosts);
1187 return 0;
1188 case HKF_STATUS_INVALID1:
1189 /* Retain invalid lines, but mark file as invalid. */
1190 ctx->invalid = 1;
1191 logit("%s:%lu: invalid line", l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1191, 0, SYSLOG_LEVEL_INFO, ((void*)0), "%s:%lu: invalid line"
, l->path, l->linenum)
;
1192 /* FALLTHROUGH */
1193 default:
1194 fprintf(ctx->out, "%s\n", l->line);
1195 return 0;
1196 }
1197 /* NOTREACHED */
1198 return -1;
1199}
1200
1201static int
1202known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
1203{
1204 struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1205 enum sshkey_fp_rep rep;
1206 int fptype;
1207 char *fp = NULL((void*)0), *ra = NULL((void*)0);
1208
1209 fptype = print_bubblebabble ? SSH_DIGEST_SHA11 : fingerprint_hash;
1210 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
1211
1212 if (l->status == HKF_STATUS_MATCHED3) {
1213 if (ctx->delete_host) {
1214 if (l->marker != MRK_NONE) {
1215 /* Don't remove CA and revocation lines */
1216 fprintf(ctx->out, "%s\n", l->line);
1217 } else {
1218 /*
1219 * Hostname matches and has no CA/revoke
1220 * marker, delete it by *not* writing the
1221 * line to ctx->out.
1222 */
1223 ctx->found_key = 1;
1224 if (!quiet)
1225 printf("# Host %s found: line %lu\n",
1226 ctx->host, l->linenum);
1227 }
1228 return 0;
1229 } else if (ctx->find_host) {
1230 ctx->found_key = 1;
1231 if (!quiet) {
1232 printf("# Host %s found: line %lu %s\n",
1233 ctx->host,
1234 l->linenum, l->marker == MRK_CA ? "CA" :
1235 (l->marker == MRK_REVOKE ? "REVOKED" : ""));
1236 }
1237 if (ctx->hash_hosts)
1238 known_hosts_hash(l, ctx);
1239 else if (print_fingerprint) {
1240 fp = sshkey_fingerprint(l->key, fptype, rep);
1241 ra = sshkey_fingerprint(l->key,
1242 fingerprint_hash, SSH_FP_RANDOMART);
1243 if (fp == NULL((void*)0) || ra == NULL((void*)0))
1244 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1244, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint failed"
)
;
1245 mprintf("%s %s %s%s%s\n", ctx->host,
1246 sshkey_type(l->key), fp,
1247 l->comment[0] ? " " : "",
1248 l->comment);
1249 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
1250 printf("%s\n", ra);
1251 free(ra);
1252 free(fp);
1253 } else
1254 fprintf(ctx->out, "%s\n", l->line);
1255 return 0;
1256 }
1257 } else if (ctx->delete_host) {
1258 /* Retain non-matching hosts when deleting */
1259 if (l->status == HKF_STATUS_INVALID1) {
1260 ctx->invalid = 1;
1261 logit("%s:%lu: invalid line", l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1261, 0, SYSLOG_LEVEL_INFO, ((void*)0), "%s:%lu: invalid line"
, l->path, l->linenum)
;
1262 }
1263 fprintf(ctx->out, "%s\n", l->line);
1264 }
1265 return 0;
1266}
1267
1268static void
1269do_known_hosts(struct passwd *pw, const char *name, int find_host,
1270 int delete_host, int hash_hosts)
1271{
1272 char *cp, tmp[PATH_MAX1024], old[PATH_MAX1024];
1273 int r, fd, oerrno, inplace = 0;
1274 struct known_hosts_ctx ctx;
1275 u_int foreach_options;
1276 struct stat sb;
1277
1278 if (!have_identity) {
1279 cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE"~/" ".ssh" "/known_hosts", pw->pw_uid);
1280 if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
1281 sizeof(identity_file))
1282 fatal("Specified known hosts path too long")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1282, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Specified known hosts path too long"
)
;
1283 free(cp);
1284 have_identity = 1;
1285 }
1286 if (stat(identity_file, &sb) != 0)
1287 fatal("Cannot stat %s: %s", identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1287, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Cannot stat %s: %s"
, identity_file, strerror((*__errno())))
;
1288
1289 memset(&ctx, 0, sizeof(ctx));
1290 ctx.out = stdout(&__sF[1]);
1291 ctx.host = name;
1292 ctx.hash_hosts = hash_hosts;
1293 ctx.find_host = find_host;
1294 ctx.delete_host = delete_host;
1295
1296 /*
1297 * Find hosts goes to stdout, hash and deletions happen in-place
1298 * A corner case is ssh-keygen -HF foo, which should go to stdout
1299 */
1300 if (!find_host && (hash_hosts || delete_host)) {
1301 if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
1302 strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
1303 strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
1304 strlcat(old, ".old", sizeof(old)) >= sizeof(old))
1305 fatal("known_hosts path too long")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1305, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "known_hosts path too long"
)
;
1306 umask(077);
1307 if ((fd = mkstemp(tmp)) == -1)
1308 fatal("mkstemp: %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1308, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "mkstemp: %s", strerror
((*__errno())))
;
1309 if ((ctx.out = fdopen(fd, "w")) == NULL((void*)0)) {
1310 oerrno = errno(*__errno());
1311 unlink(tmp);
1312 fatal("fdopen: %s", strerror(oerrno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1312, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "fdopen: %s", strerror
(oerrno))
;
1313 }
1314 fchmod(fd, sb.st_mode & 0644);
1315 inplace = 1;
1316 }
1317 /* XXX support identity_file == "-" for stdin */
1318 foreach_options = find_host ? HKF_WANT_MATCH(1) : 0;
1319 foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY(1<<1) : 0;
1320 if ((r = hostkeys_foreach(identity_file, (find_host || !hash_hosts) ?
1321 known_hosts_find_delete : known_hosts_hash, &ctx, name, NULL((void*)0),
1322 foreach_options, 0)) != 0) {
1323 if (inplace)
1324 unlink(tmp);
1325 fatal_fr(r, "hostkeys_foreach")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1325, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "hostkeys_foreach"
)
;
1326 }
1327
1328 if (inplace)
1329 fclose(ctx.out);
1330
1331 if (ctx.invalid) {
1332 error("%s is not a valid known_hosts file.", identity_file)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1332, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "%s is not a valid known_hosts file."
, identity_file)
;
1333 if (inplace) {
1334 error("Not replacing existing known_hosts "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1335, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Not replacing existing known_hosts "
"file because of errors")
1335 "file because of errors")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1335, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Not replacing existing known_hosts "
"file because of errors")
;
1336 unlink(tmp);
1337 }
1338 exit(1);
1339 } else if (delete_host && !ctx.found_key) {
1340 logit("Host %s not found in %s", name, identity_file)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1340, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Host %s not found in %s"
, name, identity_file)
;
1341 if (inplace)
1342 unlink(tmp);
1343 } else if (inplace) {
1344 /* Backup existing file */
1345 if (unlink(old) == -1 && errno(*__errno()) != ENOENT2)
1346 fatal("unlink %.100s: %s", old, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1346, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "unlink %.100s: %s"
, old, strerror((*__errno())))
;
1347 if (link(identity_file, old) == -1)
1348 fatal("link %.100s to %.100s: %s", identity_file, old,sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1349, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "link %.100s to %.100s: %s"
, identity_file, old, strerror((*__errno())))
1349 strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1349, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "link %.100s to %.100s: %s"
, identity_file, old, strerror((*__errno())))
;
1350 /* Move new one into place */
1351 if (rename(tmp, identity_file) == -1) {
1352 error("rename\"%s\" to \"%s\": %s", tmp, identity_file,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1353, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "rename\"%s\" to \"%s\": %s"
, tmp, identity_file, strerror((*__errno())))
1353 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1353, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "rename\"%s\" to \"%s\": %s"
, tmp, identity_file, strerror((*__errno())))
;
1354 unlink(tmp);
1355 unlink(old);
1356 exit(1);
1357 }
1358
1359 printf("%s updated.\n", identity_file);
1360 printf("Original contents retained as %s\n", old);
1361 if (ctx.has_unhashed) {
1362 logit("WARNING: %s contains unhashed entries", old)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1362, 0, SYSLOG_LEVEL_INFO, ((void*)0), "WARNING: %s contains unhashed entries"
, old)
;
1363 logit("Delete this file to ensure privacy "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1364, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Delete this file to ensure privacy "
"of hostnames")
1364 "of hostnames")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1364, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Delete this file to ensure privacy "
"of hostnames")
;
1365 }
1366 }
1367
1368 exit (find_host && !ctx.found_key);
1369}
1370
1371/*
1372 * Perform changing a passphrase. The argument is the passwd structure
1373 * for the current user.
1374 */
1375static void
1376do_change_passphrase(struct passwd *pw)
1377{
1378 char *comment;
1379 char *old_passphrase, *passphrase1, *passphrase2;
1380 struct stat st;
1381 struct sshkey *private;
1382 int r;
1383
1384 if (!have_identity)
1385 ask_filename(pw, "Enter file in which the key is");
1386 if (stat(identity_file, &st) == -1)
1387 fatal("%s: %s", identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1387, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s", identity_file
, strerror((*__errno())))
;
1388 /* Try to load the file with empty passphrase. */
1389 r = sshkey_load_private(identity_file, "", &private, &comment);
1390 if (r == SSH_ERR_KEY_WRONG_PASSPHRASE-43) {
1391 if (identity_passphrase)
1392 old_passphrase = xstrdup(identity_passphrase);
1393 else
1394 old_passphrase =
1395 read_passphrase("Enter old passphrase: ",
1396 RP_ALLOW_STDIN0x0002);
1397 r = sshkey_load_private(identity_file, old_passphrase,
1398 &private, &comment);
1399 freezero(old_passphrase, strlen(old_passphrase));
1400 if (r != 0)
1401 goto badkey;
1402 } else if (r != 0) {
1403 badkey:
1404 fatal_r(r, "Failed to load key %s", identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1404, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Failed to load key %s"
, identity_file)
;
1405 }
1406 if (comment)
1407 mprintf("Key has comment '%s'\n", comment);
1408
1409 /* Ask the new passphrase (twice). */
1410 if (identity_new_passphrase) {
1411 passphrase1 = xstrdup(identity_new_passphrase);
1412 passphrase2 = NULL((void*)0);
1413 } else {
1414 passphrase1 =
1415 read_passphrase("Enter new passphrase (empty for no "
1416 "passphrase): ", RP_ALLOW_STDIN0x0002);
1417 passphrase2 = read_passphrase("Enter same passphrase again: ",
1418 RP_ALLOW_STDIN0x0002);
1419
1420 /* Verify that they are the same. */
1421 if (strcmp(passphrase1, passphrase2) != 0) {
1422 explicit_bzero(passphrase1, strlen(passphrase1));
1423 explicit_bzero(passphrase2, strlen(passphrase2));
1424 free(passphrase1);
1425 free(passphrase2);
1426 printf("Pass phrases do not match. Try again.\n");
1427 exit(1);
1428 }
1429 /* Destroy the other copy. */
1430 freezero(passphrase2, strlen(passphrase2));
1431 }
1432
1433 /* Save the file using the new passphrase. */
1434 if ((r = sshkey_save_private(private, identity_file, passphrase1,
1435 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
1436 error_r(r, "Saving key \"%s\" failed", identity_file)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1436, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Saving key \"%s\" failed"
, identity_file)
;
1437 freezero(passphrase1, strlen(passphrase1));
1438 sshkey_free(private);
1439 free(comment);
1440 exit(1);
1441 }
1442 /* Destroy the passphrase and the copy of the key in memory. */
1443 freezero(passphrase1, strlen(passphrase1));
1444 sshkey_free(private); /* Destroys contents */
1445 free(comment);
1446
1447 printf("Your identification has been saved with the new passphrase.\n");
1448 exit(0);
1449}
1450
1451/*
1452 * Print the SSHFP RR.
1453 */
1454static int
1455do_print_resource_record(struct passwd *pw, char *fname, char *hname,
1456 int print_generic)
1457{
1458 struct sshkey *public;
1459 char *comment = NULL((void*)0);
1460 struct stat st;
1461 int r;
1462
1463 if (fname == NULL((void*)0))
1464 fatal_f("no filename")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1464, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "no filename")
;
1465 if (stat(fname, &st) == -1) {
1466 if (errno(*__errno()) == ENOENT2)
1467 return 0;
1468 fatal("%s: %s", fname, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1468, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s", fname, strerror
((*__errno())))
;
1469 }
1470 if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
1471 fatal_r(r, "Failed to read v2 public key from \"%s\"", fname)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1471, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Failed to read v2 public key from \"%s\""
, fname)
;
1472 export_dns_rr(hname, public, stdout(&__sF[1]), print_generic);
1473 sshkey_free(public);
1474 free(comment);
1475 return 1;
1476}
1477
1478/*
1479 * Change the comment of a private key file.
1480 */
1481static void
1482do_change_comment(struct passwd *pw, const char *identity_comment)
1483{
1484 char new_comment[1024], *comment, *passphrase;
1485 struct sshkey *private;
1486 struct sshkey *public;
1487 struct stat st;
1488 int r;
1489
1490 if (!have_identity)
1491 ask_filename(pw, "Enter file in which the key is");
1492 if (stat(identity_file, &st) == -1)
1493 fatal("%s: %s", identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1493, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s", identity_file
, strerror((*__errno())))
;
1494 if ((r = sshkey_load_private(identity_file, "",
1495 &private, &comment)) == 0)
1496 passphrase = xstrdup("");
1497 else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE-43)
1498 fatal_r(r, "Cannot load private key \"%s\"", identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1498, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Cannot load private key \"%s\""
, identity_file)
;
1499 else {
1500 if (identity_passphrase)
1501 passphrase = xstrdup(identity_passphrase);
1502 else if (identity_new_passphrase)
1503 passphrase = xstrdup(identity_new_passphrase);
1504 else
1505 passphrase = read_passphrase("Enter passphrase: ",
1506 RP_ALLOW_STDIN0x0002);
1507 /* Try to load using the passphrase. */
1508 if ((r = sshkey_load_private(identity_file, passphrase,
1509 &private, &comment)) != 0) {
1510 freezero(passphrase, strlen(passphrase));
1511 fatal_r(r, "Cannot load private key \"%s\"",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1512, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Cannot load private key \"%s\""
, identity_file)
1512 identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1512, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Cannot load private key \"%s\""
, identity_file)
;
1513 }
1514 }
1515
1516 if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
1517 private_key_format != SSHKEY_PRIVATE_OPENSSH) {
1518 error("Comments are only supported for keys stored in "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1519, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Comments are only supported for keys stored in "
"the new format (-o).")
1519 "the new format (-o).")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1519, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Comments are only supported for keys stored in "
"the new format (-o).")
;
1520 explicit_bzero(passphrase, strlen(passphrase));
1521 sshkey_free(private);
1522 exit(1);
1523 }
1524 if (comment)
1525 printf("Old comment: %s\n", comment);
1526 else
1527 printf("No existing comment\n");
1528
1529 if (identity_comment) {
1530 strlcpy(new_comment, identity_comment, sizeof(new_comment));
1531 } else {
1532 printf("New comment: ");
1533 fflush(stdout(&__sF[1]));
1534 if (!fgets(new_comment, sizeof(new_comment), stdin(&__sF[0]))) {
1535 explicit_bzero(passphrase, strlen(passphrase));
1536 sshkey_free(private);
1537 exit(1);
1538 }
1539 new_comment[strcspn(new_comment, "\n")] = '\0';
1540 }
1541 if (comment != NULL((void*)0) && strcmp(comment, new_comment) == 0) {
1542 printf("No change to comment\n");
1543 free(passphrase);
1544 sshkey_free(private);
1545 free(comment);
1546 exit(0);
1547 }
1548
1549 /* Save the file using the new passphrase. */
1550 if ((r = sshkey_save_private(private, identity_file, passphrase,
1551 new_comment, private_key_format, openssh_format_cipher,
1552 rounds)) != 0) {
1553 error_r(r, "Saving key \"%s\" failed", identity_file)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1553, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Saving key \"%s\" failed"
, identity_file)
;
1554 freezero(passphrase, strlen(passphrase));
1555 sshkey_free(private);
1556 free(comment);
1557 exit(1);
1558 }
1559 freezero(passphrase, strlen(passphrase));
1560 if ((r = sshkey_from_private(private, &public)) != 0)
1561 fatal_fr(r, "sshkey_from_private")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1561, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshkey_from_private"
)
;
1562 sshkey_free(private);
1563
1564 strlcat(identity_file, ".pub", sizeof(identity_file));
1565 if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0)
1566 fatal_r(r, "Unable to save public key to %s", identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1566, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to save public key to %s"
, identity_file)
;
1567 sshkey_free(public);
1568 free(comment);
1569
1570 if (strlen(new_comment) > 0)
1571 printf("Comment '%s' applied\n", new_comment);
1572 else
1573 printf("Comment removed\n");
1574
1575 exit(0);
1576}
1577
1578static void
1579cert_ext_add(const char *key, const char *value, int iscrit)
1580{
1581 cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext));
1582 cert_ext[ncert_ext].key = xstrdup(key);
1583 cert_ext[ncert_ext].val = value == NULL((void*)0) ? NULL((void*)0) : xstrdup(value);
1584 cert_ext[ncert_ext].crit = iscrit;
1585 ncert_ext++;
1586}
1587
1588/* qsort(3) comparison function for certificate extensions */
1589static int
1590cert_ext_cmp(const void *_a, const void *_b)
1591{
1592 const struct cert_ext *a = (const struct cert_ext *)_a;
1593 const struct cert_ext *b = (const struct cert_ext *)_b;
1594 int r;
1595
1596 if (a->crit != b->crit)
1597 return (a->crit < b->crit) ? -1 : 1;
1598 if ((r = strcmp(a->key, b->key)) != 0)
1599 return r;
1600 if ((a->val == NULL((void*)0)) != (b->val == NULL((void*)0)))
1601 return (a->val == NULL((void*)0)) ? -1 : 1;
1602 if (a->val != NULL((void*)0) && (r = strcmp(a->val, b->val)) != 0)
1603 return r;
1604 return 0;
1605}
1606
1607#define OPTIONS_CRITICAL1 1
1608#define OPTIONS_EXTENSIONS2 2
1609static void
1610prepare_options_buf(struct sshbuf *c, int which)
1611{
1612 struct sshbuf *b;
1613 size_t i;
1614 int r;
1615 const struct cert_ext *ext;
1616
1617 if ((b = sshbuf_new()) == NULL((void*)0))
1618 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1618, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
1619 sshbuf_reset(c);
1620 for (i = 0; i < ncert_ext; i++) {
1621 ext = &cert_ext[i];
1622 if ((ext->crit && (which & OPTIONS_EXTENSIONS2)) ||
1623 (!ext->crit && (which & OPTIONS_CRITICAL1)))
1624 continue;
1625 if (ext->val == NULL((void*)0)) {
1626 /* flag option */
1627 debug3_f("%s", ext->key)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1627, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s", ext->key
)
;
1628 if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1629 (r = sshbuf_put_string(c, NULL((void*)0), 0)) != 0)
1630 fatal_fr(r, "prepare flag")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1630, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "prepare flag")
;
1631 } else {
1632 /* key/value option */
1633 debug3_f("%s=%s", ext->key, ext->val)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1633, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%s=%s", ext->
key, ext->val)
;
1634 sshbuf_reset(b);
1635 if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1636 (r = sshbuf_put_cstring(b, ext->val)) != 0 ||
1637 (r = sshbuf_put_stringb(c, b)) != 0)
1638 fatal_fr(r, "prepare k/v")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1638, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "prepare k/v")
;
1639 }
1640 }
1641 sshbuf_free(b);
1642}
1643
1644static void
1645finalise_cert_exts(void)
1646{
1647 /* critical options */
1648 if (certflags_command != NULL((void*)0))
1649 cert_ext_add("force-command", certflags_command, 1);
1650 if (certflags_src_addr != NULL((void*)0))
1651 cert_ext_add("source-address", certflags_src_addr, 1);
1652 /* extensions */
1653 if ((certflags_flags & CERTOPT_X_FWD(1)) != 0)
1654 cert_ext_add("permit-X11-forwarding", NULL((void*)0), 0);
1655 if ((certflags_flags & CERTOPT_AGENT_FWD(1<<1)) != 0)
1656 cert_ext_add("permit-agent-forwarding", NULL((void*)0), 0);
1657 if ((certflags_flags & CERTOPT_PORT_FWD(1<<2)) != 0)
1658 cert_ext_add("permit-port-forwarding", NULL((void*)0), 0);
1659 if ((certflags_flags & CERTOPT_PTY(1<<3)) != 0)
1660 cert_ext_add("permit-pty", NULL((void*)0), 0);
1661 if ((certflags_flags & CERTOPT_USER_RC(1<<4)) != 0)
1662 cert_ext_add("permit-user-rc", NULL((void*)0), 0);
1663 if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE(1<<5)) != 0)
1664 cert_ext_add("no-touch-required", NULL((void*)0), 0);
1665 /* order lexically by key */
1666 if (ncert_ext > 0)
1667 qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp);
1668}
1669
1670static struct sshkey *
1671load_pkcs11_key(char *path)
1672{
1673#ifdef ENABLE_PKCS111
1674 struct sshkey **keys = NULL((void*)0), *public, *private = NULL((void*)0);
1675 int r, i, nkeys;
1676
1677 if ((r = sshkey_load_public(path, &public, NULL((void*)0))) != 0)
1678 fatal_r(r, "Couldn't load CA public key \"%s\"", path)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1678, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Couldn't load CA public key \"%s\""
, path)
;
1679
1680 nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase,
1681 &keys, NULL((void*)0));
1682 debug3_f("%d keys", nkeys)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1682, 1, SYSLOG_LEVEL_DEBUG3, ((void*)0), "%d keys", nkeys)
;
1683 if (nkeys <= 0)
1684 fatal("cannot read public key from pkcs11")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1684, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "cannot read public key from pkcs11"
)
;
1685 for (i = 0; i < nkeys; i++) {
1686 if (sshkey_equal_public(public, keys[i])) {
1687 private = keys[i];
1688 continue;
1689 }
1690 sshkey_free(keys[i]);
1691 }
1692 free(keys);
1693 sshkey_free(public);
1694 return private;
1695#else
1696 fatal("no pkcs11 support")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1696, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "no pkcs11 support"
)
;
1697#endif /* ENABLE_PKCS11 */
1698}
1699
1700/* Signer for sshkey_certify_custom that uses the agent */
1701static int
1702agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp,
1703 const u_char *data, size_t datalen,
1704 const char *alg, const char *provider, const char *pin,
1705 u_int compat, void *ctx)
1706{
1707 int *agent_fdp = (int *)ctx;
1708
1709 return ssh_agent_sign(*agent_fdp, key, sigp, lenp,
1710 data, datalen, alg, compat);
1711}
1712
1713static void
1714do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
1715 unsigned long long cert_serial, int cert_serial_autoinc,
1716 int argc, char **argv)
1717{
1718 int r, i, found, agent_fd = -1;
1719 u_int n;
1720 struct sshkey *ca, *public;
1721 char valid[64], *otmp, *tmp, *cp, *out, *comment;
1722 char *ca_fp = NULL((void*)0), **plist = NULL((void*)0), *pin = NULL((void*)0);
1723 struct ssh_identitylist *agent_ids;
1724 size_t j;
1725 struct notifier_ctx *notifier = NULL((void*)0);
1726
1727#ifdef ENABLE_PKCS111
1728 pkcs11_init(1);
1729#endif
1730 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
1731 if (pkcs11provider != NULL((void*)0)) {
1732 /* If a PKCS#11 token was specified then try to use it */
1733 if ((ca = load_pkcs11_key(tmp)) == NULL((void*)0))
1734 fatal("No PKCS#11 key matching %s found", ca_key_path)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1734, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "No PKCS#11 key matching %s found"
, ca_key_path)
;
1735 } else if (prefer_agent) {
1736 /*
1737 * Agent signature requested. Try to use agent after making
1738 * sure the public key specified is actually present in the
1739 * agent.
1740 */
1741 if ((r = sshkey_load_public(tmp, &ca, NULL((void*)0))) != 0)
1742 fatal_r(r, "Cannot load CA public key %s", tmp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1742, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Cannot load CA public key %s"
, tmp)
;
1743 if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
1744 fatal_r(r, "Cannot use public key for CA signature")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1744, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Cannot use public key for CA signature"
)
;
1745 if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
1746 fatal_r(r, "Retrieve agent key list")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1746, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Retrieve agent key list"
)
;
1747 found = 0;
1748 for (j = 0; j < agent_ids->nkeys; j++) {
1749 if (sshkey_equal(ca, agent_ids->keys[j])) {
1750 found = 1;
1751 break;
1752 }
1753 }
1754 if (!found)
1755 fatal("CA key %s not found in agent", tmp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1755, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "CA key %s not found in agent"
, tmp)
;
1756 ssh_free_identitylist(agent_ids);
1757 ca->flags |= SSHKEY_FLAG_EXT0x0001;
1758 } else {
1759 /* CA key is assumed to be a private key on the filesystem */
1760 ca = load_identity(tmp, NULL((void*)0));
1761 if (sshkey_is_sk(ca) &&
1762 (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD0x04)) {
1763 if ((pin = read_passphrase("Enter PIN for CA key: ",
1764 RP_ALLOW_STDIN0x0002)) == NULL((void*)0))
1765 fatal_f("couldn't read PIN")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1765, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "couldn't read PIN"
)
;
1766 }
1767 }
1768 free(tmp);
1769
1770 if (key_type_name != NULL((void*)0)) {
1771 if (sshkey_type_from_name(key_type_name) != ca->type) {
1772 fatal("CA key type %s doesn't match specified %s",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1773, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "CA key type %s doesn't match specified %s"
, sshkey_ssh_name(ca), key_type_name)
1773 sshkey_ssh_name(ca), key_type_name)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1773, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "CA key type %s doesn't match specified %s"
, sshkey_ssh_name(ca), key_type_name)
;
1774 }
1775 } else if (ca->type == KEY_RSA) {
1776 /* Default to a good signature algorithm */
1777 key_type_name = "rsa-sha2-512";
1778 }
1779 ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT);
1780
1781 finalise_cert_exts();
1782 for (i = 0; i < argc; i++) {
1783 /* Split list of principals */
1784 n = 0;
1785 if (cert_principals != NULL((void*)0)) {
1786 otmp = tmp = xstrdup(cert_principals);
1787 plist = NULL((void*)0);
1788 for (; (cp = strsep(&tmp, ",")) != NULL((void*)0); n++) {
1789 plist = xreallocarray(plist, n + 1, sizeof(*plist));
1790 if (*(plist[n] = xstrdup(cp)) == '\0')
1791 fatal("Empty principal name")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1791, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Empty principal name"
)
;
1792 }
1793 free(otmp);
1794 }
1795 if (n > SSHKEY_CERT_MAX_PRINCIPALS256)
1796 fatal("Too many certificate principals specified")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1796, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Too many certificate principals specified"
)
;
1797
1798 tmp = tilde_expand_filename(argv[i], pw->pw_uid);
1799 if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
1800 fatal_r(r, "load pubkey \"%s\"", tmp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1800, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "load pubkey \"%s\""
, tmp)
;
1801 if (sshkey_is_cert(public))
1802 fatal_f("key \"%s\" type %s cannot be certified",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1803, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "key \"%s\" type %s cannot be certified"
, tmp, sshkey_type(public))
1803 tmp, sshkey_type(public))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1803, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "key \"%s\" type %s cannot be certified"
, tmp, sshkey_type(public))
;
1804
1805 /* Prepare certificate to sign */
1806 if ((r = sshkey_to_certified(public)) != 0)
1807 fatal_r(r, "Could not upgrade key %s to certificate", tmp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1807, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Could not upgrade key %s to certificate"
, tmp)
;
1808 public->cert->type = cert_key_type;
1809 public->cert->serial = (u_int64_t)cert_serial;
1810 public->cert->key_id = xstrdup(cert_key_id);
1811 public->cert->nprincipals = n;
1812 public->cert->principals = plist;
1813 public->cert->valid_after = cert_valid_from;
1814 public->cert->valid_before = cert_valid_to;
1815 prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL1);
1816 prepare_options_buf(public->cert->extensions,
1817 OPTIONS_EXTENSIONS2);
1818 if ((r = sshkey_from_private(ca,
1819 &public->cert->signature_key)) != 0)
1820 fatal_r(r, "sshkey_from_private (ca key)")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1820, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshkey_from_private (ca key)"
)
;
1821
1822 if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT0x0001) != 0) {
1823 if ((r = sshkey_certify_custom(public, ca,
1824 key_type_name, sk_provider, NULL((void*)0), agent_signer,
1825 &agent_fd)) != 0)
1826 fatal_r(r, "Couldn't certify %s via agent", tmp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1826, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Couldn't certify %s via agent"
, tmp)
;
1827 } else {
1828 if (sshkey_is_sk(ca) &&
1829 (ca->sk_flags & SSH_SK_USER_PRESENCE_REQD0x01)) {
1830 notifier = notify_start(0,
1831 "Confirm user presence for key %s %s",
1832 sshkey_type(ca), ca_fp);
1833 }
1834 r = sshkey_certify(public, ca, key_type_name,
1835 sk_provider, pin);
1836 notify_complete(notifier, "User presence confirmed");
1837 if (r != 0)
1838 fatal_r(r, "Couldn't certify key %s", tmp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1838, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Couldn't certify key %s"
, tmp)
;
1839 }
1840
1841 if ((cp = strrchr(tmp, '.')) != NULL((void*)0) && strcmp(cp, ".pub") == 0)
1842 *cp = '\0';
1843 xasprintf(&out, "%s-cert.pub", tmp);
1844 free(tmp);
1845
1846 if ((r = sshkey_save_public(public, out, comment)) != 0) {
1847 fatal_r(r, "Unable to save public key to %s",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1848, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to save public key to %s"
, identity_file)
1848 identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1848, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to save public key to %s"
, identity_file)
;
1849 }
1850
1851 if (!quiet) {
1852 sshkey_format_cert_validity(public->cert,
1853 valid, sizeof(valid));
1854 logit("Signed %s key %s: id \"%s\" serial %llu%s%s "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1860, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public), out, public->cert->
key_id, (unsigned long long)public->cert->serial, cert_principals
!= ((void*)0) ? " for " : "", cert_principals != ((void*)0) ?
cert_principals : "", valid)
1855 "valid %s", sshkey_cert_type(public),sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1860, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public), out, public->cert->
key_id, (unsigned long long)public->cert->serial, cert_principals
!= ((void*)0) ? " for " : "", cert_principals != ((void*)0) ?
cert_principals : "", valid)
1856 out, public->cert->key_id,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1860, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public), out, public->cert->
key_id, (unsigned long long)public->cert->serial, cert_principals
!= ((void*)0) ? " for " : "", cert_principals != ((void*)0) ?
cert_principals : "", valid)
1857 (unsigned long long)public->cert->serial,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1860, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public), out, public->cert->
key_id, (unsigned long long)public->cert->serial, cert_principals
!= ((void*)0) ? " for " : "", cert_principals != ((void*)0) ?
cert_principals : "", valid)
1858 cert_principals != NULL ? " for " : "",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1860, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public), out, public->cert->
key_id, (unsigned long long)public->cert->serial, cert_principals
!= ((void*)0) ? " for " : "", cert_principals != ((void*)0) ?
cert_principals : "", valid)
1859 cert_principals != NULL ? cert_principals : "",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1860, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public), out, public->cert->
key_id, (unsigned long long)public->cert->serial, cert_principals
!= ((void*)0) ? " for " : "", cert_principals != ((void*)0) ?
cert_principals : "", valid)
1860 valid)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1860, 0, SYSLOG_LEVEL_INFO, ((void*)0), "Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public), out, public->cert->
key_id, (unsigned long long)public->cert->serial, cert_principals
!= ((void*)0) ? " for " : "", cert_principals != ((void*)0) ?
cert_principals : "", valid)
;
1861 }
1862
1863 sshkey_free(public);
1864 free(out);
1865 if (cert_serial_autoinc)
1866 cert_serial++;
1867 }
1868 if (pin != NULL((void*)0))
1869 freezero(pin, strlen(pin));
1870 free(ca_fp);
1871#ifdef ENABLE_PKCS111
1872 pkcs11_terminate();
1873#endif
1874 exit(0);
1875}
1876
1877static u_int64_t
1878parse_relative_time(const char *s, time_t now)
1879{
1880 int64_t mul, secs;
1881
1882 mul = *s == '-' ? -1 : 1;
1883
1884 if ((secs = convtime(s + 1)) == -1)
1885 fatal("Invalid relative certificate time %s", s)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1885, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid relative certificate time %s"
, s)
;
1886 if (mul == -1 && secs > now)
1887 fatal("Certificate time %s cannot be represented", s)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1887, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Certificate time %s cannot be represented"
, s)
;
1888 return now + (u_int64_t)(secs * mul);
1889}
1890
1891static void
1892parse_cert_times(char *timespec)
1893{
1894 char *from, *to;
1895 time_t now = time(NULL((void*)0));
1896 int64_t secs;
1897
1898 /* +timespec relative to now */
1899 if (*timespec == '+' && strchr(timespec, ':') == NULL((void*)0)) {
1900 if ((secs = convtime(timespec + 1)) == -1)
1901 fatal("Invalid relative certificate life %s", timespec)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1901, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid relative certificate life %s"
, timespec)
;
1902 cert_valid_to = now + secs;
1903 /*
1904 * Backdate certificate one minute to avoid problems on hosts
1905 * with poorly-synchronised clocks.
1906 */
1907 cert_valid_from = ((now - 59)/ 60) * 60;
1908 return;
1909 }
1910
1911 /*
1912 * from:to, where
1913 * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always"
1914 * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever"
1915 */
1916 from = xstrdup(timespec);
1917 to = strchr(from, ':');
1918 if (to == NULL((void*)0) || from == to || *(to + 1) == '\0')
1919 fatal("Invalid certificate life specification %s", timespec)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1919, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid certificate life specification %s"
, timespec)
;
1920 *to++ = '\0';
1921
1922 if (*from == '-' || *from == '+')
1923 cert_valid_from = parse_relative_time(from, now);
1924 else if (strcmp(from, "always") == 0)
1925 cert_valid_from = 0;
1926 else if (parse_absolute_time(from, &cert_valid_from) != 0)
1927 fatal("Invalid from time \"%s\"", from)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1927, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid from time \"%s\""
, from)
;
1928
1929 if (*to == '-' || *to == '+')
1930 cert_valid_to = parse_relative_time(to, now);
1931 else if (strcmp(to, "forever") == 0)
1932 cert_valid_to = ~(u_int64_t)0;
1933 else if (parse_absolute_time(to, &cert_valid_to) != 0)
1934 fatal("Invalid to time \"%s\"", to)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1934, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid to time \"%s\""
, to)
;
1935
1936 if (cert_valid_to <= cert_valid_from)
1937 fatal("Empty certificate validity interval")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1937, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Empty certificate validity interval"
)
;
1938 free(from);
1939}
1940
1941static void
1942add_cert_option(char *opt)
1943{
1944 char *val, *cp;
1945 int iscrit = 0;
1946
1947 if (strcasecmp(opt, "clear") == 0)
1948 certflags_flags = 0;
1949 else if (strcasecmp(opt, "no-x11-forwarding") == 0)
1950 certflags_flags &= ~CERTOPT_X_FWD(1);
1951 else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
1952 certflags_flags |= CERTOPT_X_FWD(1);
1953 else if (strcasecmp(opt, "no-agent-forwarding") == 0)
1954 certflags_flags &= ~CERTOPT_AGENT_FWD(1<<1);
1955 else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
1956 certflags_flags |= CERTOPT_AGENT_FWD(1<<1);
1957 else if (strcasecmp(opt, "no-port-forwarding") == 0)
1958 certflags_flags &= ~CERTOPT_PORT_FWD(1<<2);
1959 else if (strcasecmp(opt, "permit-port-forwarding") == 0)
1960 certflags_flags |= CERTOPT_PORT_FWD(1<<2);
1961 else if (strcasecmp(opt, "no-pty") == 0)
1962 certflags_flags &= ~CERTOPT_PTY(1<<3);
1963 else if (strcasecmp(opt, "permit-pty") == 0)
1964 certflags_flags |= CERTOPT_PTY(1<<3);
1965 else if (strcasecmp(opt, "no-user-rc") == 0)
1966 certflags_flags &= ~CERTOPT_USER_RC(1<<4);
1967 else if (strcasecmp(opt, "permit-user-rc") == 0)
1968 certflags_flags |= CERTOPT_USER_RC(1<<4);
1969 else if (strcasecmp(opt, "touch-required") == 0)
1970 certflags_flags &= ~CERTOPT_NO_REQUIRE_USER_PRESENCE(1<<5);
1971 else if (strcasecmp(opt, "no-touch-required") == 0)
1972 certflags_flags |= CERTOPT_NO_REQUIRE_USER_PRESENCE(1<<5);
1973 else if (strncasecmp(opt, "force-command=", 14) == 0) {
1974 val = opt + 14;
1975 if (*val == '\0')
1976 fatal("Empty force-command option")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1976, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Empty force-command option"
)
;
1977 if (certflags_command != NULL((void*)0))
1978 fatal("force-command already specified")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1978, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "force-command already specified"
)
;
1979 certflags_command = xstrdup(val);
1980 } else if (strncasecmp(opt, "source-address=", 15) == 0) {
1981 val = opt + 15;
1982 if (*val == '\0')
1983 fatal("Empty source-address option")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1983, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Empty source-address option"
)
;
1984 if (certflags_src_addr != NULL((void*)0))
1985 fatal("source-address already specified")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1985, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "source-address already specified"
)
;
1986 if (addr_match_cidr_list(NULL((void*)0), val) != 0)
1987 fatal("Invalid source-address list")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1987, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid source-address list"
)
;
1988 certflags_src_addr = xstrdup(val);
1989 } else if (strncasecmp(opt, "extension:", 10) == 0 ||
1990 (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) {
1991 val = xstrdup(strchr(opt, ':') + 1);
1992 if ((cp = strchr(val, '=')) != NULL((void*)0))
1993 *cp++ = '\0';
1994 cert_ext_add(val, cp, iscrit);
1995 free(val);
1996 } else
1997 fatal("Unsupported certificate option \"%s\"", opt)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 1997, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Unsupported certificate option \"%s\""
, opt)
;
1998}
1999
2000static void
2001show_options(struct sshbuf *optbuf, int in_critical)
2002{
2003 char *name, *arg, *hex;
2004 struct sshbuf *options, *option = NULL((void*)0);
2005 int r;
2006
2007 if ((options = sshbuf_fromb(optbuf)) == NULL((void*)0))
2008 fatal_f("sshbuf_fromb failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2008, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_fromb failed"
)
;
2009 while (sshbuf_len(options) != 0) {
2010 sshbuf_free(option);
2011 option = NULL((void*)0);
2012 if ((r = sshbuf_get_cstring(options, &name, NULL((void*)0))) != 0 ||
2013 (r = sshbuf_froms(options, &option)) != 0)
2014 fatal_fr(r, "parse option")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2014, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse option")
;
2015 printf(" %s", name);
2016 if (!in_critical &&
2017 (strcmp(name, "permit-X11-forwarding") == 0 ||
2018 strcmp(name, "permit-agent-forwarding") == 0 ||
2019 strcmp(name, "permit-port-forwarding") == 0 ||
2020 strcmp(name, "permit-pty") == 0 ||
2021 strcmp(name, "permit-user-rc") == 0 ||
2022 strcmp(name, "no-touch-required") == 0)) {
2023 printf("\n");
2024 } else if (in_critical &&
2025 (strcmp(name, "force-command") == 0 ||
2026 strcmp(name, "source-address") == 0)) {
2027 if ((r = sshbuf_get_cstring(option, &arg, NULL((void*)0))) != 0)
2028 fatal_fr(r, "parse critical")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2028, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse critical")
;
2029 printf(" %s\n", arg);
2030 free(arg);
2031 } else if (sshbuf_len(option) > 0) {
2032 hex = sshbuf_dtob16(option);
2033 printf(" UNKNOWN OPTION: %s (len %zu)\n",
2034 hex, sshbuf_len(option));
2035 sshbuf_reset(option);
2036 free(hex);
2037 } else
2038 printf(" UNKNOWN FLAG OPTION\n");
2039 free(name);
2040 if (sshbuf_len(option) != 0)
2041 fatal("Option corrupt: extra data at end")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2041, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option corrupt: extra data at end"
)
;
2042 }
2043 sshbuf_free(option);
2044 sshbuf_free(options);
2045}
2046
2047static void
2048print_cert(struct sshkey *key)
2049{
2050 char valid[64], *key_fp, *ca_fp;
2051 u_int i;
2052
2053 key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
2054 ca_fp = sshkey_fingerprint(key->cert->signature_key,
2055 fingerprint_hash, SSH_FP_DEFAULT);
2056 if (key_fp == NULL((void*)0) || ca_fp == NULL((void*)0))
2057 fatal_f("sshkey_fingerprint fail")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2057, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint fail"
)
;
2058 sshkey_format_cert_validity(key->cert, valid, sizeof(valid));
2059
2060 printf(" Type: %s %s certificate\n", sshkey_ssh_name(key),
2061 sshkey_cert_type(key));
2062 printf(" Public key: %s %s\n", sshkey_type(key), key_fp);
2063 printf(" Signing CA: %s %s (using %s)\n",
2064 sshkey_type(key->cert->signature_key), ca_fp,
2065 key->cert->signature_type);
2066 printf(" Key ID: \"%s\"\n", key->cert->key_id);
2067 printf(" Serial: %llu\n", (unsigned long long)key->cert->serial);
2068 printf(" Valid: %s\n", valid);
2069 printf(" Principals: ");
2070 if (key->cert->nprincipals == 0)
2071 printf("(none)\n");
2072 else {
2073 for (i = 0; i < key->cert->nprincipals; i++)
2074 printf("\n %s",
2075 key->cert->principals[i]);
2076 printf("\n");
2077 }
2078 printf(" Critical Options: ");
2079 if (sshbuf_len(key->cert->critical) == 0)
2080 printf("(none)\n");
2081 else {
2082 printf("\n");
2083 show_options(key->cert->critical, 1);
2084 }
2085 printf(" Extensions: ");
2086 if (sshbuf_len(key->cert->extensions) == 0)
2087 printf("(none)\n");
2088 else {
2089 printf("\n");
2090 show_options(key->cert->extensions, 0);
2091 }
2092}
2093
2094static void
2095do_show_cert(struct passwd *pw)
2096{
2097 struct sshkey *key = NULL((void*)0);
2098 struct stat st;
2099 int r, is_stdin = 0, ok = 0;
2100 FILE *f;
2101 char *cp, *line = NULL((void*)0);
2102 const char *path;
2103 size_t linesize = 0;
2104 u_long lnum = 0;
2105
2106 if (!have_identity)
2107 ask_filename(pw, "Enter file in which the key is");
2108 if (strcmp(identity_file, "-") != 0 && stat(identity_file, &st) == -1)
2109 fatal("%s: %s: %s", __progname, identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2109, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s: %s", __progname
, identity_file, strerror((*__errno())))
;
2110
2111 path = identity_file;
2112 if (strcmp(path, "-") == 0) {
2113 f = stdin(&__sF[0]);
2114 path = "(stdin)";
2115 is_stdin = 1;
2116 } else if ((f = fopen(identity_file, "r")) == NULL((void*)0))
2117 fatal("fopen %s: %s", identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2117, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "fopen %s: %s", identity_file
, strerror((*__errno())))
;
2118
2119 while (getline(&line, &linesize, f) != -1) {
2120 lnum++;
2121 sshkey_free(key);
2122 key = NULL((void*)0);
2123 /* Trim leading space and comments */
2124 cp = line + strspn(line, " \t");
2125 if (*cp == '#' || *cp == '\0')
2126 continue;
2127 if ((key = sshkey_new(KEY_UNSPEC)) == NULL((void*)0))
2128 fatal("sshkey_new")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2128, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new")
;
2129 if ((r = sshkey_read(key, &cp)) != 0) {
2130 error_r(r, "%s:%lu: invalid key", path, lnum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2130, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "%s:%lu: invalid key"
, path, lnum)
;
2131 continue;
2132 }
2133 if (!sshkey_is_cert(key)) {
2134 error("%s:%lu is not a certificate", path, lnum)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2134, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "%s:%lu is not a certificate"
, path, lnum)
;
2135 continue;
2136 }
2137 ok = 1;
2138 if (!is_stdin && lnum == 1)
2139 printf("%s:\n", path);
2140 else
2141 printf("%s:%lu:\n", path, lnum);
2142 print_cert(key);
2143 }
2144 free(line);
2145 sshkey_free(key);
2146 fclose(f);
2147 exit(ok ? 0 : 1);
2148}
2149
2150static void
2151load_krl(const char *path, struct ssh_krl **krlp)
2152{
2153 struct sshbuf *krlbuf;
2154 int r;
2155
2156 if ((r = sshbuf_load_file(path, &krlbuf)) != 0)
2157 fatal_r(r, "Unable to load KRL %s", path)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2157, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to load KRL %s"
, path)
;
2158 /* XXX check sigs */
2159 if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL((void*)0), 0)) != 0 ||
2160 *krlp == NULL((void*)0))
2161 fatal_r(r, "Invalid KRL file %s", path)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2161, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Invalid KRL file %s"
, path)
;
2162 sshbuf_free(krlbuf);
2163}
2164
2165static void
2166hash_to_blob(const char *cp, u_char **blobp, size_t *lenp,
2167 const char *file, u_long lnum)
2168{
2169 char *tmp;
2170 size_t tlen;
2171 struct sshbuf *b;
2172 int r;
2173
2174 if (strncmp(cp, "SHA256:", 7) != 0)
2175 fatal("%s:%lu: unsupported hash algorithm", file, lnum)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2175, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: unsupported hash algorithm"
, file, lnum)
;
2176 cp += 7;
2177
2178 /*
2179 * OpenSSH base64 hashes omit trailing '='
2180 * characters; put them back for decode.
2181 */
2182 tlen = strlen(cp);
2183 tmp = xmalloc(tlen + 4 + 1);
2184 strlcpy(tmp, cp, tlen + 1);
2185 while ((tlen % 4) != 0) {
2186 tmp[tlen++] = '=';
2187 tmp[tlen] = '\0';
2188 }
2189 if ((b = sshbuf_new()) == NULL((void*)0))
2190 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2190, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
2191 if ((r = sshbuf_b64tod(b, tmp)) != 0)
2192 fatal_r(r, "%s:%lu: decode hash failed", file, lnum)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2192, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "%s:%lu: decode hash failed"
, file, lnum)
;
2193 free(tmp);
2194 *lenp = sshbuf_len(b);
2195 *blobp = xmalloc(*lenp);
2196 memcpy(*blobp, sshbuf_ptr(b), *lenp);
2197 sshbuf_free(b);
2198}
2199
2200static void
2201update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
2202 const struct sshkey *ca, struct ssh_krl *krl)
2203{
2204 struct sshkey *key = NULL((void*)0);
2205 u_long lnum = 0;
2206 char *path, *cp, *ep, *line = NULL((void*)0);
2207 u_char *blob = NULL((void*)0);
2208 size_t blen = 0, linesize = 0;
2209 unsigned long long serial, serial2;
2210 int i, was_explicit_key, was_sha1, was_sha256, was_hash, r;
2211 FILE *krl_spec;
2212
2213 path = tilde_expand_filename(file, pw->pw_uid);
2214 if (strcmp(path, "-") == 0) {
2215 krl_spec = stdin(&__sF[0]);
2216 free(path);
2217 path = xstrdup("(standard input)");
2218 } else if ((krl_spec = fopen(path, "r")) == NULL((void*)0))
2219 fatal("fopen %s: %s", path, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2219, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "fopen %s: %s", path
, strerror((*__errno())))
;
2220
2221 if (!quiet)
2222 printf("Revoking from %s\n", path);
2223 while (getline(&line, &linesize, krl_spec) != -1) {
2224 lnum++;
2225 was_explicit_key = was_sha1 = was_sha256 = was_hash = 0;
2226 cp = line + strspn(line, " \t");
2227 /* Trim trailing space, comments and strip \n */
2228 for (i = 0, r = -1; cp[i] != '\0'; i++) {
2229 if (cp[i] == '#' || cp[i] == '\n') {
2230 cp[i] = '\0';
2231 break;
2232 }
2233 if (cp[i] == ' ' || cp[i] == '\t') {
2234 /* Remember the start of a span of whitespace */
2235 if (r == -1)
2236 r = i;
2237 } else
2238 r = -1;
2239 }
2240 if (r != -1)
2241 cp[r] = '\0';
2242 if (*cp == '\0')
2243 continue;
2244 if (strncasecmp(cp, "serial:", 7) == 0) {
2245 if (ca == NULL((void*)0) && !wild_ca) {
2246 fatal("revoking certificates by serial number "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2247, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "revoking certificates by serial number "
"requires specification of a CA key")
2247 "requires specification of a CA key")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2247, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "revoking certificates by serial number "
"requires specification of a CA key")
;
2248 }
2249 cp += 7;
2250 cp = cp + strspn(cp, " \t");
2251 errno(*__errno()) = 0;
2252 serial = strtoull(cp, &ep, 0);
2253 if (*cp == '\0' || (*ep != '\0' && *ep != '-'))
2254 fatal("%s:%lu: invalid serial \"%s\"",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2255, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial \"%s\""
, path, lnum, cp)
2255 path, lnum, cp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2255, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial \"%s\""
, path, lnum, cp)
;
2256 if (errno(*__errno()) == ERANGE34 && serial == ULLONG_MAX(9223372036854775807LL*2ULL+1ULL))
2257 fatal("%s:%lu: serial out of range",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2258, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: serial out of range"
, path, lnum)
2258 path, lnum)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2258, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: serial out of range"
, path, lnum)
;
2259 serial2 = serial;
2260 if (*ep == '-') {
2261 cp = ep + 1;
2262 errno(*__errno()) = 0;
2263 serial2 = strtoull(cp, &ep, 0);
2264 if (*cp == '\0' || *ep != '\0')
2265 fatal("%s:%lu: invalid serial \"%s\"",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2266, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial \"%s\""
, path, lnum, cp)
2266 path, lnum, cp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2266, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial \"%s\""
, path, lnum, cp)
;
2267 if (errno(*__errno()) == ERANGE34 && serial2 == ULLONG_MAX(9223372036854775807LL*2ULL+1ULL))
2268 fatal("%s:%lu: serial out of range",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2269, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: serial out of range"
, path, lnum)
2269 path, lnum)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2269, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: serial out of range"
, path, lnum)
;
2270 if (serial2 <= serial)
2271 fatal("%s:%lu: invalid serial range "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2274, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial range "
"%llu:%llu", path, lnum, (unsigned long long)serial, (unsigned
long long)serial2)
2272 "%llu:%llu", path, lnum,sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2274, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial range "
"%llu:%llu", path, lnum, (unsigned long long)serial, (unsigned
long long)serial2)
2273 (unsigned long long)serial,sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2274, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial range "
"%llu:%llu", path, lnum, (unsigned long long)serial, (unsigned
long long)serial2)
2274 (unsigned long long)serial2)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2274, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: invalid serial range "
"%llu:%llu", path, lnum, (unsigned long long)serial, (unsigned
long long)serial2)
;
2275 }
2276 if (ssh_krl_revoke_cert_by_serial_range(krl,
2277 ca, serial, serial2) != 0) {
2278 fatal_f("revoke serial failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2278, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "revoke serial failed"
)
;
2279 }
2280 } else if (strncasecmp(cp, "id:", 3) == 0) {
2281 if (ca == NULL((void*)0) && !wild_ca) {
2282 fatal("revoking certificates by key ID "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2283, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "revoking certificates by key ID "
"requires specification of a CA key")
2283 "requires specification of a CA key")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2283, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "revoking certificates by key ID "
"requires specification of a CA key")
;
2284 }
2285 cp += 3;
2286 cp = cp + strspn(cp, " \t");
2287 if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
2288 fatal_f("revoke key ID failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2288, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "revoke key ID failed"
)
;
2289 } else if (strncasecmp(cp, "hash:", 5) == 0) {
2290 cp += 5;
2291 cp = cp + strspn(cp, " \t");
2292 hash_to_blob(cp, &blob, &blen, file, lnum);
2293 r = ssh_krl_revoke_key_sha256(krl, blob, blen);
2294 if (r != 0)
2295 fatal_fr(r, "revoke key failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2295, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "revoke key failed"
)
;
2296 } else {
2297 if (strncasecmp(cp, "key:", 4) == 0) {
2298 cp += 4;
2299 cp = cp + strspn(cp, " \t");
2300 was_explicit_key = 1;
2301 } else if (strncasecmp(cp, "sha1:", 5) == 0) {
2302 cp += 5;
2303 cp = cp + strspn(cp, " \t");
2304 was_sha1 = 1;
2305 } else if (strncasecmp(cp, "sha256:", 7) == 0) {
2306 cp += 7;
2307 cp = cp + strspn(cp, " \t");
2308 was_sha256 = 1;
2309 /*
2310 * Just try to process the line as a key.
2311 * Parsing will fail if it isn't.
2312 */
2313 }
2314 if ((key = sshkey_new(KEY_UNSPEC)) == NULL((void*)0))
2315 fatal("sshkey_new")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2315, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_new")
;
2316 if ((r = sshkey_read(key, &cp)) != 0)
2317 fatal_r(r, "%s:%lu: invalid key", path, lnum)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2317, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "%s:%lu: invalid key"
, path, lnum)
;
2318 if (was_explicit_key)
2319 r = ssh_krl_revoke_key_explicit(krl, key);
2320 else if (was_sha1) {
2321 if (sshkey_fingerprint_raw(key,
2322 SSH_DIGEST_SHA11, &blob, &blen) != 0) {
2323 fatal("%s:%lu: fingerprint failed",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2324, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: fingerprint failed"
, file, lnum)
2324 file, lnum)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2324, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: fingerprint failed"
, file, lnum)
;
2325 }
2326 r = ssh_krl_revoke_key_sha1(krl, blob, blen);
2327 } else if (was_sha256) {
2328 if (sshkey_fingerprint_raw(key,
2329 SSH_DIGEST_SHA2562, &blob, &blen) != 0) {
2330 fatal("%s:%lu: fingerprint failed",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2331, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: fingerprint failed"
, file, lnum)
2331 file, lnum)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2331, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s:%lu: fingerprint failed"
, file, lnum)
;
2332 }
2333 r = ssh_krl_revoke_key_sha256(krl, blob, blen);
2334 } else
2335 r = ssh_krl_revoke_key(krl, key);
2336 if (r != 0)
2337 fatal_fr(r, "revoke key failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2337, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "revoke key failed"
)
;
2338 freezero(blob, blen);
2339 blob = NULL((void*)0);
2340 blen = 0;
2341 sshkey_free(key);
2342 }
2343 }
2344 if (strcmp(path, "-") != 0)
2345 fclose(krl_spec);
2346 free(line);
2347 free(path);
2348}
2349
2350static void
2351do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
2352 unsigned long long krl_version, const char *krl_comment,
2353 int argc, char **argv)
2354{
2355 struct ssh_krl *krl;
2356 struct stat sb;
2357 struct sshkey *ca = NULL((void*)0);
2358 int i, r, wild_ca = 0;
2359 char *tmp;
2360 struct sshbuf *kbuf;
2361
2362 if (*identity_file == '\0')
2363 fatal("KRL generation requires an output file")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2363, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "KRL generation requires an output file"
)
;
2364 if (stat(identity_file, &sb) == -1) {
2365 if (errno(*__errno()) != ENOENT2)
2366 fatal("Cannot access KRL \"%s\": %s",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2367, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Cannot access KRL \"%s\": %s"
, identity_file, strerror((*__errno())))
2367 identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2367, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Cannot access KRL \"%s\": %s"
, identity_file, strerror((*__errno())))
;
2368 if (updating)
2369 fatal("KRL \"%s\" does not exist", identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2369, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "KRL \"%s\" does not exist"
, identity_file)
;
2370 }
2371 if (ca_key_path != NULL((void*)0)) {
2372 if (strcasecmp(ca_key_path, "none") == 0)
2373 wild_ca = 1;
2374 else {
2375 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
2376 if ((r = sshkey_load_public(tmp, &ca, NULL((void*)0))) != 0)
2377 fatal_r(r, "Cannot load CA public key %s", tmp)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2377, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Cannot load CA public key %s"
, tmp)
;
2378 free(tmp);
2379 }
2380 }
2381
2382 if (updating)
2383 load_krl(identity_file, &krl);
2384 else if ((krl = ssh_krl_init()) == NULL((void*)0))
2385 fatal("couldn't create KRL")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2385, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "couldn't create KRL"
)
;
2386
2387 if (krl_version != 0)
2388 ssh_krl_set_version(krl, krl_version);
2389 if (krl_comment != NULL((void*)0))
2390 ssh_krl_set_comment(krl, krl_comment);
2391
2392 for (i = 0; i < argc; i++)
2393 update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
2394
2395 if ((kbuf = sshbuf_new()) == NULL((void*)0))
2396 fatal("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2396, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
2397 if (ssh_krl_to_blob(krl, kbuf, NULL((void*)0), 0) != 0)
2398 fatal("Couldn't generate KRL")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2398, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't generate KRL"
)
;
2399 if ((r = sshbuf_write_file(identity_file, kbuf)) != 0)
2400 fatal("write %s: %s", identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2400, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "write %s: %s", identity_file
, strerror((*__errno())))
;
2401 sshbuf_free(kbuf);
2402 ssh_krl_free(krl);
2403 sshkey_free(ca);
2404}
2405
2406static void
2407do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv)
2408{
2409 int i, r, ret = 0;
2410 char *comment;
2411 struct ssh_krl *krl;
2412 struct sshkey *k;
2413
2414 if (*identity_file == '\0')
2415 fatal("KRL checking requires an input file")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2415, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "KRL checking requires an input file"
)
;
2416 load_krl(identity_file, &krl);
2417 if (print_krl)
2418 krl_dump(krl, stdout(&__sF[1]));
2419 for (i = 0; i < argc; i++) {
2420 if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
2421 fatal_r(r, "Cannot load public key %s", argv[i])sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2421, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Cannot load public key %s"
, argv[i])
;
2422 r = ssh_krl_check_key(krl, k);
2423 printf("%s%s%s%s: %s\n", argv[i],
2424 *comment ? " (" : "", comment, *comment ? ")" : "",
2425 r == 0 ? "ok" : "REVOKED");
2426 if (r != 0)
2427 ret = 1;
2428 sshkey_free(k);
2429 free(comment);
2430 }
2431 ssh_krl_free(krl);
2432 exit(ret);
2433}
2434
2435static struct sshkey *
2436load_sign_key(const char *keypath, const struct sshkey *pubkey)
2437{
2438 size_t i, slen, plen = strlen(keypath);
2439 char *privpath = xstrdup(keypath);
2440 const char *suffixes[] = { "-cert.pub", ".pub", NULL((void*)0) };
2441 struct sshkey *ret = NULL((void*)0), *privkey = NULL((void*)0);
2442 int r;
2443
2444 /*
2445 * If passed a public key filename, then try to locate the corresponding
2446 * private key. This lets us specify certificates on the command-line
2447 * and have ssh-keygen find the appropriate private key.
2448 */
2449 for (i = 0; suffixes[i]; i++) {
2450 slen = strlen(suffixes[i]);
2451 if (plen <= slen ||
2452 strcmp(privpath + plen - slen, suffixes[i]) != 0)
2453 continue;
2454 privpath[plen - slen] = '\0';
2455 debug_f("%s looks like a public key, using private key "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2456, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "%s looks like a public key, using private key "
"path %s instead", keypath, privpath)
2456 "path %s instead", keypath, privpath)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2456, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "%s looks like a public key, using private key "
"path %s instead", keypath, privpath)
;
2457 }
2458 if ((privkey = load_identity(privpath, NULL((void*)0))) == NULL((void*)0)) {
2459 error("Couldn't load identity %s", keypath)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2459, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Couldn't load identity %s"
, keypath)
;
2460 goto done;
2461 }
2462 if (!sshkey_equal_public(pubkey, privkey)) {
2463 error("Public key %s doesn't match private %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2464, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Public key %s doesn't match private %s"
, keypath, privpath)
2464 keypath, privpath)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2464, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Public key %s doesn't match private %s"
, keypath, privpath)
;
2465 goto done;
2466 }
2467 if (sshkey_is_cert(pubkey) && !sshkey_is_cert(privkey)) {
2468 /*
2469 * Graft the certificate onto the private key to make
2470 * it capable of signing.
2471 */
2472 if ((r = sshkey_to_certified(privkey)) != 0) {
2473 error_fr(r, "sshkey_to_certified")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2473, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshkey_to_certified"
)
;
2474 goto done;
2475 }
2476 if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) {
2477 error_fr(r, "sshkey_cert_copy")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2477, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshkey_cert_copy"
)
;
2478 goto done;
2479 }
2480 }
2481 /* success */
2482 ret = privkey;
2483 privkey = NULL((void*)0);
2484 done:
2485 sshkey_free(privkey);
2486 free(privpath);
2487 return ret;
2488}
2489
2490static int
2491sign_one(struct sshkey *signkey, const char *filename, int fd,
2492 const char *sig_namespace, const char *hashalg, sshsig_signer *signer,
2493 void *signer_ctx)
2494{
2495 struct sshbuf *sigbuf = NULL((void*)0), *abuf = NULL((void*)0);
2496 int r = SSH_ERR_INTERNAL_ERROR-1, wfd = -1, oerrno;
2497 char *wfile = NULL((void*)0), *asig = NULL((void*)0), *fp = NULL((void*)0);
2498 char *pin = NULL((void*)0), *prompt = NULL((void*)0);
2499
2500 if (!quiet) {
2501 if (fd == STDIN_FILENO0)
2502 fprintf(stderr(&__sF[2]), "Signing data on standard input\n");
2503 else
2504 fprintf(stderr(&__sF[2]), "Signing file %s\n", filename);
2505 }
2506 if (signer == NULL((void*)0) && sshkey_is_sk(signkey)) {
2507 if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD0x04)) {
2508 xasprintf(&prompt, "Enter PIN for %s key: ",
2509 sshkey_type(signkey));
2510 if ((pin = read_passphrase(prompt,
2511 RP_ALLOW_STDIN0x0002)) == NULL((void*)0))
2512 fatal_f("couldn't read PIN")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2512, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "couldn't read PIN"
)
;
2513 }
2514 if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD0x01)) {
2515 if ((fp = sshkey_fingerprint(signkey, fingerprint_hash,
2516 SSH_FP_DEFAULT)) == NULL((void*)0))
2517 fatal_f("fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2517, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "fingerprint failed"
)
;
2518 fprintf(stderr(&__sF[2]), "Confirm user presence for key %s %s\n",
2519 sshkey_type(signkey), fp);
2520 free(fp);
2521 }
2522 }
2523 if ((r = sshsig_sign_fd(signkey, hashalg, sk_provider, pin,
2524 fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) {
2525 error_r(r, "Signing %s failed", filename)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2525, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Signing %s failed"
, filename)
;
2526 goto out;
2527 }
2528 if ((r = sshsig_armor(sigbuf, &abuf)) != 0) {
2529 error_fr(r, "sshsig_armor")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2529, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshsig_armor")
;
2530 goto out;
2531 }
2532 if ((asig = sshbuf_dup_string(abuf)) == NULL((void*)0)) {
2533 error_f("buffer error")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2533, 1, SYSLOG_LEVEL_ERROR, ((void*)0), "buffer error")
;
2534 r = SSH_ERR_ALLOC_FAIL-2;
2535 goto out;
2536 }
2537
2538 if (fd == STDIN_FILENO0) {
2539 fputs(asig, stdout(&__sF[1]));
2540 fflush(stdout(&__sF[1]));
2541 } else {
2542 xasprintf(&wfile, "%s.sig", filename);
2543 if (confirm_overwrite(wfile)) {
2544 if ((wfd = open(wfile, O_WRONLY0x0001|O_CREAT0x0200|O_TRUNC0x0400,
2545 0666)) == -1) {
2546 oerrno = errno(*__errno());
2547 error("Cannot open %s: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2548, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot open %s: %s"
, wfile, strerror((*__errno())))
2548 wfile, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2548, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot open %s: %s"
, wfile, strerror((*__errno())))
;
2549 errno(*__errno()) = oerrno;
2550 r = SSH_ERR_SYSTEM_ERROR-24;
2551 goto out;
2552 }
2553 if (atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, wfd, asig,
2554 strlen(asig)) != strlen(asig)) {
2555 oerrno = errno(*__errno());
2556 error("Cannot write to %s: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2557, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot write to %s: %s"
, wfile, strerror((*__errno())))
2557 wfile, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2557, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot write to %s: %s"
, wfile, strerror((*__errno())))
;
2558 errno(*__errno()) = oerrno;
2559 r = SSH_ERR_SYSTEM_ERROR-24;
2560 goto out;
2561 }
2562 if (!quiet) {
2563 fprintf(stderr(&__sF[2]), "Write signature to %s\n",
2564 wfile);
2565 }
2566 }
2567 }
2568 /* success */
2569 r = 0;
2570 out:
2571 free(wfile);
2572 free(prompt);
2573 free(asig);
2574 if (pin != NULL((void*)0))
2575 freezero(pin, strlen(pin));
2576 sshbuf_free(abuf);
2577 sshbuf_free(sigbuf);
2578 if (wfd != -1)
2579 close(wfd);
2580 return r;
2581}
2582
2583static int
2584sig_process_opts(char * const *opts, size_t nopts, char **hashalgp,
2585 uint64_t *verify_timep, int *print_pubkey)
2586{
2587 size_t i;
2588 time_t now;
2589
2590 if (verify_timep != NULL((void*)0))
2591 *verify_timep = 0;
2592 if (print_pubkey != NULL((void*)0))
2593 *print_pubkey = 0;
2594 if (hashalgp != NULL((void*)0))
2595 *hashalgp = NULL((void*)0);
2596 for (i = 0; i < nopts; i++) {
2597 if (hashalgp != NULL((void*)0) &&
2598 strncasecmp(opts[i], "hashalg=", 8) == 0) {
2599 *hashalgp = xstrdup(opts[i] + 8);
2600 } else if (verify_timep &&
2601 strncasecmp(opts[i], "verify-time=", 12) == 0) {
2602 if (parse_absolute_time(opts[i] + 12,
2603 verify_timep) != 0 || *verify_timep == 0) {
2604 error("Invalid \"verify-time\" option")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2604, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Invalid \"verify-time\" option"
)
;
2605 return SSH_ERR_INVALID_ARGUMENT-10;
2606 }
2607 } else if (print_pubkey &&
2608 strcasecmp(opts[i], "print-pubkey") == 0) {
2609 *print_pubkey = 1;
2610 } else {
2611 error("Invalid option \"%s\"", opts[i])sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2611, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Invalid option \"%s\""
, opts[i])
;
2612 return SSH_ERR_INVALID_ARGUMENT-10;
2613 }
2614 }
2615 if (verify_timep && *verify_timep == 0) {
2616 if ((now = time(NULL((void*)0))) < 0) {
2617 error("Time is before epoch")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2617, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Time is before epoch"
)
;
2618 return SSH_ERR_INVALID_ARGUMENT-10;
2619 }
2620 *verify_timep = (uint64_t)now;
2621 }
2622 return 0;
2623}
2624
2625
2626static int
2627sig_sign(const char *keypath, const char *sig_namespace, int argc, char **argv,
2628 char * const *opts, size_t nopts)
2629{
2630 int i, fd = -1, r, ret = -1;
2631 int agent_fd = -1;
2632 struct sshkey *pubkey = NULL((void*)0), *privkey = NULL((void*)0), *signkey = NULL((void*)0);
2633 sshsig_signer *signer = NULL((void*)0);
2634 char *hashalg = NULL((void*)0);
2635
2636 /* Check file arguments. */
2637 for (i = 0; i < argc; i++) {
2638 if (strcmp(argv[i], "-") != 0)
2639 continue;
2640 if (i > 0 || argc > 1)
2641 fatal("Cannot sign mix of paths and standard input")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2641, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Cannot sign mix of paths and standard input"
)
;
2642 }
2643
2644 if (sig_process_opts(opts, nopts, &hashalg, NULL((void*)0), NULL((void*)0)) != 0)
2645 goto done; /* error already logged */
2646
2647 if ((r = sshkey_load_public(keypath, &pubkey, NULL((void*)0))) != 0) {
2648 error_r(r, "Couldn't load public key %s", keypath)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2648, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Couldn't load public key %s"
, keypath)
;
2649 goto done;
2650 }
2651
2652 if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
2653 debug_r(r, "Couldn't get agent socket")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2653, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "Couldn't get agent socket"
)
;
2654 else {
2655 if ((r = ssh_agent_has_key(agent_fd, pubkey)) == 0)
2656 signer = agent_signer;
2657 else
2658 debug_r(r, "Couldn't find key in agent")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2658, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "Couldn't find key in agent"
)
;
2659 }
2660
2661 if (signer == NULL((void*)0)) {
2662 /* Not using agent - try to load private key */
2663 if ((privkey = load_sign_key(keypath, pubkey)) == NULL((void*)0))
2664 goto done;
2665 signkey = privkey;
2666 } else {
2667 /* Will use key in agent */
2668 signkey = pubkey;
2669 }
2670
2671 if (argc == 0) {
2672 if ((r = sign_one(signkey, "(stdin)", STDIN_FILENO0,
2673 sig_namespace, hashalg, signer, &agent_fd)) != 0)
2674 goto done;
2675 } else {
2676 for (i = 0; i < argc; i++) {
2677 if (strcmp(argv[i], "-") == 0)
2678 fd = STDIN_FILENO0;
2679 else if ((fd = open(argv[i], O_RDONLY0x0000)) == -1) {
2680 error("Cannot open %s for signing: %s",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2681, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot open %s for signing: %s"
, argv[i], strerror((*__errno())))
2681 argv[i], strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2681, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot open %s for signing: %s"
, argv[i], strerror((*__errno())))
;
2682 goto done;
2683 }
2684 if ((r = sign_one(signkey, argv[i], fd, sig_namespace,
2685 hashalg, signer, &agent_fd)) != 0)
2686 goto done;
2687 if (fd != STDIN_FILENO0)
2688 close(fd);
2689 fd = -1;
2690 }
2691 }
2692
2693 ret = 0;
2694done:
2695 if (fd != -1 && fd != STDIN_FILENO0)
2696 close(fd);
2697 sshkey_free(pubkey);
2698 sshkey_free(privkey);
2699 free(hashalg);
2700 return ret;
2701}
2702
2703static int
2704sig_verify(const char *signature, const char *sig_namespace,
2705 const char *principal, const char *allowed_keys, const char *revoked_keys,
2706 char * const *opts, size_t nopts)
2707{
2708 int r, ret = -1;
2709 int print_pubkey = 0;
2710 struct sshbuf *sigbuf = NULL((void*)0), *abuf = NULL((void*)0);
2711 struct sshkey *sign_key = NULL((void*)0);
2712 char *fp = NULL((void*)0);
2713 struct sshkey_sig_details *sig_details = NULL((void*)0);
2714 uint64_t verify_time = 0;
2715
2716 if (sig_process_opts(opts, nopts, NULL((void*)0), &verify_time,
2717 &print_pubkey) != 0)
2718 goto done; /* error already logged */
2719
2720 memset(&sig_details, 0, sizeof(sig_details));
2721 if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
2722 error_r(r, "Couldn't read signature file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2722, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Couldn't read signature file"
)
;
2723 goto done;
2724 }
2725
2726 if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
2727 error_fr(r, "sshsig_armor")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2727, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshsig_armor")
;
2728 goto done;
2729 }
2730 if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO0, sig_namespace,
2731 &sign_key, &sig_details)) != 0)
2732 goto done; /* sshsig_verify() prints error */
2733
2734 if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
2735 SSH_FP_DEFAULT)) == NULL((void*)0))
2736 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2736, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint failed"
)
;
2737 debug("Valid (unverified) signature from key %s", fp)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2737, 0, SYSLOG_LEVEL_DEBUG1, ((void*)0), "Valid (unverified) signature from key %s"
, fp)
;
2738 if (sig_details != NULL((void*)0)) {
2739 debug2_f("signature details: counter = %u, flags = 0x%02x",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2740, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "signature details: counter = %u, flags = 0x%02x"
, sig_details->sk_counter, sig_details->sk_flags)
2740 sig_details->sk_counter, sig_details->sk_flags)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2740, 1, SYSLOG_LEVEL_DEBUG2, ((void*)0), "signature details: counter = %u, flags = 0x%02x"
, sig_details->sk_counter, sig_details->sk_flags)
;
2741 }
2742 free(fp);
2743 fp = NULL((void*)0);
2744
2745 if (revoked_keys != NULL((void*)0)) {
2746 if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) {
2747 debug3_fr(r, "sshkey_check_revoked")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2747, 1, SYSLOG_LEVEL_DEBUG3, ssh_err(r), "sshkey_check_revoked"
)
;
2748 goto done;
2749 }
2750 }
2751
2752 if (allowed_keys != NULL((void*)0) && (r = sshsig_check_allowed_keys(allowed_keys,
2753 sign_key, principal, sig_namespace, verify_time)) != 0) {
2754 debug3_fr(r, "sshsig_check_allowed_keys")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2754, 1, SYSLOG_LEVEL_DEBUG3, ssh_err(r), "sshsig_check_allowed_keys"
)
;
2755 goto done;
2756 }
2757 /* success */
2758 ret = 0;
2759done:
2760 if (!quiet) {
2761 if (ret == 0) {
2762 if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
2763 SSH_FP_DEFAULT)) == NULL((void*)0))
2764 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2764, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint failed"
)
;
2765 if (principal == NULL((void*)0)) {
2766 printf("Good \"%s\" signature with %s key %s\n",
2767 sig_namespace, sshkey_type(sign_key), fp);
2768
2769 } else {
2770 printf("Good \"%s\" signature for %s with %s key %s\n",
2771 sig_namespace, principal,
2772 sshkey_type(sign_key), fp);
2773 }
2774 } else {
2775 printf("Could not verify signature.\n");
2776 }
2777 }
2778 /* Print the signature key if requested */
2779 if (ret == 0 && print_pubkey && sign_key != NULL((void*)0)) {
2780 if ((r = sshkey_write(sign_key, stdout(&__sF[1]))) == 0)
2781 fputc('\n', stdout(&__sF[1]));
2782 else {
2783 error_r(r, "Could not print public key.\n")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2783, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Could not print public key.\n"
)
;
2784 ret = -1;
2785 }
2786 }
2787 sshbuf_free(sigbuf);
2788 sshbuf_free(abuf);
2789 sshkey_free(sign_key);
2790 sshkey_sig_details_free(sig_details);
2791 free(fp);
2792 return ret;
2793}
2794
2795static int
2796sig_find_principals(const char *signature, const char *allowed_keys,
2797 char * const *opts, size_t nopts)
2798{
2799 int r, ret = -1;
2800 struct sshbuf *sigbuf = NULL((void*)0), *abuf = NULL((void*)0);
2801 struct sshkey *sign_key = NULL((void*)0);
2802 char *principals = NULL((void*)0), *cp, *tmp;
2803 uint64_t verify_time = 0;
2804
2805 if (sig_process_opts(opts, nopts, NULL((void*)0), &verify_time, NULL((void*)0)) != 0)
2806 goto done; /* error already logged */
2807
2808 if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
2809 error_r(r, "Couldn't read signature file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2809, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Couldn't read signature file"
)
;
2810 goto done;
2811 }
2812 if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
2813 error_fr(r, "sshsig_armor")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2813, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshsig_armor")
;
2814 goto done;
2815 }
2816 if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) {
2817 error_fr(r, "sshsig_get_pubkey")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2817, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshsig_get_pubkey"
)
;
2818 goto done;
2819 }
2820 if ((r = sshsig_find_principals(allowed_keys, sign_key,
2821 verify_time, &principals)) != 0) {
2822 if (r != SSH_ERR_KEY_NOT_FOUND-46)
2823 error_fr(r, "sshsig_find_principal")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2823, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "sshsig_find_principal"
)
;
2824 goto done;
2825 }
2826 ret = 0;
2827done:
2828 if (ret == 0 ) {
2829 /* Emit matching principals one per line */
2830 tmp = principals;
2831 while ((cp = strsep(&tmp, ",")) != NULL((void*)0) && *cp != '\0')
2832 puts(cp);
2833 } else {
2834 fprintf(stderr(&__sF[2]), "No principal matched.\n");
2835 }
2836 sshbuf_free(sigbuf);
2837 sshbuf_free(abuf);
2838 sshkey_free(sign_key);
2839 free(principals);
2840 return ret;
2841}
2842
2843static int
2844sig_match_principals(const char *allowed_keys, char *principal,
2845 char * const *opts, size_t nopts)
2846{
2847 int r;
2848 char **principals = NULL((void*)0);
2849 size_t i, nprincipals = 0;
2850
2851 if ((r = sig_process_opts(opts, nopts, NULL((void*)0), NULL((void*)0), NULL((void*)0))) != 0)
2852 return r; /* error already logged */
2853
2854 if ((r = sshsig_match_principals(allowed_keys, principal,
2855 &principals, &nprincipals)) != 0) {
2856 debug_f("match: %s", ssh_err(r))sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2856, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "match: %s", ssh_err
(r))
;
2857 fprintf(stderr(&__sF[2]), "No principal matched.\n");
2858 return r;
2859 }
2860 for (i = 0; i < nprincipals; i++) {
2861 printf("%s\n", principals[i]);
2862 free(principals[i]);
2863 }
2864 free(principals);
2865
2866 return 0;
2867}
2868
2869static void
2870do_moduli_gen(const char *out_file, char **opts, size_t nopts)
2871{
2872#ifdef WITH_OPENSSL1
2873 /* Moduli generation/screening */
2874 u_int32_t memory = 0;
2875 BIGNUM *start = NULL((void*)0);
2876 int moduli_bits = 0;
2877 FILE *out;
2878 size_t i;
2879 const char *errstr;
2880
2881 /* Parse options */
2882 for (i = 0; i < nopts; i++) {
2883 if (strncmp(opts[i], "memory=", 7) == 0) {
2884 memory = (u_int32_t)strtonum(opts[i]+7, 1,
2885 UINT_MAX(2147483647 *2U +1U), &errstr);
2886 if (errstr) {
2887 fatal("Memory limit is %s: %s",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2888, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Memory limit is %s: %s"
, errstr, opts[i]+7)
2888 errstr, opts[i]+7)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2888, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Memory limit is %s: %s"
, errstr, opts[i]+7)
;
2889 }
2890 } else if (strncmp(opts[i], "start=", 6) == 0) {
2891 /* XXX - also compare length against bits */
2892 if (BN_hex2bn(&start, opts[i]+6) == 0)
2893 fatal("Invalid start point.")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2893, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid start point."
)
;
2894 } else if (strncmp(opts[i], "bits=", 5) == 0) {
2895 moduli_bits = (int)strtonum(opts[i]+5, 1,
2896 INT_MAX2147483647, &errstr);
2897 if (errstr) {
2898 fatal("Invalid number: %s (%s)",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2899, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid number: %s (%s)"
, opts[i]+12, errstr)
2899 opts[i]+12, errstr)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2899, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid number: %s (%s)"
, opts[i]+12, errstr)
;
2900 }
2901 } else {
2902 fatal("Option \"%s\" is unsupported for moduli "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2903, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for moduli "
"generation", opts[i])
2903 "generation", opts[i])sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2903, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for moduli "
"generation", opts[i])
;
2904 }
2905 }
2906
2907 if ((out = fopen(out_file, "w")) == NULL((void*)0)) {
2908 fatal("Couldn't open modulus candidate file \"%s\": %s",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2909, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't open modulus candidate file \"%s\": %s"
, out_file, strerror((*__errno())))
2909 out_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2909, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't open modulus candidate file \"%s\": %s"
, out_file, strerror((*__errno())))
;
2910 }
2911 setvbuf(out, NULL((void*)0), _IOLBF1, 0);
2912
2913 if (moduli_bits == 0)
2914 moduli_bits = DEFAULT_BITS3072;
2915 if (gen_candidates(out, memory, moduli_bits, start) != 0)
2916 fatal("modulus candidate generation failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2916, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "modulus candidate generation failed"
)
;
2917#else /* WITH_OPENSSL */
2918 fatal("Moduli generation is not supported")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2918, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Moduli generation is not supported"
)
;
2919#endif /* WITH_OPENSSL */
2920}
2921
2922static void
2923do_moduli_screen(const char *out_file, char **opts, size_t nopts)
2924{
2925#ifdef WITH_OPENSSL1
2926 /* Moduli generation/screening */
2927 char *checkpoint = NULL((void*)0);
2928 u_int32_t generator_wanted = 0;
2929 unsigned long start_lineno = 0, lines_to_process = 0;
2930 int prime_tests = 0;
2931 FILE *out, *in = stdin(&__sF[0]);
2932 size_t i;
2933 const char *errstr;
2934
2935 /* Parse options */
2936 for (i = 0; i < nopts; i++) {
2937 if (strncmp(opts[i], "lines=", 6) == 0) {
2938 lines_to_process = strtoul(opts[i]+6, NULL((void*)0), 10);
2939 } else if (strncmp(opts[i], "start-line=", 11) == 0) {
2940 start_lineno = strtoul(opts[i]+11, NULL((void*)0), 10);
2941 } else if (strncmp(opts[i], "checkpoint=", 11) == 0) {
2942 checkpoint = xstrdup(opts[i]+11);
2943 } else if (strncmp(opts[i], "generator=", 10) == 0) {
2944 generator_wanted = (u_int32_t)strtonum(
2945 opts[i]+10, 1, UINT_MAX(2147483647 *2U +1U), &errstr);
2946 if (errstr != NULL((void*)0)) {
2947 fatal("Generator invalid: %s (%s)",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2948, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Generator invalid: %s (%s)"
, opts[i]+10, errstr)
2948 opts[i]+10, errstr)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2948, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Generator invalid: %s (%s)"
, opts[i]+10, errstr)
;
2949 }
2950 } else if (strncmp(opts[i], "prime-tests=", 12) == 0) {
2951 prime_tests = (int)strtonum(opts[i]+12, 1,
2952 INT_MAX2147483647, &errstr);
2953 if (errstr) {
2954 fatal("Invalid number: %s (%s)",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2955, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid number: %s (%s)"
, opts[i]+12, errstr)
2955 opts[i]+12, errstr)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2955, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid number: %s (%s)"
, opts[i]+12, errstr)
;
2956 }
2957 } else {
2958 fatal("Option \"%s\" is unsupported for moduli "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2959, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for moduli "
"screening", opts[i])
2959 "screening", opts[i])sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2959, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for moduli "
"screening", opts[i])
;
2960 }
2961 }
2962
2963 if (have_identity && strcmp(identity_file, "-") != 0) {
2964 if ((in = fopen(identity_file, "r")) == NULL((void*)0)) {
2965 fatal("Couldn't open modulus candidate "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2967, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't open modulus candidate "
"file \"%s\": %s", identity_file, strerror((*__errno())))
2966 "file \"%s\": %s", identity_file,sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2967, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't open modulus candidate "
"file \"%s\": %s", identity_file, strerror((*__errno())))
2967 strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2967, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't open modulus candidate "
"file \"%s\": %s", identity_file, strerror((*__errno())))
;
2968 }
2969 }
2970
2971 if ((out = fopen(out_file, "a")) == NULL((void*)0)) {
2972 fatal("Couldn't open moduli file \"%s\": %s",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2973, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't open moduli file \"%s\": %s"
, out_file, strerror((*__errno())))
2973 out_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2973, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Couldn't open moduli file \"%s\": %s"
, out_file, strerror((*__errno())))
;
2974 }
2975 setvbuf(out, NULL((void*)0), _IOLBF1, 0);
2976 if (prime_test(in, out, prime_tests == 0 ? 100 : prime_tests,
2977 generator_wanted, checkpoint,
2978 start_lineno, lines_to_process) != 0)
2979 fatal("modulus screening failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2979, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "modulus screening failed"
)
;
2980#else /* WITH_OPENSSL */
2981 fatal("Moduli screening is not supported")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 2981, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Moduli screening is not supported"
)
;
2982#endif /* WITH_OPENSSL */
2983}
2984
2985static char *
2986private_key_passphrase(void)
2987{
2988 char *passphrase1, *passphrase2;
2989
2990 /* Ask for a passphrase (twice). */
2991 if (identity_passphrase)
2992 passphrase1 = xstrdup(identity_passphrase);
2993 else if (identity_new_passphrase)
2994 passphrase1 = xstrdup(identity_new_passphrase);
2995 else {
2996passphrase_again:
2997 passphrase1 =
2998 read_passphrase("Enter passphrase (empty for no "
2999 "passphrase): ", RP_ALLOW_STDIN0x0002);
3000 passphrase2 = read_passphrase("Enter same passphrase again: ",
3001 RP_ALLOW_STDIN0x0002);
3002 if (strcmp(passphrase1, passphrase2) != 0) {
3003 /*
3004 * The passphrases do not match. Clear them and
3005 * retry.
3006 */
3007 freezero(passphrase1, strlen(passphrase1));
3008 freezero(passphrase2, strlen(passphrase2));
3009 printf("Passphrases do not match. Try again.\n");
3010 goto passphrase_again;
3011 }
3012 /* Clear the other copy of the passphrase. */
3013 freezero(passphrase2, strlen(passphrase2));
3014 }
3015 return passphrase1;
3016}
3017
3018static char *
3019sk_suffix(const char *application, const uint8_t *user, size_t userlen)
3020{
3021 char *ret, *cp;
3022 size_t slen, i;
3023
3024 /* Trim off URL-like preamble */
3025 if (strncmp(application, "ssh://", 6) == 0)
3026 ret = xstrdup(application + 6);
3027 else if (strncmp(application, "ssh:", 4) == 0)
3028 ret = xstrdup(application + 4);
3029 else
3030 ret = xstrdup(application);
3031
3032 /* Count trailing zeros in user */
3033 for (i = 0; i < userlen; i++) {
3034 if (user[userlen - i - 1] != 0)
3035 break;
3036 }
3037 if (i >= userlen)
3038 return ret; /* user-id was default all-zeros */
3039
3040 /* Append user-id, escaping non-UTF-8 characters */
3041 slen = userlen - i;
3042 if (asmprintf(&cp, INT_MAX2147483647, NULL((void*)0), "%.*s", (int)slen, user) == -1)
3043 fatal_f("asmprintf failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3043, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "asmprintf failed"
)
;
3044 /* Don't emit a user-id that contains path or control characters */
3045 if (strchr(cp, '/') != NULL((void*)0) || strstr(cp, "..") != NULL((void*)0) ||
3046 strchr(cp, '\\') != NULL((void*)0)) {
3047 free(cp);
3048 cp = tohex(user, slen);
3049 }
3050 xextendf(&ret, "_", "%s", cp);
3051 free(cp);
3052 return ret;
3053}
3054
3055static int
3056do_download_sk(const char *skprovider, const char *device)
3057{
3058 struct sshsk_resident_key **srks;
3059 size_t nsrks, i;
3060 int r, ret = -1;
3061 char *fp, *pin = NULL((void*)0), *pass = NULL((void*)0), *path, *pubpath;
3062 const char *ext;
3063 struct sshkey *key;
3064
3065 if (skprovider == NULL((void*)0))
3066 fatal("Cannot download keys without provider")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3066, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Cannot download keys without provider"
)
;
3067
3068 pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN0x0002);
3069 if (!quiet) {
3070 printf("You may need to touch your authenticator "
3071 "to authorize key download.\n");
3072 }
3073 if ((r = sshsk_load_resident(skprovider, device, pin, 0,
3074 &srks, &nsrks)) != 0) {
3075 if (pin != NULL((void*)0))
3076 freezero(pin, strlen(pin));
3077 error_r(r, "Unable to load resident keys")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3077, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Unable to load resident keys"
)
;
3078 return -1;
3079 }
3080 if (nsrks == 0)
3081 logit("No keys to download")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3081, 0, SYSLOG_LEVEL_INFO, ((void*)0), "No keys to download"
)
;
3082 if (pin != NULL((void*)0))
3083 freezero(pin, strlen(pin));
3084
3085 for (i = 0; i < nsrks; i++) {
3086 key = srks[i]->key;
3087 if (key->type != KEY_ECDSA_SK && key->type != KEY_ED25519_SK) {
3088 error("Unsupported key type %s (%d)",sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3089, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unsupported key type %s (%d)"
, sshkey_type(key), key->type)
3089 sshkey_type(key), key->type)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3089, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unsupported key type %s (%d)"
, sshkey_type(key), key->type)
;
3090 continue;
3091 }
3092 if ((fp = sshkey_fingerprint(key, fingerprint_hash,
3093 SSH_FP_DEFAULT)) == NULL((void*)0))
3094 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3094, 1, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint failed"
)
;
3095 debug_f("key %zu: %s %s %s (flags 0x%02x)", i,sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3096, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "key %zu: %s %s %s (flags 0x%02x)"
, i, sshkey_type(key), fp, key->sk_application, key->sk_flags
)
3096 sshkey_type(key), fp, key->sk_application, key->sk_flags)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3096, 1, SYSLOG_LEVEL_DEBUG1, ((void*)0), "key %zu: %s %s %s (flags 0x%02x)"
, i, sshkey_type(key), fp, key->sk_application, key->sk_flags
)
;
3097 ext = sk_suffix(key->sk_application,
3098 srks[i]->user_id, srks[i]->user_id_len);
3099 xasprintf(&path, "id_%s_rk%s%s",
3100 key->type == KEY_ECDSA_SK ? "ecdsa_sk" : "ed25519_sk",
3101 *ext == '\0' ? "" : "_", ext);
3102
3103 /* If the file already exists, ask the user to confirm. */
3104 if (!confirm_overwrite(path)) {
3105 free(path);
3106 break;
3107 }
3108
3109 /* Save the key with the application string as the comment */
3110 if (pass == NULL((void*)0))
3111 pass = private_key_passphrase();
3112 if ((r = sshkey_save_private(key, path, pass,
3113 key->sk_application, private_key_format,
3114 openssh_format_cipher, rounds)) != 0) {
3115 error_r(r, "Saving key \"%s\" failed", path)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3115, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Saving key \"%s\" failed"
, path)
;
3116 free(path);
3117 break;
3118 }
3119 if (!quiet) {
3120 printf("Saved %s key%s%s to %s\n", sshkey_type(key),
3121 *ext != '\0' ? " " : "",
3122 *ext != '\0' ? key->sk_application : "",
3123 path);
3124 }
3125
3126 /* Save public key too */
3127 xasprintf(&pubpath, "%s.pub", path);
3128 free(path);
3129 if ((r = sshkey_save_public(key, pubpath,
3130 key->sk_application)) != 0) {
3131 error_r(r, "Saving public key \"%s\" failed", pubpath)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3131, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Saving public key \"%s\" failed"
, pubpath)
;
3132 free(pubpath);
3133 break;
3134 }
3135 free(pubpath);
3136 }
3137
3138 if (i >= nsrks)
3139 ret = 0; /* success */
3140 if (pass != NULL((void*)0))
3141 freezero(pass, strlen(pass));
3142 sshsk_free_resident_keys(srks, nsrks);
3143 return ret;
3144}
3145
3146static void
3147save_attestation(struct sshbuf *attest, const char *path)
3148{
3149 mode_t omask;
3150 int r;
3151
3152 if (path == NULL((void*)0))
3153 return; /* nothing to do */
3154 if (attest == NULL((void*)0) || sshbuf_len(attest) == 0)
3155 fatal("Enrollment did not return attestation data")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3155, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Enrollment did not return attestation data"
)
;
3156 omask = umask(077);
3157 r = sshbuf_write_file(path, attest);
3158 umask(omask);
3159 if (r != 0)
3160 fatal_r(r, "Unable to write attestation data \"%s\"", path)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3160, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to write attestation data \"%s\""
, path)
;
3161 if (!quiet)
3162 printf("Your FIDO attestation certificate has been saved in "
3163 "%s\n", path);
3164}
3165
3166static void
3167usage(void)
3168{
3169 fprintf(stderr(&__sF[2]),
3170 "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n"
3171 " [-m format] [-N new_passphrase] [-O option]\n"
3172 " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n"
3173 " [-w provider] [-Z cipher]\n"
3174 " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n"
3175 " [-P old_passphrase] [-Z cipher]\n"
3176#ifdef WITH_OPENSSL1
3177 " ssh-keygen -i [-f input_keyfile] [-m key_format]\n"
3178 " ssh-keygen -e [-f input_keyfile] [-m key_format]\n"
3179#endif
3180 " ssh-keygen -y [-f input_keyfile]\n"
3181 " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n"
3182 " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n"
3183 " ssh-keygen -B [-f input_keyfile]\n");
3184#ifdef ENABLE_PKCS111
3185 fprintf(stderr(&__sF[2]),
3186 " ssh-keygen -D pkcs11\n");
3187#endif
3188 fprintf(stderr(&__sF[2]),
3189 " ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n"
3190 " ssh-keygen -H [-f known_hosts_file]\n"
3191 " ssh-keygen -K [-a rounds] [-w provider]\n"
3192 " ssh-keygen -R hostname [-f known_hosts_file]\n"
3193 " ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
3194#ifdef WITH_OPENSSL1
3195 " ssh-keygen -M generate [-O option] output_file\n"
3196 " ssh-keygen -M screen [-f input_file] [-O option] output_file\n"
3197#endif
3198 " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
3199 " [-n principals] [-O option] [-V validity_interval]\n"
3200 " [-z serial_number] file ...\n"
3201 " ssh-keygen -L [-f input_keyfile]\n"
3202 " ssh-keygen -A [-a rounds] [-f prefix_path]\n"
3203 " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
3204 " file ...\n"
3205 " ssh-keygen -Q [-l] -f krl_file [file ...]\n"
3206 " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n"
3207 " ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file\n"
3208 " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n"
3209 " ssh-keygen -Y sign -f key_file -n namespace file [-O option] ...\n"
3210 " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n"
3211 " -n namespace -s signature_file [-r krl_file] [-O option]\n");
3212 exit(1);
3213}
3214
3215/*
3216 * Main program for key management.
3217 */
3218int
3219main(int argc, char **argv)
3220{
3221 char comment[1024], *passphrase;
3222 char *rr_hostname = NULL((void*)0), *ep, *fp, *ra;
3223 struct sshkey *private, *public;
3224 struct passwd *pw;
3225 int r, opt, type;
3226 int change_passphrase = 0, change_comment = 0, show_cert = 0;
3227 int find_host = 0, delete_host = 0, hash_hosts = 0;
3228 int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
3229 int prefer_agent = 0, convert_to = 0, convert_from = 0;
3230 int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
3231 int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0;
3232 unsigned long long cert_serial = 0;
3233 char *identity_comment = NULL((void*)0), *ca_key_path = NULL((void*)0), **opts = NULL((void*)0);
3234 char *sk_application = NULL((void*)0), *sk_device = NULL((void*)0), *sk_user = NULL((void*)0);
3235 char *sk_attestation_path = NULL((void*)0);
3236 struct sshbuf *challenge = NULL((void*)0), *attest = NULL((void*)0);
3237 size_t i, nopts = 0;
3238 u_int32_t bits = 0;
3239 uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD0x01;
3240 const char *errstr;
3241 int log_level = SYSLOG_LEVEL_INFO;
3242 char *sign_op = NULL((void*)0);
3243
3244 extern int optind;
3245 extern char *optarg;
3246
3247 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
3248 sanitise_stdfd();
3249
3250#ifdef WITH_OPENSSL1
3251 OpenSSL_add_all_algorithms()OPENSSL_add_all_algorithms_noconf();
3252#endif
3253 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
3254
3255 setlocale(LC_CTYPE2, "");
3256
3257 /* we need this for the home * directory. */
3258 pw = getpwuid(getuid());
3259 if (!pw)
3260 fatal("No user exists for uid %lu", (u_long)getuid())sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3260, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "No user exists for uid %lu"
, (u_long)getuid())
;
3261 pw = pwcopy(pw);
3262 if (gethostname(hostname, sizeof(hostname)) == -1)
3263 fatal("gethostname: %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3263, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "gethostname: %s",
strerror((*__errno())))
;
3264
3265 sk_provider = getenv("SSH_SK_PROVIDER");
3266
3267 /* Remaining characters: dGjJSTWx */
3268 while ((opt = getopt(argc, argv, "ABHKLQUXceghiklopquvy"
3269 "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
3270 "a:b:f:g:m:n:r:s:t:w:z:")) != -1) {
3271 switch (opt) {
3272 case 'A':
3273 gen_all_hostkeys = 1;
3274 break;
3275 case 'b':
3276 bits = (u_int32_t)strtonum(optarg, 1, UINT32_MAX0xffffffffU,
3277 &errstr);
3278 if (errstr)
3279 fatal("Bits has bad value %s (%s)",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3280, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Bits has bad value %s (%s)"
, optarg, errstr)
3280 optarg, errstr)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3280, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Bits has bad value %s (%s)"
, optarg, errstr)
;
3281 break;
3282 case 'E':
3283 fingerprint_hash = ssh_digest_alg_by_name(optarg);
3284 if (fingerprint_hash == -1)
3285 fatal("Invalid hash algorithm \"%s\"", optarg)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3285, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid hash algorithm \"%s\""
, optarg)
;
3286 break;
3287 case 'F':
3288 find_host = 1;
3289 rr_hostname = optarg;
3290 break;
3291 case 'H':
3292 hash_hosts = 1;
3293 break;
3294 case 'I':
3295 cert_key_id = optarg;
3296 break;
3297 case 'R':
3298 delete_host = 1;
3299 rr_hostname = optarg;
3300 break;
3301 case 'L':
3302 show_cert = 1;
3303 break;
3304 case 'l':
3305 print_fingerprint = 1;
3306 break;
3307 case 'B':
3308 print_bubblebabble = 1;
3309 break;
3310 case 'm':
3311 if (strcasecmp(optarg, "RFC4716") == 0 ||
3312 strcasecmp(optarg, "ssh2") == 0) {
3313 convert_format = FMT_RFC4716;
3314 break;
3315 }
3316 if (strcasecmp(optarg, "PKCS8") == 0) {
3317 convert_format = FMT_PKCS8;
3318 private_key_format = SSHKEY_PRIVATE_PKCS8;
3319 break;
3320 }
3321 if (strcasecmp(optarg, "PEM") == 0) {
3322 convert_format = FMT_PEM;
3323 private_key_format = SSHKEY_PRIVATE_PEM;
3324 break;
3325 }
3326 fatal("Unsupported conversion format \"%s\"", optarg)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3326, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Unsupported conversion format \"%s\""
, optarg)
;
3327 case 'n':
3328 cert_principals = optarg;
3329 break;
3330 case 'o':
3331 /* no-op; new format is already the default */
3332 break;
3333 case 'p':
3334 change_passphrase = 1;
3335 break;
3336 case 'c':
3337 change_comment = 1;
3338 break;
3339 case 'f':
3340 if (strlcpy(identity_file, optarg,
3341 sizeof(identity_file)) >= sizeof(identity_file))
3342 fatal("Identity filename too long")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3342, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Identity filename too long"
)
;
3343 have_identity = 1;
3344 break;
3345 case 'g':
3346 print_generic = 1;
3347 break;
3348 case 'K':
3349 download_sk = 1;
3350 break;
3351 case 'P':
3352 identity_passphrase = optarg;
3353 break;
3354 case 'N':
3355 identity_new_passphrase = optarg;
3356 break;
3357 case 'Q':
3358 check_krl = 1;
3359 break;
3360 case 'O':
3361 opts = xrecallocarray(opts, nopts, nopts + 1,
3362 sizeof(*opts));
3363 opts[nopts++] = xstrdup(optarg);
3364 break;
3365 case 'Z':
3366 openssh_format_cipher = optarg;
3367 if (cipher_by_name(openssh_format_cipher) == NULL((void*)0))
3368 fatal("Invalid OpenSSH-format cipher '%s'",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3369, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid OpenSSH-format cipher '%s'"
, openssh_format_cipher)
3369 openssh_format_cipher)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3369, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid OpenSSH-format cipher '%s'"
, openssh_format_cipher)
;
3370 break;
3371 case 'C':
3372 identity_comment = optarg;
3373 break;
3374 case 'q':
3375 quiet = 1;
3376 break;
3377 case 'e':
3378 /* export key */
3379 convert_to = 1;
3380 break;
3381 case 'h':
3382 cert_key_type = SSH2_CERT_TYPE_HOST2;
3383 certflags_flags = 0;
3384 break;
3385 case 'k':
3386 gen_krl = 1;
3387 break;
3388 case 'i':
3389 case 'X':
3390 /* import key */
3391 convert_from = 1;
3392 break;
3393 case 'y':
3394 print_public = 1;
3395 break;
3396 case 's':
3397 ca_key_path = optarg;
3398 break;
3399 case 't':
3400 key_type_name = optarg;
3401 break;
3402 case 'D':
3403 pkcs11provider = optarg;
3404 break;
3405 case 'U':
3406 prefer_agent = 1;
3407 break;
3408 case 'u':
3409 update_krl = 1;
3410 break;
3411 case 'v':
3412 if (log_level == SYSLOG_LEVEL_INFO)
3413 log_level = SYSLOG_LEVEL_DEBUG1;
3414 else {
3415 if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
3416 log_level < SYSLOG_LEVEL_DEBUG3)
3417 log_level++;
3418 }
3419 break;
3420 case 'r':
3421 rr_hostname = optarg;
3422 break;
3423 case 'a':
3424 rounds = (int)strtonum(optarg, 1, INT_MAX2147483647, &errstr);
3425 if (errstr)
3426 fatal("Invalid number: %s (%s)",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3427, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid number: %s (%s)"
, optarg, errstr)
3427 optarg, errstr)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3427, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid number: %s (%s)"
, optarg, errstr)
;
3428 break;
3429 case 'V':
3430 parse_cert_times(optarg);
3431 break;
3432 case 'Y':
3433 sign_op = optarg;
3434 break;
3435 case 'w':
3436 sk_provider = optarg;
3437 break;
3438 case 'z':
3439 errno(*__errno()) = 0;
3440 if (*optarg == '+') {
3441 cert_serial_autoinc = 1;
3442 optarg++;
3443 }
3444 cert_serial = strtoull(optarg, &ep, 10);
3445 if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
3446 (errno(*__errno()) == ERANGE34 && cert_serial == ULLONG_MAX(9223372036854775807LL*2ULL+1ULL)))
3447 fatal("Invalid serial number \"%s\"", optarg)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3447, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Invalid serial number \"%s\""
, optarg)
;
3448 break;
3449 case 'M':
3450 if (strcmp(optarg, "generate") == 0)
3451 do_gen_candidates = 1;
3452 else if (strcmp(optarg, "screen") == 0)
3453 do_screen_candidates = 1;
3454 else
3455 fatal("Unsupported moduli option %s", optarg)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3455, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Unsupported moduli option %s"
, optarg)
;
3456 break;
3457 case '?':
3458 default:
3459 usage();
3460 }
3461 }
3462
3463 if (sk_provider == NULL((void*)0))
3464 sk_provider = "internal";
3465
3466 /* reinit */
3467 log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
3468
3469 argv += optind;
3470 argc -= optind;
3471
3472 if (sign_op != NULL((void*)0)) {
3473 if (strncmp(sign_op, "find-principals", 15) == 0) {
3474 if (ca_key_path == NULL((void*)0)) {
3475 error("Too few arguments for find-principals:"sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3476, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for find-principals:"
"missing signature file")
3476 "missing signature file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3476, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for find-principals:"
"missing signature file")
;
3477 exit(1);
3478 }
3479 if (!have_identity) {
3480 error("Too few arguments for find-principals:"sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3481, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for find-principals:"
"missing allowed keys file")
3481 "missing allowed keys file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3481, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for find-principals:"
"missing allowed keys file")
;
3482 exit(1);
3483 }
3484 return sig_find_principals(ca_key_path, identity_file,
3485 opts, nopts);
3486 } else if (strncmp(sign_op, "match-principals", 16) == 0) {
3487 if (!have_identity) {
3488 error("Too few arguments for match-principals:"sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3489, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for match-principals:"
"missing allowed keys file")
3489 "missing allowed keys file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3489, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for match-principals:"
"missing allowed keys file")
;
3490 exit(1);
3491 }
3492 if (cert_key_id == NULL((void*)0)) {
3493 error("Too few arguments for match-principals: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3494, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for match-principals: "
"missing principal ID")
3494 "missing principal ID")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3494, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for match-principals: "
"missing principal ID")
;
3495 exit(1);
3496 }
3497 return sig_match_principals(identity_file, cert_key_id,
3498 opts, nopts);
3499 } else if (strncmp(sign_op, "sign", 4) == 0) {
3500 /* NB. cert_principals is actually namespace, via -n */
3501 if (cert_principals == NULL((void*)0) ||
3502 *cert_principals == '\0') {
3503 error("Too few arguments for sign: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3504, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for sign: "
"missing namespace")
3504 "missing namespace")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3504, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for sign: "
"missing namespace")
;
3505 exit(1);
3506 }
3507 if (!have_identity) {
3508 error("Too few arguments for sign: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3509, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for sign: "
"missing key")
3509 "missing key")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3509, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for sign: "
"missing key")
;
3510 exit(1);
3511 }
3512 return sig_sign(identity_file, cert_principals,
3513 argc, argv, opts, nopts);
3514 } else if (strncmp(sign_op, "check-novalidate", 16) == 0) {
3515 if (ca_key_path == NULL((void*)0)) {
3516 error("Too few arguments for check-novalidate: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3517, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for check-novalidate: "
"missing signature file")
3517 "missing signature file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3517, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for check-novalidate: "
"missing signature file")
;
3518 exit(1);
3519 }
3520 return sig_verify(ca_key_path, cert_principals,
3521 NULL((void*)0), NULL((void*)0), NULL((void*)0), opts, nopts);
3522 } else if (strncmp(sign_op, "verify", 6) == 0) {
3523 /* NB. cert_principals is actually namespace, via -n */
3524 if (cert_principals == NULL((void*)0) ||
3525 *cert_principals == '\0') {
3526 error("Too few arguments for verify: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3527, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for verify: "
"missing namespace")
3527 "missing namespace")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3527, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for verify: "
"missing namespace")
;
3528 exit(1);
3529 }
3530 if (ca_key_path == NULL((void*)0)) {
3531 error("Too few arguments for verify: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3532, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for verify: "
"missing signature file")
3532 "missing signature file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3532, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for verify: "
"missing signature file")
;
3533 exit(1);
3534 }
3535 if (!have_identity) {
3536 error("Too few arguments for sign: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3537, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for sign: "
"missing allowed keys file")
3537 "missing allowed keys file")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3537, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for sign: "
"missing allowed keys file")
;
3538 exit(1);
3539 }
3540 if (cert_key_id == NULL((void*)0)) {
3541 error("Too few arguments for verify: "sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3542, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for verify: "
"missing principal identity")
3542 "missing principal identity")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3542, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments for verify: "
"missing principal identity")
;
3543 exit(1);
3544 }
3545 return sig_verify(ca_key_path, cert_principals,
3546 cert_key_id, identity_file, rr_hostname,
3547 opts, nopts);
3548 }
3549 error("Unsupported operation for -Y: \"%s\"", sign_op)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3549, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Unsupported operation for -Y: \"%s\""
, sign_op)
;
3550 usage();
3551 /* NOTREACHED */
3552 }
3553
3554 if (ca_key_path != NULL((void*)0)) {
3555 if (argc < 1 && !gen_krl) {
3556 error("Too few arguments.")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3556, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too few arguments."
)
;
3557 usage();
3558 }
3559 } else if (argc > 0 && !gen_krl && !check_krl &&
3560 !do_gen_candidates && !do_screen_candidates) {
3561 error("Too many arguments.")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3561, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Too many arguments."
)
;
3562 usage();
3563 }
3564 if (change_passphrase && change_comment) {
3565 error("Can only have one of -p and -c.")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3565, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Can only have one of -p and -c."
)
;
3566 usage();
3567 }
3568 if (print_fingerprint && (delete_host || hash_hosts)) {
3569 error("Cannot use -l with -H or -R.")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3569, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "Cannot use -l with -H or -R."
)
;
3570 usage();
3571 }
3572 if (gen_krl) {
3573 do_gen_krl(pw, update_krl, ca_key_path,
3574 cert_serial, identity_comment, argc, argv);
3575 return (0);
3576 }
3577 if (check_krl) {
3578 do_check_krl(pw, print_fingerprint, argc, argv);
3579 return (0);
3580 }
3581 if (ca_key_path != NULL((void*)0)) {
3582 if (cert_key_id == NULL((void*)0))
3583 fatal("Must specify key id (-I) when certifying")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3583, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Must specify key id (-I) when certifying"
)
;
3584 for (i = 0; i < nopts; i++)
3585 add_cert_option(opts[i]);
3586 do_ca_sign(pw, ca_key_path, prefer_agent,
3587 cert_serial, cert_serial_autoinc, argc, argv);
3588 }
3589 if (show_cert)
3590 do_show_cert(pw);
3591 if (delete_host || hash_hosts || find_host) {
3592 do_known_hosts(pw, rr_hostname, find_host,
3593 delete_host, hash_hosts);
3594 }
3595 if (pkcs11provider != NULL((void*)0))
3596 do_download(pw);
3597 if (download_sk) {
3598 for (i = 0; i < nopts; i++) {
3599 if (strncasecmp(opts[i], "device=", 7) == 0) {
3600 sk_device = xstrdup(opts[i] + 7);
3601 } else {
3602 fatal("Option \"%s\" is unsupported for "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3603, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for "
"FIDO authenticator download", opts[i])
3603 "FIDO authenticator download", opts[i])sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3603, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for "
"FIDO authenticator download", opts[i])
;
3604 }
3605 }
3606 return do_download_sk(sk_provider, sk_device);
3607 }
3608 if (print_fingerprint || print_bubblebabble)
3609 do_fingerprint(pw);
3610 if (change_passphrase)
3611 do_change_passphrase(pw);
3612 if (change_comment)
3613 do_change_comment(pw, identity_comment);
3614#ifdef WITH_OPENSSL1
3615 if (convert_to)
3616 do_convert_to(pw);
3617 if (convert_from)
3618 do_convert_from(pw);
3619#else /* WITH_OPENSSL */
3620 if (convert_to || convert_from)
3621 fatal("key conversion disabled at compile time")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3621, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "key conversion disabled at compile time"
)
;
3622#endif /* WITH_OPENSSL */
3623 if (print_public)
3624 do_print_public(pw);
3625 if (rr_hostname != NULL((void*)0)) {
3626 unsigned int n = 0;
3627
3628 if (have_identity) {
3629 n = do_print_resource_record(pw, identity_file,
3630 rr_hostname, print_generic);
3631 if (n == 0)
3632 fatal("%s: %s", identity_file, strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3632, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "%s: %s", identity_file
, strerror((*__errno())))
;
3633 exit(0);
3634 } else {
3635
3636 n += do_print_resource_record(pw,
3637 _PATH_HOST_RSA_KEY_FILE"/etc" "/ssh" "/ssh_host_rsa_key", rr_hostname,
3638 print_generic);
3639 n += do_print_resource_record(pw,
3640 _PATH_HOST_DSA_KEY_FILE"/etc" "/ssh" "/ssh_host_dsa_key", rr_hostname,
3641 print_generic);
3642 n += do_print_resource_record(pw,
3643 _PATH_HOST_ECDSA_KEY_FILE"/etc" "/ssh" "/ssh_host_ecdsa_key", rr_hostname,
3644 print_generic);
3645 n += do_print_resource_record(pw,
3646 _PATH_HOST_ED25519_KEY_FILE"/etc" "/ssh" "/ssh_host_ed25519_key", rr_hostname,
3647 print_generic);
3648 n += do_print_resource_record(pw,
3649 _PATH_HOST_XMSS_KEY_FILE"/etc" "/ssh" "/ssh_host_xmss_key", rr_hostname,
3650 print_generic);
3651 if (n == 0)
3652 fatal("no keys found.")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3652, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "no keys found.")
;
3653 exit(0);
3654 }
3655 }
3656
3657 if (do_gen_candidates || do_screen_candidates) {
3658 if (argc <= 0)
3659 fatal("No output file specified")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3659, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "No output file specified"
)
;
3660 else if (argc > 1)
3661 fatal("Too many output files specified")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3661, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Too many output files specified"
)
;
3662 }
3663 if (do_gen_candidates) {
3664 do_moduli_gen(argv[0], opts, nopts);
3665 return 0;
3666 }
3667 if (do_screen_candidates) {
3668 do_moduli_screen(argv[0], opts, nopts);
3669 return 0;
3670 }
3671
3672 if (gen_all_hostkeys) {
3673 do_gen_all_hostkeys(pw);
3674 return (0);
3675 }
3676
3677 if (key_type_name == NULL((void*)0))
3678 key_type_name = DEFAULT_KEY_TYPE_NAME"rsa";
3679
3680 type = sshkey_type_from_name(key_type_name);
3681 type_bits_valid(type, key_type_name, &bits);
3682
3683 if (!quiet)
3684 printf("Generating public/private %s key pair.\n",
3685 key_type_name);
3686 switch (type) {
3687 case KEY_ECDSA_SK:
3688 case KEY_ED25519_SK:
3689 for (i = 0; i < nopts; i++) {
3690 if (strcasecmp(opts[i], "no-touch-required") == 0) {
3691 sk_flags &= ~SSH_SK_USER_PRESENCE_REQD0x01;
3692 } else if (strcasecmp(opts[i], "verify-required") == 0) {
3693 sk_flags |= SSH_SK_USER_VERIFICATION_REQD0x04;
3694 } else if (strcasecmp(opts[i], "resident") == 0) {
3695 sk_flags |= SSH_SK_RESIDENT_KEY0x20;
3696 } else if (strncasecmp(opts[i], "device=", 7) == 0) {
3697 sk_device = xstrdup(opts[i] + 7);
3698 } else if (strncasecmp(opts[i], "user=", 5) == 0) {
3699 sk_user = xstrdup(opts[i] + 5);
3700 } else if (strncasecmp(opts[i], "challenge=", 10) == 0) {
3701 if ((r = sshbuf_load_file(opts[i] + 10,
3702 &challenge)) != 0) {
3703 fatal_r(r, "Unable to load FIDO "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3705, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to load FIDO "
"enrollment challenge \"%s\"", opts[i] + 10)
3704 "enrollment challenge \"%s\"",sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3705, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to load FIDO "
"enrollment challenge \"%s\"", opts[i] + 10)
3705 opts[i] + 10)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3705, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to load FIDO "
"enrollment challenge \"%s\"", opts[i] + 10)
;
3706 }
3707 } else if (strncasecmp(opts[i],
3708 "write-attestation=", 18) == 0) {
3709 sk_attestation_path = opts[i] + 18;
3710 } else if (strncasecmp(opts[i],
3711 "application=", 12) == 0) {
3712 sk_application = xstrdup(opts[i] + 12);
3713 if (strncmp(sk_application, "ssh:", 4) != 0) {
3714 fatal("FIDO application string must "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3715, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "FIDO application string must "
"begin with \"ssh:\"")
3715 "begin with \"ssh:\"")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3715, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "FIDO application string must "
"begin with \"ssh:\"")
;
3716 }
3717 } else {
3718 fatal("Option \"%s\" is unsupported for "sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3719, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for "
"FIDO authenticator enrollment", opts[i])
3719 "FIDO authenticator enrollment", opts[i])sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3719, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Option \"%s\" is unsupported for "
"FIDO authenticator enrollment", opts[i])
;
3720 }
3721 }
3722 if (!quiet) {
3723 printf("You may need to touch your authenticator "
3724 "to authorize key generation.\n");
3725 }
3726 if ((attest = sshbuf_new()) == NULL((void*)0))
3727 fatal("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3727, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshbuf_new failed"
)
;
3728 if ((sk_flags &
3729 (SSH_SK_USER_VERIFICATION_REQD0x04|SSH_SK_RESIDENT_KEY0x20))) {
3730 passphrase = read_passphrase("Enter PIN for "
3731 "authenticator: ", RP_ALLOW_STDIN0x0002);
3732 } else {
3733 passphrase = NULL((void*)0);
3734 }
3735 for (i = 0 ; ; i++) {
3736 fflush(stdout(&__sF[1]));
3737 r = sshsk_enroll(type, sk_provider, sk_device,
3738 sk_application == NULL((void*)0) ? "ssh:" : sk_application,
3739 sk_user, sk_flags, passphrase, challenge,
3740 &private, attest);
3741 if (r == 0)
3742 break;
3743 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE-43)
3744 fatal_r(r, "Key enrollment failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3744, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Key enrollment failed"
)
;
3745 else if (passphrase != NULL((void*)0)) {
3746 error("PIN incorrect")sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3746, 0, SYSLOG_LEVEL_ERROR, ((void*)0), "PIN incorrect")
;
3747 freezero(passphrase, strlen(passphrase));
3748 passphrase = NULL((void*)0);
3749 }
3750 if (i >= 3)
3751 fatal("Too many incorrect PINs")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3751, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "Too many incorrect PINs"
)
;
3752 passphrase = read_passphrase("Enter PIN for "
3753 "authenticator: ", RP_ALLOW_STDIN0x0002);
3754 if (!quiet) {
3755 printf("You may need to touch your "
3756 "authenticator (again) to authorize "
3757 "key generation.\n");
3758 }
3759 }
3760 if (passphrase != NULL((void*)0)) {
3761 freezero(passphrase, strlen(passphrase));
3762 passphrase = NULL((void*)0);
3763 }
3764 break;
3765 default:
3766 if ((r = sshkey_generate(type, bits, &private)) != 0)
3767 fatal("sshkey_generate failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3767, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_generate failed"
)
;
3768 break;
3769 }
3770 if ((r = sshkey_from_private(private, &public)) != 0)
3771 fatal_r(r, "sshkey_from_private")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3771, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshkey_from_private"
)
;
3772
3773 if (!have_identity)
3774 ask_filename(pw, "Enter file in which to save the key");
3775
3776 /* Create ~/.ssh directory if it doesn't already exist. */
3777 hostfile_create_user_ssh_dir(identity_file, !quiet);
3778
3779 /* If the file already exists, ask the user to confirm. */
3780 if (!confirm_overwrite(identity_file))
3781 exit(1);
3782
3783 /* Determine the passphrase for the private key */
3784 passphrase = private_key_passphrase();
3785 if (identity_comment) {
3786 strlcpy(comment, identity_comment, sizeof(comment));
3787 } else {
3788 /* Create default comment field for the passphrase. */
3789 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
3790 }
3791
3792 /* Save the key with the given passphrase and comment. */
3793 if ((r = sshkey_save_private(private, identity_file, passphrase,
3794 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
3795 error_r(r, "Saving key \"%s\" failed", identity_file)sshlog("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3795, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "Saving key \"%s\" failed"
, identity_file)
;
3796 freezero(passphrase, strlen(passphrase));
3797 exit(1);
3798 }
3799 freezero(passphrase, strlen(passphrase));
3800 sshkey_free(private);
3801
3802 if (!quiet) {
3803 printf("Your identification has been saved in %s\n",
3804 identity_file);
3805 }
3806
3807 strlcat(identity_file, ".pub", sizeof(identity_file));
3808 if ((r = sshkey_save_public(public, identity_file, comment)) != 0)
3809 fatal_r(r, "Unable to save public key to %s", identity_file)sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3809, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "Unable to save public key to %s"
, identity_file)
;
3810
3811 if (!quiet) {
3812 fp = sshkey_fingerprint(public, fingerprint_hash,
3813 SSH_FP_DEFAULT);
3814 ra = sshkey_fingerprint(public, fingerprint_hash,
3815 SSH_FP_RANDOMART);
3816 if (fp == NULL((void*)0) || ra == NULL((void*)0))
3817 fatal("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh-keygen/../ssh-keygen.c", __func__
, 3817, 0, SYSLOG_LEVEL_FATAL, ((void*)0), "sshkey_fingerprint failed"
)
;
3818 printf("Your public key has been saved in %s\n",
3819 identity_file);
3820 printf("The key fingerprint is:\n");
3821 printf("%s %s\n", fp, comment);
3822 printf("The key's randomart image is:\n");
3823 printf("%s\n", ra);
3824 free(ra);
3825 free(fp);
3826 }
3827
3828 if (sk_attestation_path != NULL((void*)0))
3829 save_attestation(attest, sk_attestation_path);
3830
3831 sshbuf_free(attest);
3832 sshkey_free(public);
3833
3834 exit(0);
3835}