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