LCOV - code coverage report
Current view: top level - openssh-6.6p1 - ssh-keygen.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 592 1468 40.3 %
Date: 2014-08-01 Functions: 26 41 63.4 %
Branches: 355 992 35.8 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: ssh-keygen.c,v 1.241 2014/02/05 20:13:25 naddy Exp $ */
       2                 :            : /*
       3                 :            :  * Author: Tatu Ylonen <ylo@cs.hut.fi>
       4                 :            :  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
       5                 :            :  *                    All rights reserved
       6                 :            :  * Identity and host key generation and maintenance.
       7                 :            :  *
       8                 :            :  * As far as I am concerned, the code I have written for this software
       9                 :            :  * can be used freely for any purpose.  Any derived versions of this
      10                 :            :  * software must be clearly marked as such, and if the derived work is
      11                 :            :  * incompatible with the protocol description in the RFC file, it must be
      12                 :            :  * called by a name other than "ssh" or "Secure Shell".
      13                 :            :  */
      14                 :            : 
      15                 :            : #include "includes.h"
      16                 :            : 
      17                 :            : #include <sys/types.h>
      18                 :            : #include <sys/socket.h>
      19                 :            : #include <sys/stat.h>
      20                 :            : #include <sys/param.h>
      21                 :            : 
      22                 :            : #include <openssl/evp.h>
      23                 :            : #include <openssl/pem.h>
      24                 :            : #include "openbsd-compat/openssl-compat.h"
      25                 :            : 
      26                 :            : #include <errno.h>
      27                 :            : #include <fcntl.h>
      28                 :            : #include <netdb.h>
      29                 :            : #ifdef HAVE_PATHS_H
      30                 :            : # include <paths.h>
      31                 :            : #endif
      32                 :            : #include <pwd.h>
      33                 :            : #include <stdarg.h>
      34                 :            : #include <stdio.h>
      35                 :            : #include <stdlib.h>
      36                 :            : #include <string.h>
      37                 :            : #include <unistd.h>
      38                 :            : 
      39                 :            : #include "xmalloc.h"
      40                 :            : #include "key.h"
      41                 :            : #include "rsa.h"
      42                 :            : #include "authfile.h"
      43                 :            : #include "uuencode.h"
      44                 :            : #include "buffer.h"
      45                 :            : #include "pathnames.h"
      46                 :            : #include "log.h"
      47                 :            : #include "misc.h"
      48                 :            : #include "match.h"
      49                 :            : #include "hostfile.h"
      50                 :            : #include "dns.h"
      51                 :            : #include "ssh.h"
      52                 :            : #include "ssh2.h"
      53                 :            : #include "ssh-pkcs11.h"
      54                 :            : #include "atomicio.h"
      55                 :            : #include "krl.h"
      56                 :            : 
      57                 :            : /* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
      58                 :            : #define DEFAULT_BITS            2048
      59                 :            : #define DEFAULT_BITS_DSA        1024
      60                 :            : #define DEFAULT_BITS_ECDSA      256
      61                 :            : u_int32_t bits = 0;
      62                 :            : 
      63                 :            : /*
      64                 :            :  * Flag indicating that we just want to change the passphrase.  This can be
      65                 :            :  * set on the command line.
      66                 :            :  */
      67                 :            : int change_passphrase = 0;
      68                 :            : 
      69                 :            : /*
      70                 :            :  * Flag indicating that we just want to change the comment.  This can be set
      71                 :            :  * on the command line.
      72                 :            :  */
      73                 :            : int change_comment = 0;
      74                 :            : 
      75                 :            : int quiet = 0;
      76                 :            : 
      77                 :            : int log_level = SYSLOG_LEVEL_INFO;
      78                 :            : 
      79                 :            : /* Flag indicating that we want to hash a known_hosts file */
      80                 :            : int hash_hosts = 0;
      81                 :            : /* Flag indicating that we want lookup a host in known_hosts file */
      82                 :            : int find_host = 0;
      83                 :            : /* Flag indicating that we want to delete a host from a known_hosts file */
      84                 :            : int delete_host = 0;
      85                 :            : 
      86                 :            : /* Flag indicating that we want to show the contents of a certificate */
      87                 :            : int show_cert = 0;
      88                 :            : 
      89                 :            : /* Flag indicating that we just want to see the key fingerprint */
      90                 :            : int print_fingerprint = 0;
      91                 :            : int print_bubblebabble = 0;
      92                 :            : 
      93                 :            : /* The identity file name, given on the command line or entered by the user. */
      94                 :            : char identity_file[1024];
      95                 :            : int have_identity = 0;
      96                 :            : 
      97                 :            : /* This is set to the passphrase if given on the command line. */
      98                 :            : char *identity_passphrase = NULL;
      99                 :            : 
     100                 :            : /* This is set to the new passphrase if given on the command line. */
     101                 :            : char *identity_new_passphrase = NULL;
     102                 :            : 
     103                 :            : /* This is set to the new comment if given on the command line. */
     104                 :            : char *identity_comment = NULL;
     105                 :            : 
     106                 :            : /* Path to CA key when certifying keys. */
     107                 :            : char *ca_key_path = NULL;
     108                 :            : 
     109                 :            : /* Certificate serial number */
     110                 :            : unsigned long long cert_serial = 0;
     111                 :            : 
     112                 :            : /* Key type when certifying */
     113                 :            : u_int cert_key_type = SSH2_CERT_TYPE_USER;
     114                 :            : 
     115                 :            : /* "key ID" of signed key */
     116                 :            : char *cert_key_id = NULL;
     117                 :            : 
     118                 :            : /* Comma-separated list of principal names for certifying keys */
     119                 :            : char *cert_principals = NULL;
     120                 :            : 
     121                 :            : /* Validity period for certificates */
     122                 :            : u_int64_t cert_valid_from = 0;
     123                 :            : u_int64_t cert_valid_to = ~0ULL;
     124                 :            : 
     125                 :            : /* Certificate options */
     126                 :            : #define CERTOPT_X_FWD   (1)
     127                 :            : #define CERTOPT_AGENT_FWD       (1<<1)
     128                 :            : #define CERTOPT_PORT_FWD        (1<<2)
     129                 :            : #define CERTOPT_PTY             (1<<3)
     130                 :            : #define CERTOPT_USER_RC (1<<4)
     131                 :            : #define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
     132                 :            :                          CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
     133                 :            : u_int32_t certflags_flags = CERTOPT_DEFAULT;
     134                 :            : char *certflags_command = NULL;
     135                 :            : char *certflags_src_addr = NULL;
     136                 :            : 
     137                 :            : /* Conversion to/from various formats */
     138                 :            : int convert_to = 0;
     139                 :            : int convert_from = 0;
     140                 :            : enum {
     141                 :            :         FMT_RFC4716,
     142                 :            :         FMT_PKCS8,
     143                 :            :         FMT_PEM
     144                 :            : } convert_format = FMT_RFC4716;
     145                 :            : int print_public = 0;
     146                 :            : int print_generic = 0;
     147                 :            : 
     148                 :            : char *key_type_name = NULL;
     149                 :            : 
     150                 :            : /* Load key from this PKCS#11 provider */
     151                 :            : char *pkcs11provider = NULL;
     152                 :            : 
     153                 :            : /* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
     154                 :            : int use_new_format = 0;
     155                 :            : 
     156                 :            : /* Cipher for new-format private keys */
     157                 :            : char *new_format_cipher = NULL;
     158                 :            : 
     159                 :            : /*
     160                 :            :  * Number of KDF rounds to derive new format keys /
     161                 :            :  * number of primality trials when screening moduli.
     162                 :            :  */
     163                 :            : int rounds = 0;
     164                 :            : 
     165                 :            : /* argv0 */
     166                 :            : extern char *__progname;
     167                 :            : 
     168                 :            : char hostname[MAXHOSTNAMELEN];
     169                 :            : 
     170                 :            : /* moduli.c */
     171                 :            : int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
     172                 :            : int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
     173                 :            :     unsigned long);
     174                 :            : 
     175                 :            : static void
     176                 :         53 : type_bits_valid(int type, u_int32_t *bitsp)
     177                 :            : {
     178                 :            :         u_int maxbits;
     179                 :            : 
     180         [ -  + ]:         53 :         if (type == KEY_UNSPEC) {
     181                 :          0 :                 fprintf(stderr, "unknown key type %s\n", key_type_name);
     182                 :          0 :                 exit(1);
     183                 :            :         }
     184         [ +  + ]:         53 :         if (*bitsp == 0) {
     185         [ +  + ]:         46 :                 if (type == KEY_DSA)
     186                 :         11 :                         *bitsp = DEFAULT_BITS_DSA;
     187         [ +  + ]:         35 :                 else if (type == KEY_ECDSA)
     188                 :         13 :                         *bitsp = DEFAULT_BITS_ECDSA;
     189                 :            :                 else
     190                 :         22 :                         *bitsp = DEFAULT_BITS;
     191                 :            :         }
     192         [ +  + ]:         53 :         maxbits = (type == KEY_DSA) ?
     193                 :            :             OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
     194         [ -  + ]:         53 :         if (*bitsp > maxbits) {
     195                 :          0 :                 fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
     196                 :          0 :                 exit(1);
     197                 :            :         }
     198 [ +  + ][ -  + ]:         53 :         if (type == KEY_DSA && *bitsp != 1024)
     199                 :          0 :                 fatal("DSA keys must be 1024 bits");
     200 [ +  + ][ -  + ]:         53 :         else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768)
     201                 :          0 :                 fatal("Key must at least be 768 bits");
     202 [ +  + ][ -  + ]:         53 :         else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1)
     203                 :          0 :                 fatal("Invalid ECDSA key length - valid lengths are "
     204                 :            :                     "256, 384 or 521 bits");
     205                 :         53 : }
     206                 :            : 
     207                 :            : static void
     208                 :          0 : ask_filename(struct passwd *pw, const char *prompt)
     209                 :            : {
     210                 :            :         char buf[1024];
     211                 :          0 :         char *name = NULL;
     212                 :            : 
     213         [ #  # ]:          0 :         if (key_type_name == NULL)
     214                 :            :                 name = _PATH_SSH_CLIENT_ID_RSA;
     215                 :            :         else {
     216   [ #  #  #  #  :          0 :                 switch (key_type_from_name(key_type_name)) {
                   #  # ]
     217                 :            :                 case KEY_RSA1:
     218                 :            :                         name = _PATH_SSH_CLIENT_IDENTITY;
     219                 :            :                         break;
     220                 :            :                 case KEY_DSA_CERT:
     221                 :            :                 case KEY_DSA_CERT_V00:
     222                 :            :                 case KEY_DSA:
     223                 :          0 :                         name = _PATH_SSH_CLIENT_ID_DSA;
     224                 :            :                         break;
     225                 :            : #ifdef OPENSSL_HAS_ECC
     226                 :            :                 case KEY_ECDSA_CERT:
     227                 :            :                 case KEY_ECDSA:
     228                 :          0 :                         name = _PATH_SSH_CLIENT_ID_ECDSA;
     229                 :            :                         break;
     230                 :            : #endif
     231                 :            :                 case KEY_RSA_CERT:
     232                 :            :                 case KEY_RSA_CERT_V00:
     233                 :            :                 case KEY_RSA:
     234                 :          0 :                         name = _PATH_SSH_CLIENT_ID_RSA;
     235                 :            :                         break;
     236                 :            :                 case KEY_ED25519:
     237                 :            :                 case KEY_ED25519_CERT:
     238                 :          0 :                         name = _PATH_SSH_CLIENT_ID_ED25519;
     239                 :            :                         break;
     240                 :            :                 default:
     241                 :          0 :                         fprintf(stderr, "bad key type\n");
     242                 :          0 :                         exit(1);
     243                 :            :                         break;
     244                 :            :                 }
     245                 :            :         }
     246                 :          0 :         snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
     247                 :          0 :         fprintf(stderr, "%s (%s): ", prompt, identity_file);
     248         [ #  # ]:          0 :         if (fgets(buf, sizeof(buf), stdin) == NULL)
     249                 :          0 :                 exit(1);
     250                 :          0 :         buf[strcspn(buf, "\n")] = '\0';
     251         [ #  # ]:          0 :         if (strcmp(buf, "") != 0)
     252                 :          0 :                 strlcpy(identity_file, buf, sizeof(identity_file));
     253                 :          0 :         have_identity = 1;
     254                 :          0 : }
     255                 :            : 
     256                 :            : static Key *
     257                 :        101 : load_identity(char *filename)
     258                 :            : {
     259                 :            :         char *pass;
     260                 :            :         Key *prv;
     261                 :            : 
     262                 :        101 :         prv = key_load_private(filename, "", NULL);
     263         [ -  + ]:        101 :         if (prv == NULL) {
     264         [ #  # ]:          0 :                 if (identity_passphrase)
     265                 :          0 :                         pass = xstrdup(identity_passphrase);
     266                 :            :                 else
     267                 :          0 :                         pass = read_passphrase("Enter passphrase: ",
     268                 :            :                             RP_ALLOW_STDIN);
     269                 :          0 :                 prv = key_load_private(filename, pass, NULL);
     270                 :          0 :                 explicit_bzero(pass, strlen(pass));
     271                 :          0 :                 free(pass);
     272                 :            :         }
     273                 :        101 :         return prv;
     274                 :            : }
     275                 :            : 
     276                 :            : #define SSH_COM_PUBLIC_BEGIN            "---- BEGIN SSH2 PUBLIC KEY ----"
     277                 :            : #define SSH_COM_PUBLIC_END              "---- END SSH2 PUBLIC KEY ----"
     278                 :            : #define SSH_COM_PRIVATE_BEGIN           "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
     279                 :            : #define SSH_COM_PRIVATE_KEY_MAGIC       0x3f6ff9eb
     280                 :            : 
     281                 :            : static void
     282                 :         10 : do_convert_to_ssh2(struct passwd *pw, Key *k)
     283                 :            : {
     284                 :            :         u_int len;
     285                 :            :         u_char *blob;
     286                 :            :         char comment[61];
     287                 :            : 
     288         [ -  + ]:          5 :         if (k->type == KEY_RSA1) {
     289                 :          0 :                 fprintf(stderr, "version 1 keys are not supported\n");
     290                 :          0 :                 exit(1);
     291                 :            :         }
     292         [ -  + ]:          5 :         if (key_to_blob(k, &blob, &len) <= 0) {
     293                 :          0 :                 fprintf(stderr, "key_to_blob failed\n");
     294                 :          0 :                 exit(1);
     295                 :            :         }
     296                 :            :         /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
     297                 :          5 :         snprintf(comment, sizeof(comment),
     298                 :            :             "%u-bit %s, converted by %s@%s from OpenSSH",
     299                 :            :             key_size(k), key_type(k),
     300                 :            :             pw->pw_name, hostname);
     301                 :            : 
     302                 :          5 :         fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
     303                 :          5 :         fprintf(stdout, "Comment: \"%s\"\n", comment);
     304                 :          5 :         dump_base64(stdout, blob, len);
     305                 :          5 :         fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
     306                 :          5 :         key_free(k);
     307                 :          5 :         free(blob);
     308                 :          5 :         exit(0);
     309                 :            : }
     310                 :            : 
     311                 :            : static void
     312                 :          0 : do_convert_to_pkcs8(Key *k)
     313                 :            : {
     314   [ #  #  #  # ]:          0 :         switch (key_type_plain(k->type)) {
     315                 :            :         case KEY_RSA1:
     316                 :            :         case KEY_RSA:
     317         [ #  # ]:          0 :                 if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
     318                 :          0 :                         fatal("PEM_write_RSA_PUBKEY failed");
     319                 :            :                 break;
     320                 :            :         case KEY_DSA:
     321         [ #  # ]:          0 :                 if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
     322                 :          0 :                         fatal("PEM_write_DSA_PUBKEY failed");
     323                 :            :                 break;
     324                 :            : #ifdef OPENSSL_HAS_ECC
     325                 :            :         case KEY_ECDSA:
     326         [ #  # ]:          0 :                 if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
     327                 :          0 :                         fatal("PEM_write_EC_PUBKEY failed");
     328                 :            :                 break;
     329                 :            : #endif
     330                 :            :         default:
     331                 :          0 :                 fatal("%s: unsupported key type %s", __func__, key_type(k));
     332                 :            :         }
     333                 :          0 :         exit(0);
     334                 :            : }
     335                 :            : 
     336                 :            : static void
     337                 :          0 : do_convert_to_pem(Key *k)
     338                 :            : {
     339         [ #  # ]:          0 :         switch (key_type_plain(k->type)) {
     340                 :            :         case KEY_RSA1:
     341                 :            :         case KEY_RSA:
     342         [ #  # ]:          0 :                 if (!PEM_write_RSAPublicKey(stdout, k->rsa))
     343                 :          0 :                         fatal("PEM_write_RSAPublicKey failed");
     344                 :            :                 break;
     345                 :            : #if notyet /* OpenSSH 0.9.8 lacks this function */
     346                 :            :         case KEY_DSA:
     347                 :            :                 if (!PEM_write_DSAPublicKey(stdout, k->dsa))
     348                 :            :                         fatal("PEM_write_DSAPublicKey failed");
     349                 :            :                 break;
     350                 :            : #endif
     351                 :            :         /* XXX ECDSA? */
     352                 :            :         default:
     353                 :          0 :                 fatal("%s: unsupported key type %s", __func__, key_type(k));
     354                 :            :         }
     355                 :          0 :         exit(0);
     356                 :            : }
     357                 :            : 
     358                 :            : static void
     359                 :          5 : do_convert_to(struct passwd *pw)
     360                 :            : {
     361                 :            :         Key *k;
     362                 :            :         struct stat st;
     363                 :            : 
     364         [ -  + ]:          5 :         if (!have_identity)
     365                 :          0 :                 ask_filename(pw, "Enter file in which the key is");
     366         [ -  + ]:          5 :         if (stat(identity_file, &st) < 0)
     367                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
     368         [ -  + ]:          5 :         if ((k = key_load_public(identity_file, NULL)) == NULL) {
     369         [ #  # ]:          0 :                 if ((k = load_identity(identity_file)) == NULL) {
     370                 :          0 :                         fprintf(stderr, "load failed\n");
     371                 :          0 :                         exit(1);
     372                 :            :                 }
     373                 :            :         }
     374                 :            : 
     375   [ +  -  -  - ]:          5 :         switch (convert_format) {
     376                 :            :         case FMT_RFC4716:
     377                 :          5 :                 do_convert_to_ssh2(pw, k);
     378                 :            :                 break;
     379                 :            :         case FMT_PKCS8:
     380                 :          0 :                 do_convert_to_pkcs8(k);
     381                 :            :                 break;
     382                 :            :         case FMT_PEM:
     383                 :          0 :                 do_convert_to_pem(k);
     384                 :            :                 break;
     385                 :            :         default:
     386                 :          0 :                 fatal("%s: unknown key format %d", __func__, convert_format);
     387                 :            :         }
     388                 :            :         exit(0);
     389                 :            : }
     390                 :            : 
     391                 :            : static void
     392                 :         20 : buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
     393                 :            : {
     394                 :         20 :         u_int bignum_bits = buffer_get_int(b);
     395                 :         20 :         u_int bytes = (bignum_bits + 7) / 8;
     396                 :            : 
     397         [ -  + ]:         20 :         if (buffer_len(b) < bytes)
     398                 :          0 :                 fatal("buffer_get_bignum_bits: input buffer too small: "
     399                 :            :                     "need %d have %d", bytes, buffer_len(b));
     400         [ -  + ]:         20 :         if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL)
     401                 :          0 :                 fatal("buffer_get_bignum_bits: BN_bin2bn failed");
     402                 :         20 :         buffer_consume(b, bytes);
     403                 :         20 : }
     404                 :            : 
     405                 :            : static Key *
     406                 :          4 : do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
     407                 :            : {
     408                 :            :         Buffer b;
     409                 :          4 :         Key *key = NULL;
     410                 :            :         char *type, *cipher;
     411                 :          4 :         u_char *sig, data[] = "abcde12345";
     412                 :            :         int magic, rlen, ktype, i1, i2, i3, i4;
     413                 :            :         u_int slen;
     414                 :            :         u_long e;
     415                 :            : 
     416                 :          4 :         buffer_init(&b);
     417                 :          4 :         buffer_append(&b, blob, blen);
     418                 :            : 
     419                 :          4 :         magic = buffer_get_int(&b);
     420         [ -  + ]:          4 :         if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
     421                 :          0 :                 error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
     422                 :          0 :                 buffer_free(&b);
     423                 :          0 :                 return NULL;
     424                 :            :         }
     425                 :          4 :         i1 = buffer_get_int(&b);
     426                 :          4 :         type   = buffer_get_string(&b, NULL);
     427                 :          4 :         cipher = buffer_get_string(&b, NULL);
     428                 :          4 :         i2 = buffer_get_int(&b);
     429                 :          4 :         i3 = buffer_get_int(&b);
     430                 :          4 :         i4 = buffer_get_int(&b);
     431                 :          4 :         debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
     432         [ -  + ]:          4 :         if (strcmp(cipher, "none") != 0) {
     433                 :          0 :                 error("unsupported cipher %s", cipher);
     434                 :          0 :                 free(cipher);
     435                 :          0 :                 buffer_free(&b);
     436                 :          0 :                 free(type);
     437                 :          0 :                 return NULL;
     438                 :            :         }
     439                 :          4 :         free(cipher);
     440                 :            : 
     441         [ +  + ]:          4 :         if (strstr(type, "dsa")) {
     442                 :            :                 ktype = KEY_DSA;
     443         [ -  + ]:          3 :         } else if (strstr(type, "rsa")) {
     444                 :            :                 ktype = KEY_RSA;
     445                 :            :         } else {
     446                 :          0 :                 buffer_free(&b);
     447                 :          0 :                 free(type);
     448                 :          0 :                 return NULL;
     449                 :            :         }
     450                 :          4 :         key = key_new_private(ktype);
     451                 :          4 :         free(type);
     452                 :            : 
     453      [ +  +  - ]:          4 :         switch (key->type) {
     454                 :            :         case KEY_DSA:
     455                 :          1 :                 buffer_get_bignum_bits(&b, key->dsa->p);
     456                 :          1 :                 buffer_get_bignum_bits(&b, key->dsa->g);
     457                 :          1 :                 buffer_get_bignum_bits(&b, key->dsa->q);
     458                 :          1 :                 buffer_get_bignum_bits(&b, key->dsa->pub_key);
     459                 :          1 :                 buffer_get_bignum_bits(&b, key->dsa->priv_key);
     460                 :          1 :                 break;
     461                 :            :         case KEY_RSA:
     462                 :          3 :                 e = buffer_get_char(&b);
     463                 :          3 :                 debug("e %lx", e);
     464         [ +  - ]:          3 :                 if (e < 30) {
     465                 :          3 :                         e <<= 8;
     466                 :          3 :                         e += buffer_get_char(&b);
     467                 :          3 :                         debug("e %lx", e);
     468                 :          3 :                         e <<= 8;
     469                 :          3 :                         e += buffer_get_char(&b);
     470                 :          3 :                         debug("e %lx", e);
     471                 :            :                 }
     472         [ -  + ]:          3 :                 if (!BN_set_word(key->rsa->e, e)) {
     473                 :          0 :                         buffer_free(&b);
     474                 :          0 :                         key_free(key);
     475                 :          0 :                         return NULL;
     476                 :            :                 }
     477                 :          3 :                 buffer_get_bignum_bits(&b, key->rsa->d);
     478                 :          3 :                 buffer_get_bignum_bits(&b, key->rsa->n);
     479                 :          3 :                 buffer_get_bignum_bits(&b, key->rsa->iqmp);
     480                 :          3 :                 buffer_get_bignum_bits(&b, key->rsa->q);
     481                 :          3 :                 buffer_get_bignum_bits(&b, key->rsa->p);
     482                 :          3 :                 rsa_generate_additional_parameters(key->rsa);
     483                 :          3 :                 break;
     484                 :            :         }
     485                 :          4 :         rlen = buffer_len(&b);
     486         [ -  + ]:          4 :         if (rlen != 0)
     487                 :          0 :                 error("do_convert_private_ssh2_from_blob: "
     488                 :            :                     "remaining bytes in key blob %d", rlen);
     489                 :          4 :         buffer_free(&b);
     490                 :            : 
     491                 :            :         /* try the key */
     492                 :          4 :         key_sign(key, &sig, &slen, data, sizeof(data));
     493                 :          4 :         key_verify(key, sig, slen, data, sizeof(data));
     494                 :          4 :         free(sig);
     495                 :          4 :         return key;
     496                 :            : }
     497                 :            : 
     498                 :            : static int
     499                 :         99 : get_line(FILE *fp, char *line, size_t len)
     500                 :            : {
     501                 :            :         int c;
     502                 :         99 :         size_t pos = 0;
     503                 :            : 
     504                 :         99 :         line[0] = '\0';
     505         [ +  - ]:       5901 :         while ((c = fgetc(fp)) != EOF) {
     506         [ -  + ]:       5901 :                 if (pos >= len - 1) {
     507                 :          0 :                         fprintf(stderr, "input line too long.\n");
     508                 :          0 :                         exit(1);
     509                 :            :                 }
     510      [ +  +  + ]:       5901 :                 switch (c) {
     511                 :            :                 case '\r':
     512                 :         30 :                         c = fgetc(fp);
     513 [ +  + ][ -  + ]:         30 :                         if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
     514                 :          0 :                                 fprintf(stderr, "unget: %s\n", strerror(errno));
     515                 :          0 :                                 exit(1);
     516                 :            :                         }
     517                 :         30 :                         return pos;
     518                 :            :                 case '\n':
     519                 :         69 :                         return pos;
     520                 :            :                 }
     521                 :       5802 :                 line[pos++] = c;
     522                 :       5802 :                 line[pos] = '\0';
     523                 :            :         }
     524                 :            :         /* We reached EOF */
     525                 :            :         return -1;
     526                 :            : }
     527                 :            : 
     528                 :            : static void
     529                 :          8 : do_convert_from_ssh2(struct passwd *pw, Key **k, int *private)
     530                 :            : {
     531                 :            :         int blen;
     532                 :            :         u_int len;
     533                 :            :         char line[1024];
     534                 :            :         u_char blob[8096];
     535                 :            :         char encoded[8096];
     536                 :          8 :         int escaped = 0;
     537                 :            :         FILE *fp;
     538                 :            : 
     539         [ -  + ]:          8 :         if ((fp = fopen(identity_file, "r")) == NULL)
     540                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
     541                 :          8 :         encoded[0] = '\0';
     542         [ +  - ]:         99 :         while ((blen = get_line(fp, line, sizeof(line))) != -1) {
     543 [ +  - ][ -  + ]:         99 :                 if (blen > 0 && line[blen - 1] == '\\')
     544                 :          0 :                         escaped++;
     545 [ +  + ][ +  + ]:         99 :                 if (strncmp(line, "----", 4) == 0 ||
     546                 :         83 :                     strstr(line, ": ") != NULL) {
     547         [ +  + ]:         29 :                         if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
     548                 :          4 :                                 *private = 1;
     549         [ +  + ]:         29 :                         if (strstr(line, " END ") != NULL) {
     550                 :            :                                 break;
     551                 :            :                         }
     552                 :            :                         /* fprintf(stderr, "ignore: %s", line); */
     553                 :         21 :                         continue;
     554                 :            :                 }
     555         [ -  + ]:         70 :                 if (escaped) {
     556                 :          0 :                         escaped--;
     557                 :            :                         /* fprintf(stderr, "escaped: %s", line); */
     558                 :          0 :                         continue;
     559                 :            :                 }
     560                 :         91 :                 strlcat(encoded, line, sizeof(encoded));
     561                 :            :         }
     562                 :          8 :         len = strlen(encoded);
     563 [ -  + ][ #  # ]:          8 :         if (((len % 4) == 3) &&
     564         [ #  # ]:          0 :             (encoded[len-1] == '=') &&
     565         [ #  # ]:          0 :             (encoded[len-2] == '=') &&
     566                 :          0 :             (encoded[len-3] == '='))
     567                 :          0 :                 encoded[len-3] = '\0';
     568                 :          8 :         blen = uudecode(encoded, blob, sizeof(blob));
     569         [ -  + ]:          8 :         if (blen < 0) {
     570                 :          0 :                 fprintf(stderr, "uudecode failed.\n");
     571                 :          0 :                 exit(1);
     572                 :            :         }
     573                 :         16 :         *k = *private ?
     574         [ +  + ]:          8 :             do_convert_private_ssh2_from_blob(blob, blen) :
     575                 :          4 :             key_from_blob(blob, blen);
     576         [ -  + ]:          8 :         if (*k == NULL) {
     577                 :          0 :                 fprintf(stderr, "decode blob failed.\n");
     578                 :          0 :                 exit(1);
     579                 :            :         }
     580                 :          8 :         fclose(fp);
     581                 :          8 : }
     582                 :            : 
     583                 :            : static void
     584                 :          0 : do_convert_from_pkcs8(Key **k, int *private)
     585                 :            : {
     586                 :            :         EVP_PKEY *pubkey;
     587                 :            :         FILE *fp;
     588                 :            : 
     589         [ #  # ]:          0 :         if ((fp = fopen(identity_file, "r")) == NULL)
     590                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
     591         [ #  # ]:          0 :         if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
     592                 :          0 :                 fatal("%s: %s is not a recognised public key format", __func__,
     593                 :            :                     identity_file);
     594                 :            :         }
     595                 :          0 :         fclose(fp);
     596   [ #  #  #  # ]:          0 :         switch (EVP_PKEY_type(pubkey->type)) {
     597                 :            :         case EVP_PKEY_RSA:
     598                 :          0 :                 *k = key_new(KEY_UNSPEC);
     599                 :          0 :                 (*k)->type = KEY_RSA;
     600                 :          0 :                 (*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
     601                 :            :                 break;
     602                 :            :         case EVP_PKEY_DSA:
     603                 :          0 :                 *k = key_new(KEY_UNSPEC);
     604                 :          0 :                 (*k)->type = KEY_DSA;
     605                 :          0 :                 (*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
     606                 :            :                 break;
     607                 :            : #ifdef OPENSSL_HAS_ECC
     608                 :            :         case EVP_PKEY_EC:
     609                 :          0 :                 *k = key_new(KEY_UNSPEC);
     610                 :          0 :                 (*k)->type = KEY_ECDSA;
     611                 :          0 :                 (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey);
     612                 :          0 :                 (*k)->ecdsa_nid = key_ecdsa_key_to_nid((*k)->ecdsa);
     613                 :            :                 break;
     614                 :            : #endif
     615                 :            :         default:
     616                 :          0 :                 fatal("%s: unsupported pubkey type %d", __func__,
     617                 :            :                     EVP_PKEY_type(pubkey->type));
     618                 :            :         }
     619                 :          0 :         EVP_PKEY_free(pubkey);
     620                 :          0 :         return;
     621                 :            : }
     622                 :            : 
     623                 :            : static void
     624                 :          0 : do_convert_from_pem(Key **k, int *private)
     625                 :            : {
     626                 :            :         FILE *fp;
     627                 :            :         RSA *rsa;
     628                 :            : #ifdef notyet
     629                 :            :         DSA *dsa;
     630                 :            : #endif
     631                 :            : 
     632         [ #  # ]:          0 :         if ((fp = fopen(identity_file, "r")) == NULL)
     633                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
     634         [ #  # ]:          0 :         if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
     635                 :          0 :                 *k = key_new(KEY_UNSPEC);
     636                 :          0 :                 (*k)->type = KEY_RSA;
     637                 :          0 :                 (*k)->rsa = rsa;
     638                 :          0 :                 fclose(fp);
     639                 :          0 :                 return;
     640                 :            :         }
     641                 :            : #if notyet /* OpenSSH 0.9.8 lacks this function */
     642                 :            :         rewind(fp);
     643                 :            :         if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
     644                 :            :                 *k = key_new(KEY_UNSPEC);
     645                 :            :                 (*k)->type = KEY_DSA;
     646                 :            :                 (*k)->dsa = dsa;
     647                 :            :                 fclose(fp);
     648                 :            :                 return;
     649                 :            :         }
     650                 :            :         /* XXX ECDSA */
     651                 :            : #endif
     652                 :          0 :         fatal("%s: unrecognised raw private key format", __func__);
     653                 :            : }
     654                 :            : 
     655                 :            : static void
     656                 :          8 : do_convert_from(struct passwd *pw)
     657                 :            : {
     658                 :          8 :         Key *k = NULL;
     659                 :          8 :         int private = 0, ok = 0;
     660                 :            :         struct stat st;
     661                 :            : 
     662         [ -  + ]:          8 :         if (!have_identity)
     663                 :          0 :                 ask_filename(pw, "Enter file in which the key is");
     664         [ -  + ]:          8 :         if (stat(identity_file, &st) < 0)
     665                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
     666                 :            : 
     667   [ +  -  -  - ]:          8 :         switch (convert_format) {
     668                 :            :         case FMT_RFC4716:
     669                 :          8 :                 do_convert_from_ssh2(pw, &k, &private);
     670                 :          8 :                 break;
     671                 :            :         case FMT_PKCS8:
     672                 :          0 :                 do_convert_from_pkcs8(&k, &private);
     673                 :          0 :                 break;
     674                 :            :         case FMT_PEM:
     675                 :          0 :                 do_convert_from_pem(&k, &private);
     676                 :          0 :                 break;
     677                 :            :         default:
     678                 :          0 :                 fatal("%s: unknown key format %d", __func__, convert_format);
     679                 :            :         }
     680                 :            : 
     681         [ +  + ]:          8 :         if (!private)
     682                 :          4 :                 ok = key_write(k, stdout);
     683         [ +  + ]:          8 :                 if (ok)
     684                 :          4 :                         fprintf(stdout, "\n");
     685                 :            :         else {
     686   [ +  -  +  - ]:          4 :                 switch (k->type) {
     687                 :            :                 case KEY_DSA:
     688                 :          1 :                         ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL,
     689                 :            :                             NULL, 0, NULL, NULL);
     690                 :          1 :                         break;
     691                 :            : #ifdef OPENSSL_HAS_ECC
     692                 :            :                 case KEY_ECDSA:
     693                 :          0 :                         ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL,
     694                 :            :                             NULL, 0, NULL, NULL);
     695                 :          0 :                         break;
     696                 :            : #endif
     697                 :            :                 case KEY_RSA:
     698                 :          3 :                         ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL,
     699                 :            :                             NULL, 0, NULL, NULL);
     700                 :          3 :                         break;
     701                 :            :                 default:
     702                 :          0 :                         fatal("%s: unsupported key type %s", __func__,
     703                 :            :                             key_type(k));
     704                 :            :                 }
     705                 :            :         }
     706                 :            : 
     707         [ -  + ]:          8 :         if (!ok) {
     708                 :          0 :                 fprintf(stderr, "key write failed\n");
     709                 :          0 :                 exit(1);
     710                 :            :         }
     711                 :          8 :         key_free(k);
     712                 :          8 :         exit(0);
     713                 :            : }
     714                 :            : 
     715                 :            : static void
     716                 :          2 : do_print_public(struct passwd *pw)
     717                 :            : {
     718                 :            :         Key *prv;
     719                 :            :         struct stat st;
     720                 :            : 
     721         [ -  + ]:          2 :         if (!have_identity)
     722                 :          0 :                 ask_filename(pw, "Enter file in which the key is");
     723         [ -  + ]:          2 :         if (stat(identity_file, &st) < 0) {
     724                 :          0 :                 perror(identity_file);
     725                 :          0 :                 exit(1);
     726                 :            :         }
     727                 :          2 :         prv = load_identity(identity_file);
     728         [ -  + ]:          2 :         if (prv == NULL) {
     729                 :          0 :                 fprintf(stderr, "load failed\n");
     730                 :          0 :                 exit(1);
     731                 :            :         }
     732         [ -  + ]:          2 :         if (!key_write(prv, stdout))
     733                 :          0 :                 fprintf(stderr, "key_write failed");
     734                 :          2 :         key_free(prv);
     735                 :          2 :         fprintf(stdout, "\n");
     736                 :          2 :         exit(0);
     737                 :            : }
     738                 :            : 
     739                 :            : static void
     740                 :          0 : do_download(struct passwd *pw)
     741                 :            : {
     742                 :            : #ifdef ENABLE_PKCS11
     743                 :          0 :         Key **keys = NULL;
     744                 :            :         int i, nkeys;
     745                 :            :         enum fp_rep rep;
     746                 :            :         enum fp_type fptype;
     747                 :            :         char *fp, *ra;
     748                 :            : 
     749                 :          0 :         fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
     750                 :          0 :         rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
     751                 :            : 
     752                 :          0 :         pkcs11_init(0);
     753                 :          0 :         nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
     754         [ #  # ]:          0 :         if (nkeys <= 0)
     755                 :          0 :                 fatal("cannot read public key from pkcs11");
     756         [ #  # ]:          0 :         for (i = 0; i < nkeys; i++) {
     757         [ #  # ]:          0 :                 if (print_fingerprint) {
     758                 :          0 :                         fp = key_fingerprint(keys[i], fptype, rep);
     759                 :          0 :                         ra = key_fingerprint(keys[i], SSH_FP_MD5,
     760                 :            :                             SSH_FP_RANDOMART);
     761                 :          0 :                         printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
     762                 :          0 :                             fp, key_type(keys[i]));
     763         [ #  # ]:          0 :                         if (log_level >= SYSLOG_LEVEL_VERBOSE)
     764                 :            :                                 printf("%s\n", ra);
     765                 :          0 :                         free(ra);
     766                 :          0 :                         free(fp);
     767                 :            :                 } else {
     768                 :          0 :                         key_write(keys[i], stdout);
     769                 :          0 :                         fprintf(stdout, "\n");
     770                 :            :                 }
     771                 :          0 :                 key_free(keys[i]);
     772                 :            :         }
     773                 :          0 :         free(keys);
     774                 :          0 :         pkcs11_terminate();
     775                 :          0 :         exit(0);
     776                 :            : #else
     777                 :            :         fatal("no pkcs11 support");
     778                 :            : #endif /* ENABLE_PKCS11 */
     779                 :            : }
     780                 :            : 
     781                 :            : static void
     782                 :         10 : do_fingerprint(struct passwd *pw)
     783                 :            : {
     784                 :            :         FILE *f;
     785                 :            :         Key *public;
     786                 :         10 :         char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
     787                 :         10 :         int i, skip = 0, num = 0, invalid = 1;
     788                 :            :         enum fp_rep rep;
     789                 :            :         enum fp_type fptype;
     790                 :            :         struct stat st;
     791                 :            : 
     792                 :         10 :         fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
     793                 :         10 :         rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
     794                 :            : 
     795         [ -  + ]:         10 :         if (!have_identity)
     796                 :          0 :                 ask_filename(pw, "Enter file in which the key is");
     797         [ -  + ]:         10 :         if (stat(identity_file, &st) < 0) {
     798                 :          0 :                 perror(identity_file);
     799                 :          0 :                 exit(1);
     800                 :            :         }
     801                 :         10 :         public = key_load_public(identity_file, &comment);
     802         [ +  - ]:         10 :         if (public != NULL) {
     803                 :         10 :                 fp = key_fingerprint(public, fptype, rep);
     804                 :         10 :                 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
     805                 :         10 :                 printf("%u %s %s (%s)\n", key_size(public), fp, comment,
     806                 :            :                     key_type(public));
     807         [ -  + ]:         10 :                 if (log_level >= SYSLOG_LEVEL_VERBOSE)
     808                 :            :                         printf("%s\n", ra);
     809                 :         10 :                 key_free(public);
     810                 :         10 :                 free(comment);
     811                 :         10 :                 free(ra);
     812                 :         10 :                 free(fp);
     813                 :         10 :                 exit(0);
     814                 :            :         }
     815         [ #  # ]:          0 :         if (comment) {
     816                 :          0 :                 free(comment);
     817                 :          0 :                 comment = NULL;
     818                 :            :         }
     819                 :            : 
     820         [ #  # ]:          0 :         if ((f = fopen(identity_file, "r")) == NULL)
     821                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
     822                 :            : 
     823         [ #  # ]:          0 :         while (fgets(line, sizeof(line), f)) {
     824         [ #  # ]:          0 :                 if ((cp = strchr(line, '\n')) == NULL) {
     825                 :          0 :                         error("line %d too long: %.40s...",
     826                 :            :                             num + 1, line);
     827                 :          0 :                         skip = 1;
     828                 :          0 :                         continue;
     829                 :            :                 }
     830                 :          0 :                 num++;
     831         [ #  # ]:          0 :                 if (skip) {
     832                 :          0 :                         skip = 0;
     833                 :          0 :                         continue;
     834                 :            :                 }
     835                 :          0 :                 *cp = '\0';
     836                 :            : 
     837                 :            :                 /* Skip leading whitespace, empty and comment lines. */
     838         [ #  # ]:          0 :                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
     839                 :            :                         ;
     840 [ #  # ][ #  # ]:          0 :                 if (!*cp || *cp == '\n' || *cp == '#')
     841                 :          0 :                         continue;
     842                 :          0 :                 i = strtol(cp, &ep, 10);
     843 [ #  # ][ #  # ]:          0 :                 if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
                 [ #  # ]
     844                 :          0 :                         int quoted = 0;
     845                 :          0 :                         comment = cp;
     846 [ #  # ][ #  # ]:          0 :                         for (; *cp && (quoted || (*cp != ' ' &&
                 [ #  # ]
     847                 :          0 :                             *cp != '\t')); cp++) {
     848 [ #  # ][ #  # ]:          0 :                                 if (*cp == '\\' && cp[1] == '"')
     849                 :          0 :                                         cp++;   /* Skip both */
     850         [ #  # ]:          0 :                                 else if (*cp == '"')
     851                 :          0 :                                         quoted = !quoted;
     852                 :            :                         }
     853         [ #  # ]:          0 :                         if (!*cp)
     854                 :          0 :                                 continue;
     855                 :          0 :                         *cp++ = '\0';
     856                 :            :                 }
     857                 :          0 :                 ep = cp;
     858                 :          0 :                 public = key_new(KEY_RSA1);
     859         [ #  # ]:          0 :                 if (key_read(public, &cp) != 1) {
     860                 :          0 :                         cp = ep;
     861                 :          0 :                         key_free(public);
     862                 :          0 :                         public = key_new(KEY_UNSPEC);
     863         [ #  # ]:          0 :                         if (key_read(public, &cp) != 1) {
     864                 :          0 :                                 key_free(public);
     865                 :          0 :                                 continue;
     866                 :            :                         }
     867                 :            :                 }
     868         [ #  # ]:          0 :                 comment = *cp ? cp : comment;
     869                 :          0 :                 fp = key_fingerprint(public, fptype, rep);
     870                 :          0 :                 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
     871         [ #  # ]:          0 :                 printf("%u %s %s (%s)\n", key_size(public), fp,
     872                 :          0 :                     comment ? comment : "no comment", key_type(public));
     873         [ #  # ]:          0 :                 if (log_level >= SYSLOG_LEVEL_VERBOSE)
     874                 :            :                         printf("%s\n", ra);
     875                 :          0 :                 free(ra);
     876                 :          0 :                 free(fp);
     877                 :          0 :                 key_free(public);
     878                 :          0 :                 invalid = 0;
     879                 :            :         }
     880                 :          0 :         fclose(f);
     881                 :            : 
     882         [ #  # ]:          0 :         if (invalid) {
     883                 :            :                 printf("%s is not a public key file.\n", identity_file);
     884                 :          0 :                 exit(1);
     885                 :            :         }
     886                 :          0 :         exit(0);
     887                 :            : }
     888                 :            : 
     889                 :            : static void
     890                 :          0 : do_gen_all_hostkeys(struct passwd *pw)
     891                 :            : {
     892                 :            :         struct {
     893                 :            :                 char *key_type;
     894                 :            :                 char *key_type_display;
     895                 :            :                 char *path;
     896                 :          0 :         } key_types[] = {
     897                 :            :                 { "rsa1", "RSA1", _PATH_HOST_KEY_FILE },
     898                 :            :                 { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
     899                 :            :                 { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE },
     900                 :            : #ifdef OPENSSL_HAS_ECC
     901                 :            :                 { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
     902                 :            : #endif
     903                 :            :                 { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE },
     904                 :            :                 { NULL, NULL, NULL }
     905                 :            :         };
     906                 :            : 
     907                 :          0 :         int first = 0;
     908                 :            :         struct stat st;
     909                 :            :         Key *private, *public;
     910                 :            :         char comment[1024];
     911                 :            :         int i, type, fd;
     912                 :            :         FILE *f;
     913                 :            : 
     914         [ #  # ]:          0 :         for (i = 0; key_types[i].key_type; i++) {
     915         [ #  # ]:          0 :                 if (stat(key_types[i].path, &st) == 0)
     916                 :          0 :                         continue;
     917         [ #  # ]:          0 :                 if (errno != ENOENT) {
     918                 :          0 :                         printf("Could not stat %s: %s", key_types[i].path,
     919                 :            :                             strerror(errno));
     920                 :          0 :                         first = 0;
     921                 :          0 :                         continue;
     922                 :            :                 }
     923                 :            : 
     924         [ #  # ]:          0 :                 if (first == 0) {
     925                 :          0 :                         first = 1;
     926                 :          0 :                         printf("%s: generating new host keys: ", __progname);
     927                 :            :                 }
     928                 :          0 :                 printf("%s ", key_types[i].key_type_display);
     929                 :          0 :                 fflush(stdout);
     930                 :          0 :                 type = key_type_from_name(key_types[i].key_type);
     931                 :          0 :                 strlcpy(identity_file, key_types[i].path, sizeof(identity_file));
     932                 :          0 :                 bits = 0;
     933                 :          0 :                 type_bits_valid(type, &bits);
     934                 :          0 :                 private = key_generate(type, bits);
     935         [ #  # ]:          0 :                 if (private == NULL) {
     936                 :          0 :                         fprintf(stderr, "key_generate failed\n");
     937                 :          0 :                         first = 0;
     938                 :          0 :                         continue;
     939                 :            :                 }
     940                 :          0 :                 public  = key_from_private(private);
     941                 :          0 :                 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
     942                 :            :                     hostname);
     943         [ #  # ]:          0 :                 if (!key_save_private(private, identity_file, "", comment,
     944                 :            :                     use_new_format, new_format_cipher, rounds)) {
     945                 :            :                         printf("Saving the key failed: %s.\n", identity_file);
     946                 :          0 :                         key_free(private);
     947                 :          0 :                         key_free(public);
     948                 :          0 :                         first = 0;
     949                 :          0 :                         continue;
     950                 :            :                 }
     951                 :          0 :                 key_free(private);
     952                 :          0 :                 strlcat(identity_file, ".pub", sizeof(identity_file));
     953                 :          0 :                 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
     954         [ #  # ]:          0 :                 if (fd == -1) {
     955                 :            :                         printf("Could not save your public key in %s\n",
     956                 :            :                             identity_file);
     957                 :          0 :                         key_free(public);
     958                 :          0 :                         first = 0;
     959                 :          0 :                         continue;
     960                 :            :                 }
     961                 :          0 :                 f = fdopen(fd, "w");
     962         [ #  # ]:          0 :                 if (f == NULL) {
     963                 :            :                         printf("fdopen %s failed\n", identity_file);
     964                 :          0 :                         key_free(public);
     965                 :          0 :                         first = 0;
     966                 :          0 :                         continue;
     967                 :            :                 }
     968         [ #  # ]:          0 :                 if (!key_write(public, f)) {
     969                 :          0 :                         fprintf(stderr, "write key failed\n");
     970                 :          0 :                         key_free(public);
     971                 :          0 :                         first = 0;
     972                 :          0 :                         continue;
     973                 :            :                 }
     974                 :            :                 fprintf(f, " %s\n", comment);
     975                 :          0 :                 fclose(f);
     976                 :          0 :                 key_free(public);
     977                 :            : 
     978                 :            :         }
     979         [ #  # ]:          0 :         if (first != 0)
     980                 :            :                 printf("\n");
     981                 :          0 : }
     982                 :            : 
     983                 :            : static void
     984                 :          0 : printhost(FILE *f, const char *name, Key *public, int ca, int hash)
     985                 :            : {
     986         [ #  # ]:          0 :         if (print_fingerprint) {
     987                 :            :                 enum fp_rep rep;
     988                 :            :                 enum fp_type fptype;
     989                 :            :                 char *fp, *ra;
     990                 :            : 
     991                 :          0 :                 fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
     992                 :          0 :                 rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
     993                 :          0 :                 fp = key_fingerprint(public, fptype, rep);
     994                 :          0 :                 ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
     995                 :          0 :                 printf("%u %s %s (%s)\n", key_size(public), fp, name,
     996                 :            :                     key_type(public));
     997         [ #  # ]:          0 :                 if (log_level >= SYSLOG_LEVEL_VERBOSE)
     998                 :            :                         printf("%s\n", ra);
     999                 :          0 :                 free(ra);
    1000                 :          0 :                 free(fp);
    1001                 :            :         } else {
    1002 [ #  # ][ #  # ]:          0 :                 if (hash && (name = host_hash(name, NULL, 0)) == NULL)
    1003                 :          0 :                         fatal("hash_host failed");
    1004 [ #  # ][ #  # ]:          0 :                 fprintf(f, "%s%s%s ", ca ? CA_MARKER : "", ca ? " " : "", name);
    1005         [ #  # ]:          0 :                 if (!key_write(public, f))
    1006                 :          0 :                         fatal("key_write failed");
    1007                 :            :                 fprintf(f, "\n");
    1008                 :            :         }
    1009                 :          0 : }
    1010                 :            : 
    1011                 :            : static void
    1012                 :          0 : do_known_hosts(struct passwd *pw, const char *name)
    1013                 :            : {
    1014                 :          0 :         FILE *in, *out = stdout;
    1015                 :            :         Key *pub;
    1016                 :            :         char *cp, *cp2, *kp, *kp2;
    1017                 :            :         char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
    1018                 :          0 :         int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
    1019                 :            :         int ca;
    1020                 :          0 :         int found_key = 0;
    1021                 :            : 
    1022         [ #  # ]:          0 :         if (!have_identity) {
    1023                 :          0 :                 cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
    1024         [ #  # ]:          0 :                 if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
    1025                 :            :                     sizeof(identity_file))
    1026                 :          0 :                         fatal("Specified known hosts path too long");
    1027                 :          0 :                 free(cp);
    1028                 :          0 :                 have_identity = 1;
    1029                 :            :         }
    1030         [ #  # ]:          0 :         if ((in = fopen(identity_file, "r")) == NULL)
    1031                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
    1032                 :            : 
    1033                 :            :         /*
    1034                 :            :          * Find hosts goes to stdout, hash and deletions happen in-place
    1035                 :            :          * A corner case is ssh-keygen -HF foo, which should go to stdout
    1036                 :            :          */
    1037 [ #  # ][ #  # ]:          0 :         if (!find_host && (hash_hosts || delete_host)) {
                 [ #  # ]
    1038   [ #  #  #  # ]:          0 :                 if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
    1039         [ #  # ]:          0 :                     strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
    1040         [ #  # ]:          0 :                     strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
    1041                 :          0 :                     strlcat(old, ".old", sizeof(old)) >= sizeof(old))
    1042                 :          0 :                         fatal("known_hosts path too long");
    1043                 :          0 :                 umask(077);
    1044         [ #  # ]:          0 :                 if ((c = mkstemp(tmp)) == -1)
    1045                 :          0 :                         fatal("mkstemp: %s", strerror(errno));
    1046         [ #  # ]:          0 :                 if ((out = fdopen(c, "w")) == NULL) {
    1047                 :          0 :                         c = errno;
    1048                 :          0 :                         unlink(tmp);
    1049                 :          0 :                         fatal("fdopen: %s", strerror(c));
    1050                 :            :                 }
    1051                 :            :                 inplace = 1;
    1052                 :            :         }
    1053                 :            : 
    1054         [ #  # ]:          0 :         while (fgets(line, sizeof(line), in)) {
    1055         [ #  # ]:          0 :                 if ((cp = strchr(line, '\n')) == NULL) {
    1056                 :          0 :                         error("line %d too long: %.40s...", num + 1, line);
    1057                 :          0 :                         skip = 1;
    1058                 :          0 :                         invalid = 1;
    1059                 :          0 :                         continue;
    1060                 :            :                 }
    1061                 :          0 :                 num++;
    1062         [ #  # ]:          0 :                 if (skip) {
    1063                 :          0 :                         skip = 0;
    1064                 :          0 :                         continue;
    1065                 :            :                 }
    1066                 :          0 :                 *cp = '\0';
    1067                 :            : 
    1068                 :            :                 /* Skip leading whitespace, empty and comment lines. */
    1069         [ #  # ]:          0 :                 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
    1070                 :            :                         ;
    1071 [ #  # ][ #  # ]:          0 :                 if (!*cp || *cp == '\n' || *cp == '#') {
    1072         [ #  # ]:          0 :                         if (inplace)
    1073                 :          0 :                                 fprintf(out, "%s\n", cp);
    1074                 :          0 :                         continue;
    1075                 :            :                 }
    1076                 :            :                 /* Check whether this is a CA key */
    1077 [ #  # ][ #  # ]:          0 :                 if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 &&
    1078                 :          0 :                     (cp[sizeof(CA_MARKER) - 1] == ' ' ||
    1079                 :            :                     cp[sizeof(CA_MARKER) - 1] == '\t')) {
    1080                 :          0 :                         ca = 1;
    1081                 :          0 :                         cp += sizeof(CA_MARKER);
    1082                 :            :                 } else
    1083                 :            :                         ca = 0;
    1084                 :            : 
    1085                 :            :                 /* Find the end of the host name portion. */
    1086 [ #  # ][ #  # ]:          0 :                 for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
    1087                 :            :                         ;
    1088                 :            : 
    1089 [ #  # ][ #  # ]:          0 :                 if (*kp == '\0' || *(kp + 1) == '\0') {
    1090                 :          0 :                         error("line %d missing key: %.40s...",
    1091                 :            :                             num, line);
    1092                 :          0 :                         invalid = 1;
    1093                 :          0 :                         continue;
    1094                 :            :                 }
    1095                 :          0 :                 *kp++ = '\0';
    1096                 :          0 :                 kp2 = kp;
    1097                 :            : 
    1098                 :          0 :                 pub = key_new(KEY_RSA1);
    1099         [ #  # ]:          0 :                 if (key_read(pub, &kp) != 1) {
    1100                 :          0 :                         kp = kp2;
    1101                 :          0 :                         key_free(pub);
    1102                 :          0 :                         pub = key_new(KEY_UNSPEC);
    1103         [ #  # ]:          0 :                         if (key_read(pub, &kp) != 1) {
    1104                 :          0 :                                 error("line %d invalid key: %.40s...",
    1105                 :            :                                     num, line);
    1106                 :          0 :                                 key_free(pub);
    1107                 :          0 :                                 invalid = 1;
    1108                 :          0 :                                 continue;
    1109                 :            :                         }
    1110                 :            :                 }
    1111                 :            : 
    1112         [ #  # ]:          0 :                 if (*cp == HASH_DELIM) {
    1113 [ #  # ][ #  # ]:          0 :                         if (find_host || delete_host) {
    1114                 :          0 :                                 cp2 = host_hash(name, cp, strlen(cp));
    1115         [ #  # ]:          0 :                                 if (cp2 == NULL) {
    1116                 :          0 :                                         error("line %d: invalid hashed "
    1117                 :            :                                             "name: %.64s...", num, line);
    1118                 :          0 :                                         invalid = 1;
    1119                 :          0 :                                         continue;
    1120                 :            :                                 }
    1121                 :          0 :                                 c = (strcmp(cp2, cp) == 0);
    1122 [ #  # ][ #  # ]:          0 :                                 if (find_host && c) {
    1123         [ #  # ]:          0 :                                         if (!quiet)
    1124         [ #  # ]:          0 :                                                 printf("# Host %s found: "
    1125                 :            :                                                     "line %d type %s%s\n", name,
    1126                 :            :                                                     num, key_type(pub),
    1127                 :            :                                                     ca ? " (CA key)" : "");
    1128                 :          0 :                                         printhost(out, cp, pub, ca, 0);
    1129                 :          0 :                                         found_key = 1;
    1130                 :            :                                 }
    1131         [ #  # ]:          0 :                                 if (delete_host) {
    1132         [ #  # ]:          0 :                                         if (!c && !ca)
    1133                 :          0 :                                                 printhost(out, cp, pub, ca, 0);
    1134                 :            :                                         else
    1135                 :          0 :                                                 printf("# Host %s found: "
    1136                 :            :                                                     "line %d type %s\n", name,
    1137                 :            :                                                     num, key_type(pub));
    1138                 :            :                                 }
    1139         [ #  # ]:          0 :                         } else if (hash_hosts)
    1140                 :          0 :                                 printhost(out, cp, pub, ca, 0);
    1141                 :            :                 } else {
    1142 [ #  # ][ #  # ]:          0 :                         if (find_host || delete_host) {
    1143                 :          0 :                                 c = (match_hostname(name, cp,
    1144                 :          0 :                                     strlen(cp)) == 1);
    1145 [ #  # ][ #  # ]:          0 :                                 if (find_host && c) {
    1146         [ #  # ]:          0 :                                         if (!quiet)
    1147         [ #  # ]:          0 :                                                 printf("# Host %s found: "
    1148                 :            :                                                     "line %d type %s%s\n", name,
    1149                 :            :                                                     num, key_type(pub),
    1150                 :            :                                                     ca ? " (CA key)" : "");
    1151 [ #  # ][ #  # ]:          0 :                                         printhost(out, name, pub,
    1152                 :          0 :                                             ca, hash_hosts && !ca);
    1153                 :          0 :                                         found_key = 1;
    1154                 :            :                                 }
    1155         [ #  # ]:          0 :                                 if (delete_host) {
    1156         [ #  # ]:          0 :                                         if (!c && !ca)
    1157                 :          0 :                                                 printhost(out, cp, pub, ca, 0);
    1158                 :            :                                         else
    1159                 :          0 :                                                 printf("# Host %s found: "
    1160                 :            :                                                     "line %d type %s\n", name,
    1161                 :            :                                                     num, key_type(pub));
    1162                 :            :                                 }
    1163         [ #  # ]:          0 :                         } else if (hash_hosts) {
    1164         [ #  # ]:          0 :                                 for (cp2 = strsep(&cp, ",");
    1165         [ #  # ]:          0 :                                     cp2 != NULL && *cp2 != '\0';
    1166                 :          0 :                                     cp2 = strsep(&cp, ",")) {
    1167         [ #  # ]:          0 :                                         if (ca) {
    1168                 :          0 :                                                 fprintf(stderr, "Warning: "
    1169                 :            :                                                     "ignoring CA key for host: "
    1170                 :            :                                                     "%.64s\n", cp2);
    1171                 :          0 :                                                 printhost(out, cp2, pub, ca, 0);
    1172         [ #  # ]:          0 :                                         } else if (strcspn(cp2, "*?!") !=
    1173                 :          0 :                                             strlen(cp2)) {
    1174                 :          0 :                                                 fprintf(stderr, "Warning: "
    1175                 :            :                                                     "ignoring host name with "
    1176                 :            :                                                     "metacharacters: %.64s\n",
    1177                 :            :                                                     cp2);
    1178                 :          0 :                                                 printhost(out, cp2, pub, ca, 0);
    1179                 :            :                                         } else
    1180                 :          0 :                                                 printhost(out, cp2, pub, ca, 1);
    1181                 :            :                                 }
    1182                 :            :                                 has_unhashed = 1;
    1183                 :            :                         }
    1184                 :            :                 }
    1185                 :          0 :                 key_free(pub);
    1186                 :            :         }
    1187                 :          0 :         fclose(in);
    1188                 :            : 
    1189         [ #  # ]:          0 :         if (invalid) {
    1190                 :          0 :                 fprintf(stderr, "%s is not a valid known_hosts file.\n",
    1191                 :            :                     identity_file);
    1192         [ #  # ]:          0 :                 if (inplace) {
    1193                 :          0 :                         fprintf(stderr, "Not replacing existing known_hosts "
    1194                 :            :                             "file because of errors\n");
    1195                 :          0 :                         fclose(out);
    1196                 :          0 :                         unlink(tmp);
    1197                 :            :                 }
    1198                 :          0 :                 exit(1);
    1199                 :            :         }
    1200                 :            : 
    1201         [ #  # ]:          0 :         if (inplace) {
    1202                 :          0 :                 fclose(out);
    1203                 :            : 
    1204                 :            :                 /* Backup existing file */
    1205 [ #  # ][ #  # ]:          0 :                 if (unlink(old) == -1 && errno != ENOENT)
    1206                 :          0 :                         fatal("unlink %.100s: %s", old, strerror(errno));
    1207         [ #  # ]:          0 :                 if (link(identity_file, old) == -1)
    1208                 :          0 :                         fatal("link %.100s to %.100s: %s", identity_file, old,
    1209                 :          0 :                             strerror(errno));
    1210                 :            :                 /* Move new one into place */
    1211         [ #  # ]:          0 :                 if (rename(tmp, identity_file) == -1) {
    1212                 :          0 :                         error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
    1213                 :          0 :                             strerror(errno));
    1214                 :          0 :                         unlink(tmp);
    1215                 :          0 :                         unlink(old);
    1216                 :          0 :                         exit(1);
    1217                 :            :                 }
    1218                 :            : 
    1219                 :          0 :                 fprintf(stderr, "%s updated.\n", identity_file);
    1220                 :          0 :                 fprintf(stderr, "Original contents retained as %s\n", old);
    1221         [ #  # ]:          0 :                 if (has_unhashed) {
    1222                 :          0 :                         fprintf(stderr, "WARNING: %s contains unhashed "
    1223                 :            :                             "entries\n", old);
    1224                 :          0 :                         fprintf(stderr, "Delete this file to ensure privacy "
    1225                 :            :                             "of hostnames\n");
    1226                 :            :                 }
    1227                 :            :         }
    1228                 :            : 
    1229 [ #  # ][ #  # ]:          0 :         exit (find_host && !found_key);
    1230                 :            : }
    1231                 :            : 
    1232                 :            : /*
    1233                 :            :  * Perform changing a passphrase.  The argument is the passwd structure
    1234                 :            :  * for the current user.
    1235                 :            :  */
    1236                 :            : static void
    1237                 :          3 : do_change_passphrase(struct passwd *pw)
    1238                 :            : {
    1239                 :            :         char *comment;
    1240                 :            :         char *old_passphrase, *passphrase1, *passphrase2;
    1241                 :            :         struct stat st;
    1242                 :            :         Key *private;
    1243                 :            : 
    1244         [ -  + ]:          3 :         if (!have_identity)
    1245                 :          0 :                 ask_filename(pw, "Enter file in which the key is");
    1246         [ -  + ]:          3 :         if (stat(identity_file, &st) < 0) {
    1247                 :          0 :                 perror(identity_file);
    1248                 :          0 :                 exit(1);
    1249                 :            :         }
    1250                 :            :         /* Try to load the file with empty passphrase. */
    1251                 :          3 :         private = key_load_private(identity_file, "", &comment);
    1252         [ +  - ]:          3 :         if (private == NULL) {
    1253         [ +  - ]:          3 :                 if (identity_passphrase)
    1254                 :          3 :                         old_passphrase = xstrdup(identity_passphrase);
    1255                 :            :                 else
    1256                 :          0 :                         old_passphrase =
    1257                 :            :                             read_passphrase("Enter old passphrase: ",
    1258                 :            :                             RP_ALLOW_STDIN);
    1259                 :          3 :                 private = key_load_private(identity_file, old_passphrase,
    1260                 :            :                     &comment);
    1261                 :          3 :                 explicit_bzero(old_passphrase, strlen(old_passphrase));
    1262                 :          3 :                 free(old_passphrase);
    1263         [ -  + ]:          3 :                 if (private == NULL) {
    1264                 :            :                         printf("Bad passphrase.\n");
    1265                 :          0 :                         exit(1);
    1266                 :            :                 }
    1267                 :            :         }
    1268                 :          3 :         printf("Key has comment '%s'\n", comment);
    1269                 :            : 
    1270                 :            :         /* Ask the new passphrase (twice). */
    1271         [ +  - ]:          3 :         if (identity_new_passphrase) {
    1272                 :          3 :                 passphrase1 = xstrdup(identity_new_passphrase);
    1273                 :          3 :                 passphrase2 = NULL;
    1274                 :            :         } else {
    1275                 :          0 :                 passphrase1 =
    1276                 :            :                         read_passphrase("Enter new passphrase (empty for no "
    1277                 :            :                             "passphrase): ", RP_ALLOW_STDIN);
    1278                 :          0 :                 passphrase2 = read_passphrase("Enter same passphrase again: ",
    1279                 :            :                     RP_ALLOW_STDIN);
    1280                 :            : 
    1281                 :            :                 /* Verify that they are the same. */
    1282         [ #  # ]:          0 :                 if (strcmp(passphrase1, passphrase2) != 0) {
    1283                 :          0 :                         explicit_bzero(passphrase1, strlen(passphrase1));
    1284                 :          0 :                         explicit_bzero(passphrase2, strlen(passphrase2));
    1285                 :          0 :                         free(passphrase1);
    1286                 :          0 :                         free(passphrase2);
    1287                 :            :                         printf("Pass phrases do not match.  Try again.\n");
    1288                 :          0 :                         exit(1);
    1289                 :            :                 }
    1290                 :            :                 /* Destroy the other copy. */
    1291                 :          0 :                 explicit_bzero(passphrase2, strlen(passphrase2));
    1292                 :          0 :                 free(passphrase2);
    1293                 :            :         }
    1294                 :            : 
    1295                 :            :         /* Save the file using the new passphrase. */
    1296         [ -  + ]:          3 :         if (!key_save_private(private, identity_file, passphrase1, comment,
    1297                 :            :             use_new_format, new_format_cipher, rounds)) {
    1298                 :            :                 printf("Saving the key failed: %s.\n", identity_file);
    1299                 :          0 :                 explicit_bzero(passphrase1, strlen(passphrase1));
    1300                 :          0 :                 free(passphrase1);
    1301                 :          0 :                 key_free(private);
    1302                 :          0 :                 free(comment);
    1303                 :          0 :                 exit(1);
    1304                 :            :         }
    1305                 :            :         /* Destroy the passphrase and the copy of the key in memory. */
    1306                 :          3 :         explicit_bzero(passphrase1, strlen(passphrase1));
    1307                 :          3 :         free(passphrase1);
    1308                 :          3 :         key_free(private);               /* Destroys contents */
    1309                 :          3 :         free(comment);
    1310                 :            : 
    1311                 :            :         printf("Your identification has been saved with the new passphrase.\n");
    1312                 :          3 :         exit(0);
    1313                 :            : }
    1314                 :            : 
    1315                 :            : /*
    1316                 :            :  * Print the SSHFP RR.
    1317                 :            :  */
    1318                 :            : static int
    1319                 :          0 : do_print_resource_record(struct passwd *pw, char *fname, char *hname)
    1320                 :            : {
    1321                 :            :         Key *public;
    1322                 :          0 :         char *comment = NULL;
    1323                 :            :         struct stat st;
    1324                 :            : 
    1325         [ #  # ]:          0 :         if (fname == NULL)
    1326                 :          0 :                 fatal("%s: no filename", __func__);
    1327         [ #  # ]:          0 :         if (stat(fname, &st) < 0) {
    1328         [ #  # ]:          0 :                 if (errno == ENOENT)
    1329                 :            :                         return 0;
    1330                 :          0 :                 perror(fname);
    1331                 :          0 :                 exit(1);
    1332                 :            :         }
    1333                 :          0 :         public = key_load_public(fname, &comment);
    1334         [ #  # ]:          0 :         if (public != NULL) {
    1335                 :          0 :                 export_dns_rr(hname, public, stdout, print_generic);
    1336                 :          0 :                 key_free(public);
    1337                 :          0 :                 free(comment);
    1338                 :            :                 return 1;
    1339                 :            :         }
    1340         [ #  # ]:          0 :         if (comment)
    1341                 :          0 :                 free(comment);
    1342                 :            : 
    1343                 :            :         printf("failed to read v2 public key from %s.\n", fname);
    1344                 :          0 :         exit(1);
    1345                 :            : }
    1346                 :            : 
    1347                 :            : /*
    1348                 :            :  * Change the comment of a private key file.
    1349                 :            :  */
    1350                 :            : static void
    1351                 :          0 : do_change_comment(struct passwd *pw)
    1352                 :            : {
    1353                 :            :         char new_comment[1024], *comment, *passphrase;
    1354                 :            :         Key *private;
    1355                 :            :         Key *public;
    1356                 :            :         struct stat st;
    1357                 :            :         FILE *f;
    1358                 :            :         int fd;
    1359                 :            : 
    1360         [ #  # ]:          0 :         if (!have_identity)
    1361                 :          0 :                 ask_filename(pw, "Enter file in which the key is");
    1362         [ #  # ]:          0 :         if (stat(identity_file, &st) < 0) {
    1363                 :          0 :                 perror(identity_file);
    1364                 :          0 :                 exit(1);
    1365                 :            :         }
    1366                 :          0 :         private = key_load_private(identity_file, "", &comment);
    1367         [ #  # ]:          0 :         if (private == NULL) {
    1368         [ #  # ]:          0 :                 if (identity_passphrase)
    1369                 :          0 :                         passphrase = xstrdup(identity_passphrase);
    1370         [ #  # ]:          0 :                 else if (identity_new_passphrase)
    1371                 :          0 :                         passphrase = xstrdup(identity_new_passphrase);
    1372                 :            :                 else
    1373                 :          0 :                         passphrase = read_passphrase("Enter passphrase: ",
    1374                 :            :                             RP_ALLOW_STDIN);
    1375                 :            :                 /* Try to load using the passphrase. */
    1376                 :          0 :                 private = key_load_private(identity_file, passphrase, &comment);
    1377         [ #  # ]:          0 :                 if (private == NULL) {
    1378                 :          0 :                         explicit_bzero(passphrase, strlen(passphrase));
    1379                 :          0 :                         free(passphrase);
    1380                 :            :                         printf("Bad passphrase.\n");
    1381                 :          0 :                         exit(1);
    1382                 :            :                 }
    1383                 :            :         } else {
    1384                 :          0 :                 passphrase = xstrdup("");
    1385                 :            :         }
    1386         [ #  # ]:          0 :         if (private->type != KEY_RSA1) {
    1387                 :          0 :                 fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
    1388                 :          0 :                 key_free(private);
    1389                 :          0 :                 exit(1);
    1390                 :            :         }
    1391                 :          0 :         printf("Key now has comment '%s'\n", comment);
    1392                 :            : 
    1393         [ #  # ]:          0 :         if (identity_comment) {
    1394                 :          0 :                 strlcpy(new_comment, identity_comment, sizeof(new_comment));
    1395                 :            :         } else {
    1396                 :            :                 printf("Enter new comment: ");
    1397                 :          0 :                 fflush(stdout);
    1398         [ #  # ]:          0 :                 if (!fgets(new_comment, sizeof(new_comment), stdin)) {
    1399                 :          0 :                         explicit_bzero(passphrase, strlen(passphrase));
    1400                 :          0 :                         key_free(private);
    1401                 :          0 :                         exit(1);
    1402                 :            :                 }
    1403                 :          0 :                 new_comment[strcspn(new_comment, "\n")] = '\0';
    1404                 :            :         }
    1405                 :            : 
    1406                 :            :         /* Save the file using the new passphrase. */
    1407         [ #  # ]:          0 :         if (!key_save_private(private, identity_file, passphrase, new_comment,
    1408                 :            :             use_new_format, new_format_cipher, rounds)) {
    1409                 :            :                 printf("Saving the key failed: %s.\n", identity_file);
    1410                 :          0 :                 explicit_bzero(passphrase, strlen(passphrase));
    1411                 :          0 :                 free(passphrase);
    1412                 :          0 :                 key_free(private);
    1413                 :          0 :                 free(comment);
    1414                 :          0 :                 exit(1);
    1415                 :            :         }
    1416                 :          0 :         explicit_bzero(passphrase, strlen(passphrase));
    1417                 :          0 :         free(passphrase);
    1418                 :          0 :         public = key_from_private(private);
    1419                 :          0 :         key_free(private);
    1420                 :            : 
    1421                 :          0 :         strlcat(identity_file, ".pub", sizeof(identity_file));
    1422                 :          0 :         fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    1423         [ #  # ]:          0 :         if (fd == -1) {
    1424                 :            :                 printf("Could not save your public key in %s\n", identity_file);
    1425                 :          0 :                 exit(1);
    1426                 :            :         }
    1427                 :          0 :         f = fdopen(fd, "w");
    1428         [ #  # ]:          0 :         if (f == NULL) {
    1429                 :            :                 printf("fdopen %s failed\n", identity_file);
    1430                 :          0 :                 exit(1);
    1431                 :            :         }
    1432         [ #  # ]:          0 :         if (!key_write(public, f))
    1433                 :          0 :                 fprintf(stderr, "write key failed\n");
    1434                 :          0 :         key_free(public);
    1435                 :            :         fprintf(f, " %s\n", new_comment);
    1436                 :          0 :         fclose(f);
    1437                 :            : 
    1438                 :          0 :         free(comment);
    1439                 :            : 
    1440                 :            :         printf("The comment in your key file has been changed.\n");
    1441                 :          0 :         exit(0);
    1442                 :            : }
    1443                 :            : 
    1444                 :            : static const char *
    1445                 :          9 : fmt_validity(u_int64_t valid_from, u_int64_t valid_to)
    1446                 :            : {
    1447                 :            :         char from[32], to[32];
    1448                 :            :         static char ret[64];
    1449                 :            :         time_t tt;
    1450                 :            :         struct tm *tm;
    1451                 :            : 
    1452                 :          9 :         *from = *to = '\0';
    1453         [ -  + ]:          9 :         if (valid_from == 0 && valid_to == 0xffffffffffffffffULL)
    1454                 :            :                 return "forever";
    1455                 :            : 
    1456         [ #  # ]:          0 :         if (valid_from != 0) {
    1457                 :            :                 /* XXX revisit INT_MAX in 2038 :) */
    1458                 :          0 :                 tt = valid_from > INT_MAX ? INT_MAX : valid_from;
    1459                 :          0 :                 tm = localtime(&tt);
    1460                 :          0 :                 strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
    1461                 :            :         }
    1462         [ #  # ]:          0 :         if (valid_to != 0xffffffffffffffffULL) {
    1463                 :            :                 /* XXX revisit INT_MAX in 2038 :) */
    1464                 :          0 :                 tt = valid_to > INT_MAX ? INT_MAX : valid_to;
    1465                 :          0 :                 tm = localtime(&tt);
    1466                 :          0 :                 strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
    1467                 :            :         }
    1468                 :            : 
    1469         [ #  # ]:          0 :         if (valid_from == 0) {
    1470                 :            :                 snprintf(ret, sizeof(ret), "before %s", to);
    1471                 :          0 :                 return ret;
    1472                 :            :         }
    1473         [ #  # ]:          0 :         if (valid_to == 0xffffffffffffffffULL) {
    1474                 :            :                 snprintf(ret, sizeof(ret), "after %s", from);
    1475                 :          0 :                 return ret;
    1476                 :            :         }
    1477                 :            : 
    1478                 :            :         snprintf(ret, sizeof(ret), "from %s to %s", from, to);
    1479                 :          0 :         return ret;
    1480                 :            : }
    1481                 :            : 
    1482                 :            : static void
    1483                 :        335 : add_flag_option(Buffer *c, const char *name)
    1484                 :            : {
    1485                 :        335 :         debug3("%s: %s", __func__, name);
    1486                 :        335 :         buffer_put_cstring(c, name);
    1487                 :        335 :         buffer_put_string(c, NULL, 0);
    1488                 :        335 : }
    1489                 :            : 
    1490                 :            : static void
    1491                 :         10 : add_string_option(Buffer *c, const char *name, const char *value)
    1492                 :            : {
    1493                 :            :         Buffer b;
    1494                 :            : 
    1495                 :         10 :         debug3("%s: %s=%s", __func__, name, value);
    1496                 :         10 :         buffer_init(&b);
    1497                 :         10 :         buffer_put_cstring(&b, value);
    1498                 :            : 
    1499                 :         10 :         buffer_put_cstring(c, name);
    1500                 :         10 :         buffer_put_string(c, buffer_ptr(&b), buffer_len(&b));
    1501                 :            : 
    1502                 :         10 :         buffer_free(&b);
    1503                 :         10 : }
    1504                 :            : 
    1505                 :            : #define OPTIONS_CRITICAL        1
    1506                 :            : #define OPTIONS_EXTENSIONS      2
    1507                 :            : static void
    1508                 :        159 : prepare_options_buf(Buffer *c, int which)
    1509                 :            : {
    1510                 :        159 :         buffer_clear(c);
    1511 [ +  + ][ +  + ]:        159 :         if ((which & OPTIONS_CRITICAL) != 0 &&
    1512                 :         99 :             certflags_command != NULL)
    1513                 :          6 :                 add_string_option(c, "force-command", certflags_command);
    1514 [ +  + ][ +  + ]:        159 :         if ((which & OPTIONS_EXTENSIONS) != 0 &&
    1515                 :         99 :             (certflags_flags & CERTOPT_X_FWD) != 0)
    1516                 :         67 :                 add_flag_option(c, "permit-X11-forwarding");
    1517 [ +  + ][ +  + ]:        159 :         if ((which & OPTIONS_EXTENSIONS) != 0 &&
    1518                 :         99 :             (certflags_flags & CERTOPT_AGENT_FWD) != 0)
    1519                 :         67 :                 add_flag_option(c, "permit-agent-forwarding");
    1520 [ +  + ][ +  + ]:        159 :         if ((which & OPTIONS_EXTENSIONS) != 0 &&
    1521                 :         99 :             (certflags_flags & CERTOPT_PORT_FWD) != 0)
    1522                 :         67 :                 add_flag_option(c, "permit-port-forwarding");
    1523 [ +  + ][ +  + ]:        159 :         if ((which & OPTIONS_EXTENSIONS) != 0 &&
    1524                 :         99 :             (certflags_flags & CERTOPT_PTY) != 0)
    1525                 :         67 :                 add_flag_option(c, "permit-pty");
    1526 [ +  + ][ +  + ]:        159 :         if ((which & OPTIONS_EXTENSIONS) != 0 &&
    1527                 :         99 :             (certflags_flags & CERTOPT_USER_RC) != 0)
    1528                 :         67 :                 add_flag_option(c, "permit-user-rc");
    1529 [ +  + ][ +  + ]:        159 :         if ((which & OPTIONS_CRITICAL) != 0 &&
    1530                 :         99 :             certflags_src_addr != NULL)
    1531                 :          4 :                 add_string_option(c, "source-address", certflags_src_addr);
    1532                 :        159 : }
    1533                 :            : 
    1534                 :            : static Key *
    1535                 :          0 : load_pkcs11_key(char *path)
    1536                 :            : {
    1537                 :            : #ifdef ENABLE_PKCS11
    1538                 :          0 :         Key **keys = NULL, *public, *private = NULL;
    1539                 :            :         int i, nkeys;
    1540                 :            : 
    1541         [ #  # ]:          0 :         if ((public = key_load_public(path, NULL)) == NULL)
    1542                 :          0 :                 fatal("Couldn't load CA public key \"%s\"", path);
    1543                 :            : 
    1544                 :          0 :         nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys);
    1545                 :          0 :         debug3("%s: %d keys", __func__, nkeys);
    1546         [ #  # ]:          0 :         if (nkeys <= 0)
    1547                 :          0 :                 fatal("cannot read public key from pkcs11");
    1548         [ #  # ]:          0 :         for (i = 0; i < nkeys; i++) {
    1549         [ #  # ]:          0 :                 if (key_equal_public(public, keys[i])) {
    1550                 :          0 :                         private = keys[i];
    1551                 :          0 :                         continue;
    1552                 :            :                 }
    1553                 :          0 :                 key_free(keys[i]);
    1554                 :            :         }
    1555                 :          0 :         free(keys);
    1556                 :          0 :         key_free(public);
    1557                 :          0 :         return private;
    1558                 :            : #else
    1559                 :            :         fatal("no pkcs11 support");
    1560                 :            : #endif /* ENABLE_PKCS11 */
    1561                 :            : }
    1562                 :            : 
    1563                 :            : static void
    1564                 :         99 : do_ca_sign(struct passwd *pw, int argc, char **argv)
    1565                 :            : {
    1566                 :            :         int i, fd;
    1567                 :            :         u_int n;
    1568                 :            :         Key *ca, *public;
    1569                 :         99 :         char *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
    1570                 :            :         FILE *f;
    1571                 :         99 :         int v00 = 0; /* legacy keys */
    1572                 :            : 
    1573         [ +  + ]:         99 :         if (key_type_name != NULL) {
    1574      [ +  -  - ]:         43 :                 switch (key_type_from_name(key_type_name)) {
    1575                 :            :                 case KEY_RSA_CERT_V00:
    1576                 :            :                 case KEY_DSA_CERT_V00:
    1577                 :            :                         v00 = 1;
    1578                 :            :                         break;
    1579                 :            :                 case KEY_UNSPEC:
    1580         [ +  + ]:         43 :                         if (strcasecmp(key_type_name, "v00") == 0) {
    1581                 :            :                                 v00 = 1;
    1582                 :            :                                 break;
    1583         [ -  + ]:          4 :                         } else if (strcasecmp(key_type_name, "v01") == 0)
    1584                 :            :                                 break;
    1585                 :            :                         /* FALLTHROUGH */
    1586                 :            :                 default:
    1587                 :          0 :                         fprintf(stderr, "unknown key type %s\n", key_type_name);
    1588                 :          0 :                         exit(1);
    1589                 :            :                 }
    1590                 :            :         }
    1591                 :            : 
    1592                 :         99 :         pkcs11_init(1);
    1593                 :         99 :         tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
    1594         [ -  + ]:         99 :         if (pkcs11provider != NULL) {
    1595         [ #  # ]:          0 :                 if ((ca = load_pkcs11_key(tmp)) == NULL)
    1596                 :          0 :                         fatal("No PKCS#11 key matching %s found", ca_key_path);
    1597         [ -  + ]:         99 :         } else if ((ca = load_identity(tmp)) == NULL)
    1598                 :          0 :                 fatal("Couldn't load CA key \"%s\"", tmp);
    1599                 :         99 :         free(tmp);
    1600                 :            : 
    1601         [ +  + ]:        198 :         for (i = 0; i < argc; i++) {
    1602                 :            :                 /* Split list of principals */
    1603                 :         99 :                 n = 0;
    1604         [ +  + ]:         99 :                 if (cert_principals != NULL) {
    1605                 :         72 :                         otmp = tmp = xstrdup(cert_principals);
    1606                 :         72 :                         plist = NULL;
    1607         [ +  + ]:        188 :                         for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
    1608                 :        116 :                                 plist = xrealloc(plist, n + 1, sizeof(*plist));
    1609         [ -  + ]:        116 :                                 if (*(plist[n] = xstrdup(cp)) == '\0')
    1610                 :          0 :                                         fatal("Empty principal name");
    1611                 :            :                         }
    1612                 :         72 :                         free(otmp);
    1613                 :            :                 }
    1614                 :            :         
    1615                 :         99 :                 tmp = tilde_expand_filename(argv[i], pw->pw_uid);
    1616         [ -  + ]:         99 :                 if ((public = key_load_public(tmp, &comment)) == NULL)
    1617                 :          0 :                         fatal("%s: unable to open \"%s\"", __func__, tmp);
    1618         [ -  + ]:         99 :                 if (public->type != KEY_RSA && public->type != KEY_DSA &&
    1619                 :         99 :                     public->type != KEY_ECDSA && public->type != KEY_ED25519)
    1620                 :          0 :                         fatal("%s: key \"%s\" type %s cannot be certified",
    1621                 :            :                             __func__, tmp, key_type(public));
    1622                 :            : 
    1623                 :            :                 /* Prepare certificate to sign */
    1624         [ -  + ]:         99 :                 if (key_to_certified(public, v00) != 0)
    1625                 :          0 :                         fatal("Could not upgrade key %s to certificate", tmp);
    1626                 :         99 :                 public->cert->type = cert_key_type;
    1627                 :         99 :                 public->cert->serial = (u_int64_t)cert_serial;
    1628                 :         99 :                 public->cert->key_id = xstrdup(cert_key_id);
    1629                 :         99 :                 public->cert->nprincipals = n;
    1630                 :         99 :                 public->cert->principals = plist;
    1631                 :         99 :                 public->cert->valid_after = cert_valid_from;
    1632                 :         99 :                 public->cert->valid_before = cert_valid_to;
    1633         [ +  + ]:         99 :                 if (v00) {
    1634                 :         39 :                         prepare_options_buf(&public->cert->critical,
    1635                 :            :                             OPTIONS_CRITICAL|OPTIONS_EXTENSIONS);
    1636                 :            :                 } else {
    1637                 :         60 :                         prepare_options_buf(&public->cert->critical,
    1638                 :            :                             OPTIONS_CRITICAL);
    1639                 :         60 :                         prepare_options_buf(&public->cert->extensions,
    1640                 :            :                             OPTIONS_EXTENSIONS);
    1641                 :            :                 }
    1642                 :         99 :                 public->cert->signature_key = key_from_private(ca);
    1643                 :            : 
    1644         [ -  + ]:         99 :                 if (key_certify(public, ca) != 0)
    1645                 :          0 :                         fatal("Couldn't not certify key %s", tmp);
    1646                 :            : 
    1647 [ +  - ][ -  + ]:         99 :                 if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
    1648                 :          0 :                         *cp = '\0';
    1649                 :         99 :                 xasprintf(&out, "%s-cert.pub", tmp);
    1650                 :         99 :                 free(tmp);
    1651                 :            : 
    1652         [ -  + ]:         99 :                 if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
    1653                 :          0 :                         fatal("Could not open \"%s\" for writing: %s", out,
    1654                 :          0 :                             strerror(errno));
    1655         [ -  + ]:         99 :                 if ((f = fdopen(fd, "w")) == NULL)
    1656                 :          0 :                         fatal("%s: fdopen: %s", __func__, strerror(errno));
    1657         [ -  + ]:         99 :                 if (!key_write(public, f))
    1658                 :          0 :                         fatal("Could not write certified key to %s", out);
    1659                 :         99 :                 fprintf(f, " %s\n", comment);
    1660                 :         99 :                 fclose(f);
    1661                 :            : 
    1662         [ +  + ]:         99 :                 if (!quiet) {
    1663 [ -  + ][ +  - ]:          9 :                         logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
    1664                 :            :                             "valid %s", key_cert_type(public), 
    1665                 :            :                             out, public->cert->key_id,
    1666                 :          9 :                             (unsigned long long)public->cert->serial,
    1667                 :            :                             cert_principals != NULL ? " for " : "",
    1668                 :          9 :                             cert_principals != NULL ? cert_principals : "",
    1669                 :            :                             fmt_validity(cert_valid_from, cert_valid_to));
    1670                 :            :                 }
    1671                 :            : 
    1672                 :         99 :                 key_free(public);
    1673                 :         99 :                 free(out);
    1674                 :            :         }
    1675                 :         99 :         pkcs11_terminate();
    1676                 :         99 :         exit(0);
    1677                 :            : }
    1678                 :            : 
    1679                 :            : static u_int64_t
    1680                 :         12 : parse_relative_time(const char *s, time_t now)
    1681                 :            : {
    1682                 :            :         int64_t mul, secs;
    1683                 :            : 
    1684         [ +  + ]:         12 :         mul = *s == '-' ? -1 : 1;
    1685                 :            : 
    1686         [ -  + ]:         12 :         if ((secs = convtime(s + 1)) == -1)
    1687                 :          0 :                 fatal("Invalid relative certificate time %s", s);
    1688         [ -  + ]:         12 :         if (mul == -1 && secs > now)
    1689                 :          0 :                 fatal("Certificate time %s cannot be represented", s);
    1690                 :         12 :         return now + (u_int64_t)(secs * mul);
    1691                 :            : }
    1692                 :            : 
    1693                 :            : static u_int64_t
    1694                 :         24 : parse_absolute_time(const char *s)
    1695                 :            : {
    1696                 :            :         struct tm tm;
    1697                 :            :         time_t tt;
    1698                 :            :         char buf[32], *fmt;
    1699                 :            : 
    1700                 :            :         /*
    1701                 :            :          * POSIX strptime says "The application shall ensure that there 
    1702                 :            :          * is white-space or other non-alphanumeric characters between
    1703                 :            :          * any two conversion specifications" so arrange things this way.
    1704                 :            :          */
    1705      [ +  -  - ]:         24 :         switch (strlen(s)) {
    1706                 :            :         case 8:
    1707                 :         24 :                 fmt = "%Y-%m-%d";
    1708                 :         24 :                 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6);
    1709                 :            :                 break;
    1710                 :            :         case 14:
    1711                 :          0 :                 fmt = "%Y-%m-%dT%H:%M:%S";
    1712                 :          0 :                 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s",
    1713                 :            :                     s, s + 4, s + 6, s + 8, s + 10, s + 12);
    1714                 :            :                 break;
    1715                 :            :         default:
    1716                 :          0 :                 fatal("Invalid certificate time format %s", s);
    1717                 :            :         }
    1718                 :            : 
    1719                 :            :         memset(&tm, 0, sizeof(tm));
    1720         [ -  + ]:         24 :         if (strptime(buf, fmt, &tm) == NULL)
    1721                 :          0 :                 fatal("Invalid certificate time %s", s);
    1722         [ -  + ]:         24 :         if ((tt = mktime(&tm)) < 0)
    1723                 :          0 :                 fatal("Certificate time %s cannot be represented", s);
    1724                 :         24 :         return (u_int64_t)tt;
    1725                 :            : }
    1726                 :            : 
    1727                 :            : static void
    1728                 :         18 : parse_cert_times(char *timespec)
    1729                 :            : {
    1730                 :            :         char *from, *to;
    1731                 :         18 :         time_t now = time(NULL);
    1732                 :            :         int64_t secs;
    1733                 :            : 
    1734                 :            :         /* +timespec relative to now */
    1735 [ -  + ][ #  # ]:         18 :         if (*timespec == '+' && strchr(timespec, ':') == NULL) {
    1736         [ #  # ]:          0 :                 if ((secs = convtime(timespec + 1)) == -1)
    1737                 :          0 :                         fatal("Invalid relative certificate life %s", timespec);
    1738                 :          0 :                 cert_valid_to = now + secs;
    1739                 :            :                 /*
    1740                 :            :                  * Backdate certificate one minute to avoid problems on hosts
    1741                 :            :                  * with poorly-synchronised clocks.
    1742                 :            :                  */
    1743                 :          0 :                 cert_valid_from = ((now - 59)/ 60) * 60;
    1744                 :          0 :                 return;
    1745                 :            :         }
    1746                 :            : 
    1747                 :            :         /*
    1748                 :            :          * from:to, where
    1749                 :            :          * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
    1750                 :            :          *   to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
    1751                 :            :          */
    1752                 :         18 :         from = xstrdup(timespec);
    1753                 :         18 :         to = strchr(from, ':');
    1754 [ +  - ][ -  + ]:         18 :         if (to == NULL || from == to || *(to + 1) == '\0')
    1755                 :          0 :                 fatal("Invalid certificate life specification %s", timespec);
    1756                 :         18 :         *to++ = '\0';
    1757                 :            : 
    1758         [ +  + ]:         18 :         if (*from == '-' || *from == '+')
    1759                 :          6 :                 cert_valid_from = parse_relative_time(from, now);
    1760                 :            :         else
    1761                 :         12 :                 cert_valid_from = parse_absolute_time(from);
    1762                 :            : 
    1763         [ +  + ]:         18 :         if (*to == '-' || *to == '+')
    1764                 :          6 :                 cert_valid_to = parse_relative_time(to, now);
    1765                 :            :         else
    1766                 :         12 :                 cert_valid_to = parse_absolute_time(to);
    1767                 :            : 
    1768         [ -  + ]:         18 :         if (cert_valid_to <= cert_valid_from)
    1769                 :          0 :                 fatal("Empty certificate validity interval");
    1770                 :         18 :         free(from);
    1771                 :            : }
    1772                 :            : 
    1773                 :            : static void
    1774                 :         10 : add_cert_option(char *opt)
    1775                 :            : {
    1776                 :            :         char *val;
    1777                 :            : 
    1778         [ -  + ]:         10 :         if (strcasecmp(opt, "clear") == 0)
    1779                 :          0 :                 certflags_flags = 0;
    1780         [ -  + ]:         10 :         else if (strcasecmp(opt, "no-x11-forwarding") == 0)
    1781                 :          0 :                 certflags_flags &= ~CERTOPT_X_FWD;
    1782         [ -  + ]:         10 :         else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
    1783                 :          0 :                 certflags_flags |= CERTOPT_X_FWD;
    1784         [ -  + ]:         10 :         else if (strcasecmp(opt, "no-agent-forwarding") == 0)
    1785                 :          0 :                 certflags_flags &= ~CERTOPT_AGENT_FWD;
    1786         [ -  + ]:         10 :         else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
    1787                 :          0 :                 certflags_flags |= CERTOPT_AGENT_FWD;
    1788         [ -  + ]:         10 :         else if (strcasecmp(opt, "no-port-forwarding") == 0)
    1789                 :          0 :                 certflags_flags &= ~CERTOPT_PORT_FWD;
    1790         [ -  + ]:         10 :         else if (strcasecmp(opt, "permit-port-forwarding") == 0)
    1791                 :          0 :                 certflags_flags |= CERTOPT_PORT_FWD;
    1792         [ -  + ]:         10 :         else if (strcasecmp(opt, "no-pty") == 0)
    1793                 :          0 :                 certflags_flags &= ~CERTOPT_PTY;
    1794         [ -  + ]:         10 :         else if (strcasecmp(opt, "permit-pty") == 0)
    1795                 :          0 :                 certflags_flags |= CERTOPT_PTY;
    1796         [ -  + ]:         10 :         else if (strcasecmp(opt, "no-user-rc") == 0)
    1797                 :          0 :                 certflags_flags &= ~CERTOPT_USER_RC;
    1798         [ -  + ]:         10 :         else if (strcasecmp(opt, "permit-user-rc") == 0)
    1799                 :          0 :                 certflags_flags |= CERTOPT_USER_RC;
    1800         [ +  + ]:         10 :         else if (strncasecmp(opt, "force-command=", 14) == 0) {
    1801                 :          6 :                 val = opt + 14;
    1802         [ -  + ]:          6 :                 if (*val == '\0')
    1803                 :          0 :                         fatal("Empty force-command option");
    1804         [ -  + ]:          6 :                 if (certflags_command != NULL)
    1805                 :          0 :                         fatal("force-command already specified");
    1806                 :          6 :                 certflags_command = xstrdup(val);
    1807         [ +  - ]:          4 :         } else if (strncasecmp(opt, "source-address=", 15) == 0) {
    1808                 :          4 :                 val = opt + 15;
    1809         [ -  + ]:          4 :                 if (*val == '\0')
    1810                 :          0 :                         fatal("Empty source-address option");
    1811         [ -  + ]:          4 :                 if (certflags_src_addr != NULL)
    1812                 :          0 :                         fatal("source-address already specified");
    1813         [ -  + ]:          4 :                 if (addr_match_cidr_list(NULL, val) != 0)
    1814                 :          0 :                         fatal("Invalid source-address list");
    1815                 :          4 :                 certflags_src_addr = xstrdup(val);
    1816                 :            :         } else
    1817                 :          0 :                 fatal("Unsupported certificate option \"%s\"", opt);
    1818                 :         10 : }
    1819                 :            : 
    1820                 :            : static void
    1821                 :          0 : show_options(const Buffer *optbuf, int v00, int in_critical)
    1822                 :            : {
    1823                 :            :         char *name;
    1824                 :            :         u_char *data;
    1825                 :            :         u_int dlen;
    1826                 :            :         Buffer options, option;
    1827                 :            : 
    1828                 :          0 :         buffer_init(&options);
    1829                 :          0 :         buffer_append(&options, buffer_ptr(optbuf), buffer_len(optbuf));
    1830                 :            : 
    1831                 :          0 :         buffer_init(&option);
    1832         [ #  # ]:          0 :         while (buffer_len(&options) != 0) {
    1833                 :          0 :                 name = buffer_get_string(&options, NULL);
    1834                 :          0 :                 data = buffer_get_string_ptr(&options, &dlen);
    1835                 :          0 :                 buffer_append(&option, data, dlen);
    1836                 :            :                 printf("                %s", name);
    1837 [ #  # ][ #  # ]:          0 :                 if ((v00 || !in_critical) && 
    1838         [ #  # ]:          0 :                     (strcmp(name, "permit-X11-forwarding") == 0 ||
    1839         [ #  # ]:          0 :                     strcmp(name, "permit-agent-forwarding") == 0 ||
    1840         [ #  # ]:          0 :                     strcmp(name, "permit-port-forwarding") == 0 ||
    1841         [ #  # ]:          0 :                     strcmp(name, "permit-pty") == 0 ||
    1842                 :          0 :                     strcmp(name, "permit-user-rc") == 0))
    1843                 :            :                         printf("\n");
    1844 [ #  # ][ #  # ]:          0 :                 else if ((v00 || in_critical) &&
    1845         [ #  # ]:          0 :                     (strcmp(name, "force-command") == 0 ||
    1846                 :          0 :                     strcmp(name, "source-address") == 0)) {
    1847                 :          0 :                         data = buffer_get_string(&option, NULL);
    1848                 :            :                         printf(" %s\n", data);
    1849                 :          0 :                         free(data);
    1850                 :            :                 } else {
    1851                 :          0 :                         printf(" UNKNOWN OPTION (len %u)\n",
    1852                 :            :                             buffer_len(&option));
    1853                 :          0 :                         buffer_clear(&option);
    1854                 :            :                 }
    1855                 :          0 :                 free(name);
    1856         [ #  # ]:          0 :                 if (buffer_len(&option) != 0)
    1857                 :          0 :                         fatal("Option corrupt: extra data at end");
    1858                 :            :         }
    1859                 :          0 :         buffer_free(&option);
    1860                 :          0 :         buffer_free(&options);
    1861                 :          0 : }
    1862                 :            : 
    1863                 :            : static void
    1864                 :          0 : do_show_cert(struct passwd *pw)
    1865                 :            : {
    1866                 :            :         Key *key;
    1867                 :            :         struct stat st;
    1868                 :            :         char *key_fp, *ca_fp;
    1869                 :            :         u_int i, v00;
    1870                 :            : 
    1871         [ #  # ]:          0 :         if (!have_identity)
    1872                 :          0 :                 ask_filename(pw, "Enter file in which the key is");
    1873         [ #  # ]:          0 :         if (stat(identity_file, &st) < 0)
    1874                 :          0 :                 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
    1875         [ #  # ]:          0 :         if ((key = key_load_public(identity_file, NULL)) == NULL)
    1876                 :          0 :                 fatal("%s is not a public key", identity_file);
    1877         [ #  # ]:          0 :         if (!key_is_cert(key))
    1878                 :          0 :                 fatal("%s is not a certificate", identity_file);
    1879                 :          0 :         v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
    1880                 :            : 
    1881                 :          0 :         key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
    1882                 :          0 :         ca_fp = key_fingerprint(key->cert->signature_key,
    1883                 :            :             SSH_FP_MD5, SSH_FP_HEX);
    1884                 :            : 
    1885                 :            :         printf("%s:\n", identity_file);
    1886                 :          0 :         printf("        Type: %s %s certificate\n", key_ssh_name(key),
    1887                 :            :             key_cert_type(key));
    1888                 :          0 :         printf("        Public key: %s %s\n", key_type(key), key_fp);
    1889                 :          0 :         printf("        Signing CA: %s %s\n",
    1890                 :          0 :             key_type(key->cert->signature_key), ca_fp);
    1891                 :          0 :         printf("        Key ID: \"%s\"\n", key->cert->key_id);
    1892         [ #  # ]:          0 :         if (!v00) {
    1893                 :            :                 printf("        Serial: %llu\n",
    1894                 :          0 :                     (unsigned long long)key->cert->serial);
    1895                 :            :         }
    1896                 :          0 :         printf("        Valid: %s\n",
    1897                 :          0 :             fmt_validity(key->cert->valid_after, key->cert->valid_before));
    1898                 :            :         printf("        Principals: ");
    1899         [ #  # ]:          0 :         if (key->cert->nprincipals == 0)
    1900                 :            :                 printf("(none)\n");
    1901                 :            :         else {
    1902         [ #  # ]:          0 :                 for (i = 0; i < key->cert->nprincipals; i++)
    1903                 :          0 :                         printf("\n                %s",
    1904                 :          0 :                             key->cert->principals[i]);
    1905                 :            :                 printf("\n");
    1906                 :            :         }
    1907                 :            :         printf("        Critical Options: ");
    1908         [ #  # ]:          0 :         if (buffer_len(&key->cert->critical) == 0)
    1909                 :            :                 printf("(none)\n");
    1910                 :            :         else {
    1911                 :            :                 printf("\n");
    1912                 :          0 :                 show_options(&key->cert->critical, v00, 1);
    1913                 :            :         }
    1914         [ #  # ]:          0 :         if (!v00) {
    1915                 :            :                 printf("        Extensions: ");
    1916         [ #  # ]:          0 :                 if (buffer_len(&key->cert->extensions) == 0)
    1917                 :            :                         printf("(none)\n");
    1918                 :            :                 else {
    1919                 :            :                         printf("\n");
    1920                 :          0 :                         show_options(&key->cert->extensions, v00, 0);
    1921                 :            :                 }
    1922                 :            :         }
    1923                 :          0 :         exit(0);
    1924                 :            : }
    1925                 :            : 
    1926                 :            : static void
    1927                 :        294 : load_krl(const char *path, struct ssh_krl **krlp)
    1928                 :            : {
    1929                 :            :         Buffer krlbuf;
    1930                 :            :         int fd;
    1931                 :            : 
    1932                 :        294 :         buffer_init(&krlbuf);
    1933         [ -  + ]:        294 :         if ((fd = open(path, O_RDONLY)) == -1)
    1934                 :          0 :                 fatal("open %s: %s", path, strerror(errno));
    1935         [ -  + ]:        294 :         if (!key_load_file(fd, path, &krlbuf))
    1936                 :          0 :                 fatal("Unable to load KRL");
    1937                 :        294 :         close(fd);
    1938                 :            :         /* XXX check sigs */
    1939 [ +  - ][ -  + ]:        294 :         if (ssh_krl_from_blob(&krlbuf, krlp, NULL, 0) != 0 ||
    1940                 :        294 :             *krlp == NULL)
    1941                 :          0 :                 fatal("Invalid KRL file");
    1942                 :        294 :         buffer_free(&krlbuf);
    1943                 :        294 : }
    1944                 :            : 
    1945                 :            : static void
    1946                 :        312 : update_krl_from_file(struct passwd *pw, const char *file, const Key *ca,
    1947                 :            :     struct ssh_krl *krl)
    1948                 :            : {
    1949                 :        312 :         Key *key = NULL;
    1950                 :        312 :         u_long lnum = 0;
    1951                 :            :         char *path, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES];
    1952                 :            :         unsigned long long serial, serial2;
    1953                 :            :         int i, was_explicit_key, was_sha1, r;
    1954                 :            :         FILE *krl_spec;
    1955                 :            : 
    1956                 :        312 :         path = tilde_expand_filename(file, pw->pw_uid);
    1957 [ +  + ][ +  + ]:        312 :         if (strcmp(path, "-") == 0) {
    1958                 :          7 :                 krl_spec = stdin;
    1959                 :          7 :                 free(path);
    1960                 :          7 :                 path = xstrdup("(standard input)");
    1961         [ -  + ]:        305 :         } else if ((krl_spec = fopen(path, "r")) == NULL)
    1962                 :          0 :                 fatal("fopen %s: %s", path, strerror(errno));
    1963                 :            : 
    1964         [ +  + ]:        312 :         if (!quiet)
    1965                 :            :                 printf("Revoking from %s\n", path);
    1966         [ +  + ]:       4292 :         while (read_keyfile_line(krl_spec, path, line, sizeof(line),
    1967                 :            :             &lnum) == 0) {
    1968                 :            :                 was_explicit_key = was_sha1 = 0;
    1969                 :       3980 :                 cp = line + strspn(line, " \t");
    1970                 :            :                 /* Trim trailing space, comments and strip \n */
    1971         [ +  - ]:     226738 :                 for (i = 0, r = -1; cp[i] != '\0'; i++) {
    1972         [ +  + ]:     226738 :                         if (cp[i] == '#' || cp[i] == '\n') {
    1973                 :       3980 :                                 cp[i] = '\0';
    1974                 :            :                                 break;
    1975                 :            :                         }
    1976         [ +  + ]:     222758 :                         if (cp[i] == ' ' || cp[i] == '\t') {
    1977                 :            :                                 /* Remember the start of a span of whitespace */
    1978         [ +  + ]:       7974 :                                 if (r == -1)
    1979                 :       7848 :                                         r = i;
    1980                 :            :                         } else
    1981                 :            :                                 r = -1;
    1982                 :            :                 }
    1983         [ +  + ]:       3980 :                 if (r != -1)
    1984                 :        259 :                         cp[r] = '\0';
    1985         [ +  + ]:       3980 :                 if (*cp == '\0')
    1986                 :          7 :                         continue;
    1987         [ +  + ]:       3973 :                 if (strncasecmp(cp, "serial:", 7) == 0) {
    1988         [ -  + ]:         98 :                         if (ca == NULL) {
    1989                 :          0 :                                 fatal("revoking certificates by serial number "
    1990                 :            :                                     "requires specification of a CA key");
    1991                 :            :                         }
    1992                 :         98 :                         cp += 7;
    1993                 :        196 :                         cp = cp + strspn(cp, " \t");
    1994                 :         98 :                         errno = 0;
    1995                 :         98 :                         serial = strtoull(cp, &ep, 0);
    1996 [ +  - ][ -  + ]:         98 :                         if (*cp == '\0' || (*ep != '\0' && *ep != '-'))
    1997                 :          0 :                                 fatal("%s:%lu: invalid serial \"%s\"",
    1998                 :            :                                     path, lnum, cp);
    1999 [ -  + ][ #  # ]:         98 :                         if (errno == ERANGE && serial == ULLONG_MAX)
    2000                 :          0 :                                 fatal("%s:%lu: serial out of range",
    2001                 :            :                                     path, lnum);
    2002                 :         98 :                         serial2 = serial;
    2003         [ +  + ]:         98 :                         if (*ep == '-') {
    2004                 :         28 :                                 cp = ep + 1;
    2005                 :         28 :                                 errno = 0;
    2006                 :         28 :                                 serial2 = strtoull(cp, &ep, 0);
    2007 [ +  - ][ -  + ]:         28 :                                 if (*cp == '\0' || *ep != '\0')
    2008                 :          0 :                                         fatal("%s:%lu: invalid serial \"%s\"",
    2009                 :            :                                             path, lnum, cp);
    2010 [ -  + ][ #  # ]:         28 :                                 if (errno == ERANGE && serial2 == ULLONG_MAX)
    2011                 :          0 :                                         fatal("%s:%lu: serial out of range",
    2012                 :            :                                             path, lnum);
    2013         [ -  + ]:         28 :                                 if (serial2 <= serial)
    2014                 :          0 :                                         fatal("%s:%lu: invalid serial range "
    2015                 :            :                                             "%llu:%llu", path, lnum,
    2016                 :            :                                             (unsigned long long)serial,
    2017                 :            :                                             (unsigned long long)serial2);
    2018                 :            :                         }
    2019         [ -  + ]:         98 :                         if (ssh_krl_revoke_cert_by_serial_range(krl,
    2020                 :            :                             ca, serial, serial2) != 0) {
    2021                 :          0 :                                 fatal("%s: revoke serial failed",
    2022                 :            :                                     __func__);
    2023                 :            :                         }
    2024         [ +  + ]:       3875 :                 } else if (strncasecmp(cp, "id:", 3) == 0) {
    2025         [ -  + ]:       3584 :                         if (ca == NULL) {
    2026                 :          0 :                                 fatal("revoking certificates by key ID "
    2027                 :            :                                     "requires specification of a CA key");
    2028                 :            :                         }
    2029                 :       3584 :                         cp += 3;
    2030                 :       7168 :                         cp = cp + strspn(cp, " \t");
    2031         [ -  + ]:       3584 :                         if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
    2032                 :          0 :                                 fatal("%s: revoke key ID failed", __func__);
    2033                 :            :                 } else {
    2034         [ -  + ]:        291 :                         if (strncasecmp(cp, "key:", 4) == 0) {
    2035                 :          0 :                                 cp += 4;
    2036                 :          0 :                                 cp = cp + strspn(cp, " \t");
    2037                 :          0 :                                 was_explicit_key = 1;
    2038         [ -  + ]:        291 :                         } else if (strncasecmp(cp, "sha1:", 5) == 0) {
    2039                 :          0 :                                 cp += 5;
    2040                 :          0 :                                 cp = cp + strspn(cp, " \t");
    2041                 :          0 :                                 was_sha1 = 1;
    2042                 :            :                         } else {
    2043                 :            :                                 /*
    2044                 :            :                                  * Just try to process the line as a key.
    2045                 :            :                                  * Parsing will fail if it isn't.
    2046                 :            :                                  */
    2047                 :            :                         }
    2048         [ -  + ]:        291 :                         if ((key = key_new(KEY_UNSPEC)) == NULL)
    2049                 :          0 :                                 fatal("key_new");
    2050         [ -  + ]:        291 :                         if (key_read(key, &cp) != 1)
    2051                 :          0 :                                 fatal("%s:%lu: invalid key", path, lnum);
    2052         [ -  + ]:        291 :                         if (was_explicit_key)
    2053                 :          0 :                                 r = ssh_krl_revoke_key_explicit(krl, key);
    2054         [ -  + ]:        291 :                         else if (was_sha1)
    2055                 :          0 :                                 r = ssh_krl_revoke_key_sha1(krl, key);
    2056                 :            :                         else
    2057                 :        291 :                                 r = ssh_krl_revoke_key(krl, key);
    2058         [ -  + ]:        291 :                         if (r != 0)
    2059                 :          0 :                                 fatal("%s: revoke key failed", __func__);
    2060                 :       3980 :                         key_free(key);
    2061                 :            :                 }
    2062                 :            :         }
    2063 [ -  + ][ +  - ]:        312 :         if (strcmp(path, "-") != 0)
    2064                 :        312 :                 fclose(krl_spec);
    2065                 :        312 :         free(path);
    2066                 :        312 : }
    2067                 :            : 
    2068                 :            : static void
    2069                 :        113 : do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
    2070                 :            : {
    2071                 :            :         struct ssh_krl *krl;
    2072                 :            :         struct stat sb;
    2073                 :        113 :         Key *ca = NULL;
    2074                 :            :         int fd, i;
    2075                 :            :         char *tmp;
    2076                 :            :         Buffer kbuf;
    2077                 :            : 
    2078         [ -  + ]:        113 :         if (*identity_file == '\0')
    2079                 :          0 :                 fatal("KRL generation requires an output file");
    2080         [ +  + ]:        113 :         if (stat(identity_file, &sb) == -1) {
    2081         [ -  + ]:         39 :                 if (errno != ENOENT)
    2082                 :          0 :                         fatal("Cannot access KRL \"%s\": %s",
    2083                 :            :                             identity_file, strerror(errno));
    2084         [ -  + ]:         39 :                 if (updating)
    2085                 :          0 :                         fatal("KRL \"%s\" does not exist", identity_file);
    2086                 :            :         }
    2087         [ +  + ]:        113 :         if (ca_key_path != NULL) {
    2088                 :         14 :                 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
    2089         [ -  + ]:         14 :                 if ((ca = key_load_public(tmp, NULL)) == NULL)
    2090                 :          0 :                         fatal("Cannot load CA public key %s", tmp);
    2091                 :         14 :                 free(tmp);
    2092                 :            :         }
    2093                 :            : 
    2094         [ +  + ]:        113 :         if (updating)
    2095                 :         42 :                 load_krl(identity_file, &krl);
    2096         [ -  + ]:         71 :         else if ((krl = ssh_krl_init()) == NULL)
    2097                 :          0 :                 fatal("couldn't create KRL");
    2098                 :            : 
    2099         [ -  + ]:        113 :         if (cert_serial != 0)
    2100                 :          0 :                 ssh_krl_set_version(krl, cert_serial);
    2101         [ -  + ]:        113 :         if (identity_comment != NULL)
    2102                 :        113 :                 ssh_krl_set_comment(krl, identity_comment);
    2103                 :            : 
    2104         [ +  + ]:        425 :         for (i = 0; i < argc; i++)
    2105                 :        312 :                 update_krl_from_file(pw, argv[i], ca, krl);
    2106                 :            : 
    2107                 :        113 :         buffer_init(&kbuf);
    2108         [ -  + ]:        113 :         if (ssh_krl_to_blob(krl, &kbuf, NULL, 0) != 0)
    2109                 :          0 :                 fatal("Couldn't generate KRL");
    2110         [ -  + ]:        113 :         if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
    2111                 :          0 :                 fatal("open %s: %s", identity_file, strerror(errno));
    2112         [ -  + ]:        226 :         if (atomicio(vwrite, fd, buffer_ptr(&kbuf), buffer_len(&kbuf)) !=
    2113                 :        113 :             buffer_len(&kbuf))
    2114                 :          0 :                 fatal("write %s: %s", identity_file, strerror(errno));
    2115                 :        113 :         close(fd);
    2116                 :        113 :         buffer_free(&kbuf);
    2117                 :        113 :         ssh_krl_free(krl);
    2118         [ +  + ]:        113 :         if (ca != NULL)
    2119                 :         14 :                 key_free(ca);
    2120                 :        113 : }
    2121                 :            : 
    2122                 :            : static void
    2123                 :        504 : do_check_krl(struct passwd *pw, int argc, char **argv)
    2124                 :            : {
    2125                 :        252 :         int i, r, ret = 0;
    2126                 :            :         char *comment;
    2127                 :            :         struct ssh_krl *krl;
    2128                 :            :         Key *k;
    2129                 :            : 
    2130         [ -  + ]:        252 :         if (*identity_file == '\0')
    2131                 :          0 :                 fatal("KRL checking requires an input file");
    2132                 :        252 :         load_krl(identity_file, &krl);
    2133         [ +  + ]:        504 :         for (i = 0; i < argc; i++) {
    2134         [ -  + ]:        252 :                 if ((k = key_load_public(argv[i], &comment)) == NULL)
    2135                 :          0 :                         fatal("Cannot load public key %s", argv[i]);
    2136                 :        252 :                 r = ssh_krl_check_key(krl, k);
    2137 [ +  + ][ -  + ]:        252 :                 printf("%s%s%s%s: %s\n", argv[i],
                 [ -  + ]
    2138                 :        252 :                     *comment ? " (" : "", comment, *comment ? ")" : "",
    2139                 :            :                     r == 0 ? "ok" : "REVOKED");
    2140         [ +  + ]:        252 :                 if (r != 0)
    2141                 :        144 :                         ret = 1;
    2142                 :        252 :                 key_free(k);
    2143                 :        252 :                 free(comment);
    2144                 :            :         }
    2145                 :        252 :         ssh_krl_free(krl);
    2146                 :        252 :         exit(ret);
    2147                 :            : }
    2148                 :            : 
    2149                 :            : static void
    2150                 :          0 : usage(void)
    2151                 :            : {
    2152                 :          0 :         fprintf(stderr, "usage: %s [options]\n", __progname);
    2153                 :          0 :         fprintf(stderr, "Options:\n");
    2154                 :          0 :         fprintf(stderr, "  -A          Generate non-existent host keys for all key types.\n");
    2155                 :          0 :         fprintf(stderr, "  -a number   Number of KDF rounds for new key format or moduli primality tests.\n");
    2156                 :          0 :         fprintf(stderr, "  -B          Show bubblebabble digest of key file.\n");
    2157                 :          0 :         fprintf(stderr, "  -b bits     Number of bits in the key to create.\n");
    2158                 :          0 :         fprintf(stderr, "  -C comment  Provide new comment.\n");
    2159                 :          0 :         fprintf(stderr, "  -c          Change comment in private and public key files.\n");
    2160                 :            : #ifdef ENABLE_PKCS11
    2161                 :          0 :         fprintf(stderr, "  -D pkcs11   Download public key from pkcs11 token.\n");
    2162                 :            : #endif
    2163                 :          0 :         fprintf(stderr, "  -e          Export OpenSSH to foreign format key file.\n");
    2164                 :          0 :         fprintf(stderr, "  -F hostname Find hostname in known hosts file.\n");
    2165                 :          0 :         fprintf(stderr, "  -f filename Filename of the key file.\n");
    2166                 :          0 :         fprintf(stderr, "  -G file     Generate candidates for DH-GEX moduli.\n");
    2167                 :          0 :         fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
    2168                 :          0 :         fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
    2169                 :          0 :         fprintf(stderr, "  -h          Generate host certificate instead of a user certificate.\n");
    2170                 :          0 :         fprintf(stderr, "  -I key_id   Key identifier to include in certificate.\n");
    2171                 :          0 :         fprintf(stderr, "  -i          Import foreign format to OpenSSH key file.\n");
    2172                 :          0 :         fprintf(stderr, "  -J number   Screen this number of moduli lines.\n");
    2173                 :          0 :         fprintf(stderr, "  -j number   Start screening moduli at specified line.\n");
    2174                 :          0 :         fprintf(stderr, "  -K checkpt  Write checkpoints to this file.\n");
    2175                 :          0 :         fprintf(stderr, "  -k          Generate a KRL file.\n");
    2176                 :          0 :         fprintf(stderr, "  -L          Print the contents of a certificate.\n");
    2177                 :          0 :         fprintf(stderr, "  -l          Show fingerprint of key file.\n");
    2178                 :          0 :         fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
    2179                 :          0 :         fprintf(stderr, "  -m key_fmt  Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n");
    2180                 :          0 :         fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
    2181                 :          0 :         fprintf(stderr, "  -n name,... User/host principal names to include in certificate\n");
    2182                 :          0 :         fprintf(stderr, "  -O option   Specify a certificate option.\n");
    2183                 :          0 :         fprintf(stderr, "  -o          Enforce new private key format.\n");
    2184                 :          0 :         fprintf(stderr, "  -P phrase   Provide old passphrase.\n");
    2185                 :          0 :         fprintf(stderr, "  -p          Change passphrase of private key file.\n");
    2186                 :          0 :         fprintf(stderr, "  -Q          Test whether key(s) are revoked in KRL.\n");
    2187                 :          0 :         fprintf(stderr, "  -q          Quiet.\n");
    2188                 :          0 :         fprintf(stderr, "  -R hostname Remove host from known_hosts file.\n");
    2189                 :          0 :         fprintf(stderr, "  -r hostname Print DNS resource record.\n");
    2190                 :          0 :         fprintf(stderr, "  -S start    Start point (hex) for generating DH-GEX moduli.\n");
    2191                 :          0 :         fprintf(stderr, "  -s ca_key   Certify keys with CA key.\n");
    2192                 :          0 :         fprintf(stderr, "  -T file     Screen candidates for DH-GEX moduli.\n");
    2193                 :          0 :         fprintf(stderr, "  -t type     Specify type of key to create.\n");
    2194                 :          0 :         fprintf(stderr, "  -u          Update KRL rather than creating a new one.\n");
    2195                 :          0 :         fprintf(stderr, "  -V from:to  Specify certificate validity interval.\n");
    2196                 :          0 :         fprintf(stderr, "  -v          Verbose.\n");
    2197                 :          0 :         fprintf(stderr, "  -W gen      Generator to use for generating DH-GEX moduli.\n");
    2198                 :          0 :         fprintf(stderr, "  -y          Read private key file and print public key.\n");
    2199                 :          0 :         fprintf(stderr, "  -Z cipher   Specify a cipher for new private key format.\n");
    2200                 :          0 :         fprintf(stderr, "  -z serial   Specify a serial number.\n");
    2201                 :            : 
    2202                 :          0 :         exit(1);
    2203                 :            : }
    2204                 :            : 
    2205                 :            : /*
    2206                 :            :  * Main program for key management.
    2207                 :            :  */
    2208                 :            : int
    2209                 :        545 : main(int argc, char **argv)
    2210                 :            : {
    2211                 :            :         char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
    2212                 :        545 :         char *checkpoint = NULL;
    2213                 :        545 :         char out_file[MAXPATHLEN], *ep, *rr_hostname = NULL;
    2214                 :            :         Key *private, *public;
    2215                 :            :         struct passwd *pw;
    2216                 :            :         struct stat st;
    2217                 :            :         int opt, type, fd;
    2218                 :        545 :         u_int32_t memory = 0, generator_wanted = 0;
    2219                 :        545 :         int do_gen_candidates = 0, do_screen_candidates = 0;
    2220                 :        545 :         int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
    2221                 :        545 :         unsigned long start_lineno = 0, lines_to_process = 0;
    2222                 :        545 :         BIGNUM *start = NULL;
    2223                 :            :         FILE *f;
    2224                 :            :         const char *errstr;
    2225                 :            : 
    2226                 :            :         extern int optind;
    2227                 :            :         extern char *optarg;
    2228                 :            : 
    2229                 :            :         /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
    2230                 :        545 :         sanitise_stdfd();
    2231                 :            : 
    2232                 :        545 :         __progname = ssh_get_progname(argv[0]);
    2233                 :            : 
    2234                 :        545 :         OpenSSL_add_all_algorithms();
    2235                 :        545 :         log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
    2236                 :            : 
    2237                 :        545 :         seed_rng();
    2238                 :            : 
    2239                 :            :         /* we need this for the home * directory.  */
    2240                 :        545 :         pw = getpwuid(getuid());
    2241         [ -  + ]:        545 :         if (!pw) {
    2242                 :          0 :                 printf("No user exists for uid %lu\n", (u_long)getuid());
    2243                 :          0 :                 exit(1);
    2244                 :            :         }
    2245         [ +  - ]:        545 :         if (gethostname(hostname, sizeof(hostname)) < 0) {
    2246                 :          0 :                 perror("gethostname");
    2247                 :          0 :                 exit(1);
    2248                 :            :         }
    2249                 :            : 
    2250                 :            :         /* Remaining characters: EUYdw */
    2251         [ +  + ]:       2160 :         while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy"
    2252                 :            :             "C:D:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
    2253   [ +  -  -  +  :       1615 :                 switch (opt) {
          -  -  -  -  +  
          +  -  +  -  +  
          -  +  -  +  +  
          +  +  -  +  +  
          +  +  +  +  +  
          +  +  -  +  -  
          -  -  -  -  -  
          -  -  -  +  +  
                   -  - ]
    2254                 :            :                 case 'A':
    2255                 :            :                         gen_all_hostkeys = 1;
    2256                 :            :                         break;
    2257                 :            :                 case 'b':
    2258                 :          7 :                         bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr);
    2259         [ -  + ]:          7 :                         if (errstr)
    2260                 :          0 :                                 fatal("Bits has bad value %s (%s)",
    2261                 :            :                                         optarg, errstr);
    2262                 :            :                         break;
    2263                 :            :                 case 'F':
    2264                 :          0 :                         find_host = 1;
    2265                 :          0 :                         rr_hostname = optarg;
    2266                 :          0 :                         break;
    2267                 :            :                 case 'H':
    2268                 :          0 :                         hash_hosts = 1;
    2269                 :          0 :                         break;
    2270                 :            :                 case 'I':
    2271                 :         99 :                         cert_key_id = optarg;
    2272                 :         99 :                         break;
    2273                 :            :                 case 'J':
    2274                 :          0 :                         lines_to_process = strtoul(optarg, NULL, 10);
    2275                 :       1615 :                         break;
    2276                 :            :                 case 'j':
    2277                 :          0 :                         start_lineno = strtoul(optarg, NULL, 10);
    2278                 :          0 :                         break;
    2279                 :            :                 case 'R':
    2280                 :          0 :                         delete_host = 1;
    2281                 :          0 :                         rr_hostname = optarg;
    2282                 :          0 :                         break;
    2283                 :            :                 case 'L':
    2284                 :          0 :                         show_cert = 1;
    2285                 :          0 :                         break;
    2286                 :            :                 case 'l':
    2287                 :          5 :                         print_fingerprint = 1;
    2288                 :          5 :                         break;
    2289                 :            :                 case 'B':
    2290                 :          5 :                         print_bubblebabble = 1;
    2291                 :          5 :                         break;
    2292                 :            :                 case 'm':
    2293 [ #  # ][ #  # ]:          0 :                         if (strcasecmp(optarg, "RFC4716") == 0 ||
    2294                 :          0 :                             strcasecmp(optarg, "ssh2") == 0) {
    2295                 :          0 :                                 convert_format = FMT_RFC4716;
    2296                 :          0 :                                 break;
    2297                 :            :                         }
    2298         [ #  # ]:          0 :                         if (strcasecmp(optarg, "PKCS8") == 0) {
    2299                 :          0 :                                 convert_format = FMT_PKCS8;
    2300                 :          0 :                                 break;
    2301                 :            :                         }
    2302         [ #  # ]:          0 :                         if (strcasecmp(optarg, "PEM") == 0) {
    2303                 :          0 :                                 convert_format = FMT_PEM;
    2304                 :          0 :                                 break;
    2305                 :            :                         }
    2306                 :          0 :                         fatal("Unsupported conversion format \"%s\"", optarg);
    2307                 :            :                 case 'n':
    2308                 :         72 :                         cert_principals = optarg;
    2309                 :         72 :                         break;
    2310                 :            :                 case 'o':
    2311                 :          0 :                         use_new_format = 1;
    2312                 :          0 :                         break;
    2313                 :            :                 case 'p':
    2314                 :          3 :                         change_passphrase = 1;
    2315                 :          3 :                         break;
    2316                 :            :                 case 'c':
    2317                 :          0 :                         change_comment = 1;
    2318                 :          0 :                         break;
    2319                 :            :                 case 'f':
    2320         [ -  + ]:        446 :                         if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
    2321                 :            :                             sizeof(identity_file))
    2322                 :          0 :                                 fatal("Identity filename too long");
    2323                 :        446 :                         have_identity = 1;
    2324                 :        446 :                         break;
    2325                 :            :                 case 'g':
    2326                 :          0 :                         print_generic = 1;
    2327                 :          0 :                         break;
    2328                 :            :                 case 'P':
    2329                 :          3 :                         identity_passphrase = optarg;
    2330                 :          3 :                         break;
    2331                 :            :                 case 'N':
    2332                 :         56 :                         identity_new_passphrase = optarg;
    2333                 :         56 :                         break;
    2334                 :            :                 case 'Q':
    2335                 :        252 :                         check_krl = 1;
    2336                 :        252 :                         break;
    2337                 :            :                 case 'O':
    2338                 :         10 :                         add_cert_option(optarg);
    2339                 :         10 :                         break;
    2340                 :            :                 case 'Z':
    2341                 :          0 :                         new_format_cipher = optarg;
    2342                 :          0 :                         break;
    2343                 :            :                 case 'C':
    2344                 :         10 :                         identity_comment = optarg;
    2345                 :         10 :                         break;
    2346                 :            :                 case 'q':
    2347                 :        203 :                         quiet = 1;
    2348                 :        203 :                         break;
    2349                 :            :                 case 'e':
    2350                 :            :                 case 'x':
    2351                 :            :                         /* export key */
    2352                 :          5 :                         convert_to = 1;
    2353                 :          5 :                         break;
    2354                 :            :                 case 'h':
    2355                 :         32 :                         cert_key_type = SSH2_CERT_TYPE_HOST;
    2356                 :         32 :                         certflags_flags = 0;
    2357                 :         32 :                         break;
    2358                 :            :                 case 'k':
    2359                 :        113 :                         gen_krl = 1;
    2360                 :        113 :                         break;
    2361                 :            :                 case 'i':
    2362                 :            :                 case 'X':
    2363                 :            :                         /* import key */
    2364                 :          8 :                         convert_from = 1;
    2365                 :          8 :                         break;
    2366                 :            :                 case 'y':
    2367                 :          2 :                         print_public = 1;
    2368                 :          2 :                         break;
    2369                 :            :                 case 's':
    2370                 :        113 :                         ca_key_path = optarg;
    2371                 :        113 :                         break;
    2372                 :            :                 case 't':
    2373                 :         96 :                         key_type_name = optarg;
    2374                 :         96 :                         break;
    2375                 :            :                 case 'D':
    2376                 :          0 :                         pkcs11provider = optarg;
    2377                 :          0 :                         break;
    2378                 :            :                 case 'u':
    2379                 :         42 :                         update_krl = 1;
    2380                 :         42 :                         break;
    2381                 :            :                 case 'v':
    2382         [ #  # ]:          0 :                         if (log_level == SYSLOG_LEVEL_INFO)
    2383                 :          0 :                                 log_level = SYSLOG_LEVEL_DEBUG1;
    2384                 :            :                         else {
    2385         [ #  # ]:          0 :                                 if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
    2386                 :            :                                     log_level < SYSLOG_LEVEL_DEBUG3)
    2387                 :          0 :                                         log_level++;
    2388                 :            :                         }
    2389                 :            :                         break;
    2390                 :            :                 case 'r':
    2391                 :          0 :                         rr_hostname = optarg;
    2392                 :          0 :                         break;
    2393                 :            :                 case 'W':
    2394                 :          0 :                         generator_wanted = (u_int32_t)strtonum(optarg, 1,
    2395                 :            :                             UINT_MAX, &errstr);
    2396         [ #  # ]:          0 :                         if (errstr)
    2397                 :          0 :                                 fatal("Desired generator has bad value: %s (%s)",
    2398                 :            :                                         optarg, errstr);
    2399                 :            :                         break;
    2400                 :            :                 case 'a':
    2401                 :          0 :                         rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
    2402         [ #  # ]:          0 :                         if (errstr)
    2403                 :          0 :                                 fatal("Invalid number: %s (%s)",
    2404                 :            :                                         optarg, errstr);
    2405                 :            :                         break;
    2406                 :            :                 case 'M':
    2407                 :          0 :                         memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
    2408         [ #  # ]:          0 :                         if (errstr)
    2409                 :          0 :                                 fatal("Memory limit is %s: %s", errstr, optarg);
    2410                 :            :                         break;
    2411                 :            :                 case 'G':
    2412                 :          0 :                         do_gen_candidates = 1;
    2413         [ #  # ]:          0 :                         if (strlcpy(out_file, optarg, sizeof(out_file)) >=
    2414                 :            :                             sizeof(out_file))
    2415                 :          0 :                                 fatal("Output filename too long");
    2416                 :            :                         break;
    2417                 :            :                 case 'T':
    2418                 :          0 :                         do_screen_candidates = 1;
    2419         [ #  # ]:          0 :                         if (strlcpy(out_file, optarg, sizeof(out_file)) >=
    2420                 :            :                             sizeof(out_file))
    2421                 :          0 :                                 fatal("Output filename too long");
    2422                 :            :                         break;
    2423                 :            :                 case 'K':
    2424         [ #  # ]:          0 :                         if (strlen(optarg) >= MAXPATHLEN)
    2425                 :          0 :                                 fatal("Checkpoint filename too long");
    2426                 :          0 :                         checkpoint = xstrdup(optarg);
    2427                 :          0 :                         break;
    2428                 :            :                 case 'S':
    2429                 :            :                         /* XXX - also compare length against bits */
    2430         [ #  # ]:          0 :                         if (BN_hex2bn(&start, optarg) == 0)
    2431                 :          0 :                                 fatal("Invalid start point.");
    2432                 :            :                         break;
    2433                 :            :                 case 'V':
    2434                 :         18 :                         parse_cert_times(optarg);
    2435                 :         18 :                         break;
    2436                 :            :                 case 'z':
    2437                 :         15 :                         errno = 0;
    2438                 :         15 :                         cert_serial = strtoull(optarg, &ep, 10);
    2439 [ +  - ][ +  - ]:         15 :                         if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
                 [ -  + ]
    2440         [ #  # ]:          0 :                             (errno == ERANGE && cert_serial == ULLONG_MAX))
    2441                 :          0 :                                 fatal("Invalid serial number \"%s\"", optarg);
    2442                 :            :                         break;
    2443                 :            :                 case '?':
    2444                 :            :                 default:
    2445                 :          0 :                         usage();
    2446                 :            :                 }
    2447                 :            :         }
    2448                 :            : 
    2449                 :            :         /* reinit */
    2450                 :        545 :         log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
    2451                 :            : 
    2452                 :        545 :         argv += optind;
    2453                 :        545 :         argc -= optind;
    2454                 :            : 
    2455         [ +  + ]:        545 :         if (ca_key_path != NULL) {
    2456         [ -  + ]:        113 :                 if (argc < 1 && !gen_krl) {
    2457                 :            :                         printf("Too few arguments.\n");
    2458                 :          0 :                         usage();
    2459                 :            :                 }
    2460 [ +  + ][ -  + ]:        432 :         } else if (argc > 0 && !gen_krl && !check_krl) {
    2461                 :            :                 printf("Too many arguments.\n");
    2462                 :          0 :                 usage();
    2463                 :            :         }
    2464 [ +  + ][ -  + ]:        545 :         if (change_passphrase && change_comment) {
    2465                 :            :                 printf("Can only have one of -p and -c.\n");
    2466                 :          0 :                 usage();
    2467                 :            :         }
    2468 [ +  + ][ +  - ]:        545 :         if (print_fingerprint && (delete_host || hash_hosts)) {
                 [ -  + ]
    2469                 :            :                 printf("Cannot use -l with -H or -R.\n");
    2470                 :          0 :                 usage();
    2471                 :            :         }
    2472         [ +  + ]:        545 :         if (gen_krl) {
    2473                 :        113 :                 do_gen_krl(pw, update_krl, argc, argv);
    2474                 :        113 :                 return (0);
    2475                 :            :         }
    2476         [ +  + ]:        432 :         if (check_krl) {
    2477                 :        252 :                 do_check_krl(pw, argc, argv);
    2478                 :            :                 return (0);
    2479                 :            :         }
    2480         [ +  + ]:        180 :         if (ca_key_path != NULL) {
    2481         [ -  + ]:         99 :                 if (cert_key_id == NULL)
    2482                 :          0 :                         fatal("Must specify key id (-I) when certifying");
    2483                 :         99 :                 do_ca_sign(pw, argc, argv);
    2484                 :            :         }
    2485         [ -  + ]:         81 :         if (show_cert)
    2486                 :          0 :                 do_show_cert(pw);
    2487 [ +  - ][ +  - ]:         81 :         if (delete_host || hash_hosts || find_host)
                 [ -  + ]
    2488                 :          0 :                 do_known_hosts(pw, rr_hostname);
    2489         [ -  + ]:         81 :         if (pkcs11provider != NULL)
    2490                 :          0 :                 do_download(pw);
    2491 [ +  + ][ +  + ]:         81 :         if (print_fingerprint || print_bubblebabble)
    2492                 :         10 :                 do_fingerprint(pw);
    2493         [ +  + ]:         71 :         if (change_passphrase)
    2494                 :          3 :                 do_change_passphrase(pw);
    2495         [ -  + ]:         68 :         if (change_comment)
    2496                 :          0 :                 do_change_comment(pw);
    2497         [ +  + ]:         68 :         if (convert_to)
    2498                 :          5 :                 do_convert_to(pw);
    2499         [ +  + ]:         63 :         if (convert_from)
    2500                 :          8 :                 do_convert_from(pw);
    2501         [ +  + ]:         55 :         if (print_public)
    2502                 :          2 :                 do_print_public(pw);
    2503         [ -  + ]:         53 :         if (rr_hostname != NULL) {
    2504                 :          0 :                 unsigned int n = 0;
    2505                 :            : 
    2506         [ #  # ]:          0 :                 if (have_identity) {
    2507                 :          0 :                         n = do_print_resource_record(pw,
    2508                 :            :                             identity_file, rr_hostname);
    2509         [ #  # ]:          0 :                         if (n == 0) {
    2510                 :          0 :                                 perror(identity_file);
    2511                 :          0 :                                 exit(1);
    2512                 :            :                         }
    2513                 :          0 :                         exit(0);
    2514                 :            :                 } else {
    2515                 :            : 
    2516                 :          0 :                         n += do_print_resource_record(pw,
    2517                 :            :                             _PATH_HOST_RSA_KEY_FILE, rr_hostname);
    2518                 :          0 :                         n += do_print_resource_record(pw,
    2519                 :            :                             _PATH_HOST_DSA_KEY_FILE, rr_hostname);
    2520                 :          0 :                         n += do_print_resource_record(pw,
    2521                 :            :                             _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
    2522                 :            : 
    2523         [ #  # ]:          0 :                         if (n == 0)
    2524                 :          0 :                                 fatal("no keys found.");
    2525                 :          0 :                         exit(0);
    2526                 :            :                 }
    2527                 :            :         }
    2528                 :            : 
    2529         [ -  + ]:         53 :         if (do_gen_candidates) {
    2530                 :          0 :                 FILE *out = fopen(out_file, "w");
    2531                 :            : 
    2532         [ #  # ]:          0 :                 if (out == NULL) {
    2533                 :          0 :                         error("Couldn't open modulus candidate file \"%s\": %s",
    2534                 :          0 :                             out_file, strerror(errno));
    2535                 :          0 :                         return (1);
    2536                 :            :                 }
    2537         [ #  # ]:          0 :                 if (bits == 0)
    2538                 :          0 :                         bits = DEFAULT_BITS;
    2539         [ #  # ]:          0 :                 if (gen_candidates(out, memory, bits, start) != 0)
    2540                 :          0 :                         fatal("modulus candidate generation failed");
    2541                 :            : 
    2542                 :            :                 return (0);
    2543                 :            :         }
    2544                 :            : 
    2545         [ -  + ]:         53 :         if (do_screen_candidates) {
    2546                 :            :                 FILE *in;
    2547                 :          0 :                 FILE *out = fopen(out_file, "a");
    2548                 :            : 
    2549 [ #  # ][ #  # ]:          0 :                 if (have_identity && strcmp(identity_file, "-") != 0) {
                 [ #  # ]
    2550         [ #  # ]:          0 :                         if ((in = fopen(identity_file, "r")) == NULL) {
    2551                 :          0 :                                 fatal("Couldn't open modulus candidate "
    2552                 :            :                                     "file \"%s\": %s", identity_file,
    2553                 :          0 :                                     strerror(errno));
    2554                 :            :                         }
    2555                 :            :                 } else
    2556                 :          0 :                         in = stdin;
    2557                 :            : 
    2558         [ #  # ]:          0 :                 if (out == NULL) {
    2559                 :          0 :                         fatal("Couldn't open moduli file \"%s\": %s",
    2560                 :          0 :                             out_file, strerror(errno));
    2561                 :            :                 }
    2562 [ #  # ][ #  # ]:          0 :                 if (prime_test(in, out, rounds == 0 ? 100 : rounds,
    2563                 :            :                     generator_wanted, checkpoint,
    2564                 :            :                     start_lineno, lines_to_process) != 0)
    2565                 :          0 :                         fatal("modulus screening failed");
    2566                 :            :                 return (0);
    2567                 :            :         }
    2568                 :            : 
    2569         [ -  + ]:         53 :         if (gen_all_hostkeys) {
    2570                 :          0 :                 do_gen_all_hostkeys(pw);
    2571                 :          0 :                 return (0);
    2572                 :            :         }
    2573                 :            : 
    2574         [ -  + ]:         53 :         if (key_type_name == NULL)
    2575                 :          0 :                 key_type_name = "rsa";
    2576                 :            : 
    2577                 :         53 :         type = key_type_from_name(key_type_name);
    2578                 :         53 :         type_bits_valid(type, &bits);
    2579                 :            : 
    2580         [ +  + ]:         53 :         if (!quiet)
    2581                 :         10 :                 printf("Generating public/private %s key pair.\n", key_type_name);
    2582                 :         53 :         private = key_generate(type, bits);
    2583         [ -  + ]:         53 :         if (private == NULL) {
    2584                 :          0 :                 fprintf(stderr, "key_generate failed\n");
    2585                 :          0 :                 exit(1);
    2586                 :            :         }
    2587                 :         53 :         public  = key_from_private(private);
    2588                 :            : 
    2589         [ -  + ]:         53 :         if (!have_identity)
    2590                 :          0 :                 ask_filename(pw, "Enter file in which to save the key");
    2591                 :            : 
    2592                 :            :         /* Create ~/.ssh directory if it doesn't already exist. */
    2593                 :         53 :         snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
    2594                 :            :             pw->pw_dir, _PATH_SSH_USER_DIR);
    2595         [ -  + ]:         53 :         if (strstr(identity_file, dotsshdir) != NULL) {
    2596         [ #  # ]:          0 :                 if (stat(dotsshdir, &st) < 0) {
    2597         [ #  # ]:          0 :                         if (errno != ENOENT) {
    2598                 :          0 :                                 error("Could not stat %s: %s", dotsshdir,
    2599                 :            :                                     strerror(errno));
    2600         [ #  # ]:          0 :                         } else if (mkdir(dotsshdir, 0700) < 0) {
    2601                 :          0 :                                 error("Could not create directory '%s': %s",
    2602                 :            :                                     dotsshdir, strerror(errno));
    2603         [ #  # ]:          0 :                         } else if (!quiet)
    2604                 :            :                                 printf("Created directory '%s'.\n", dotsshdir);
    2605                 :            :                 }
    2606                 :            :         }
    2607                 :            :         /* If the file already exists, ask the user to confirm. */
    2608         [ -  + ]:         53 :         if (stat(identity_file, &st) >= 0) {
    2609                 :            :                 char yesno[3];
    2610                 :            :                 printf("%s already exists.\n", identity_file);
    2611                 :            :                 printf("Overwrite (y/n)? ");
    2612                 :          0 :                 fflush(stdout);
    2613         [ #  # ]:          0 :                 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
    2614                 :          0 :                         exit(1);
    2615         [ #  # ]:          0 :                 if (yesno[0] != 'y' && yesno[0] != 'Y')
    2616                 :          0 :                         exit(1);
    2617                 :            :         }
    2618                 :            :         /* Ask for a passphrase (twice). */
    2619         [ -  + ]:         53 :         if (identity_passphrase)
    2620                 :          0 :                 passphrase1 = xstrdup(identity_passphrase);
    2621         [ -  + ]:         53 :         else if (identity_new_passphrase)
    2622                 :         53 :                 passphrase1 = xstrdup(identity_new_passphrase);
    2623                 :            :         else {
    2624                 :            : passphrase_again:
    2625                 :          0 :                 passphrase1 =
    2626                 :            :                         read_passphrase("Enter passphrase (empty for no "
    2627                 :            :                             "passphrase): ", RP_ALLOW_STDIN);
    2628                 :          0 :                 passphrase2 = read_passphrase("Enter same passphrase again: ",
    2629                 :            :                     RP_ALLOW_STDIN);
    2630         [ #  # ]:          0 :                 if (strcmp(passphrase1, passphrase2) != 0) {
    2631                 :            :                         /*
    2632                 :            :                          * The passphrases do not match.  Clear them and
    2633                 :            :                          * retry.
    2634                 :            :                          */
    2635                 :          0 :                         explicit_bzero(passphrase1, strlen(passphrase1));
    2636                 :          0 :                         explicit_bzero(passphrase2, strlen(passphrase2));
    2637                 :          0 :                         free(passphrase1);
    2638                 :          0 :                         free(passphrase2);
    2639                 :            :                         printf("Passphrases do not match.  Try again.\n");
    2640                 :            :                         goto passphrase_again;
    2641                 :            :                 }
    2642                 :            :                 /* Clear the other copy of the passphrase. */
    2643                 :          0 :                 explicit_bzero(passphrase2, strlen(passphrase2));
    2644                 :          0 :                 free(passphrase2);
    2645                 :            :         }
    2646                 :            : 
    2647         [ +  + ]:         53 :         if (identity_comment) {
    2648                 :         10 :                 strlcpy(comment, identity_comment, sizeof(comment));
    2649                 :            :         } else {
    2650                 :            :                 /* Create default comment field for the passphrase. */
    2651                 :         43 :                 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
    2652                 :            :         }
    2653                 :            : 
    2654                 :            :         /* Save the key with the given passphrase and comment. */
    2655         [ -  + ]:         53 :         if (!key_save_private(private, identity_file, passphrase1, comment,
    2656                 :            :             use_new_format, new_format_cipher, rounds)) {
    2657                 :            :                 printf("Saving the key failed: %s.\n", identity_file);
    2658                 :          0 :                 explicit_bzero(passphrase1, strlen(passphrase1));
    2659                 :          0 :                 free(passphrase1);
    2660                 :          0 :                 exit(1);
    2661                 :            :         }
    2662                 :            :         /* Clear the passphrase. */
    2663                 :         53 :         explicit_bzero(passphrase1, strlen(passphrase1));
    2664                 :         53 :         free(passphrase1);
    2665                 :            : 
    2666                 :            :         /* Clear the private key and the random number generator. */
    2667                 :         53 :         key_free(private);
    2668                 :            : 
    2669         [ +  + ]:         53 :         if (!quiet)
    2670                 :            :                 printf("Your identification has been saved in %s.\n", identity_file);
    2671                 :            : 
    2672                 :         53 :         strlcat(identity_file, ".pub", sizeof(identity_file));
    2673                 :         53 :         fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    2674         [ -  + ]:         53 :         if (fd == -1) {
    2675                 :            :                 printf("Could not save your public key in %s\n", identity_file);
    2676                 :          0 :                 exit(1);
    2677                 :            :         }
    2678                 :         53 :         f = fdopen(fd, "w");
    2679         [ -  + ]:         53 :         if (f == NULL) {
    2680                 :            :                 printf("fdopen %s failed\n", identity_file);
    2681                 :          0 :                 exit(1);
    2682                 :            :         }
    2683         [ -  + ]:         53 :         if (!key_write(public, f))
    2684                 :          0 :                 fprintf(stderr, "write key failed\n");
    2685                 :            :         fprintf(f, " %s\n", comment);
    2686                 :         53 :         fclose(f);
    2687                 :            : 
    2688         [ +  + ]:         53 :         if (!quiet) {
    2689                 :         10 :                 char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
    2690                 :         10 :                 char *ra = key_fingerprint(public, SSH_FP_MD5,
    2691                 :            :                     SSH_FP_RANDOMART);
    2692                 :            :                 printf("Your public key has been saved in %s.\n",
    2693                 :            :                     identity_file);
    2694                 :            :                 printf("The key fingerprint is:\n");
    2695                 :            :                 printf("%s %s\n", fp, comment);
    2696                 :            :                 printf("The key's randomart image is:\n");
    2697                 :            :                 printf("%s\n", ra);
    2698                 :         10 :                 free(ra);
    2699                 :         10 :                 free(fp);
    2700                 :            :         }
    2701                 :            : 
    2702                 :         53 :         key_free(public);
    2703                 :         53 :         exit(0);
    2704                 :            : }

Generated by: LCOV version 1.9