[BACK]Return to ssh-keygen.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/ssh-keygen.c, Revision 1.192

1.192   ! djm         1: /* $OpenBSD: ssh-keygen.c,v 1.191 2010/06/22 04:32:06 djm Exp $ */
1.1       deraadt     2: /*
1.13      deraadt     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.
1.31      deraadt     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".
1.13      deraadt    13:  */
1.1       deraadt    14:
1.136     stevesk    15: #include <sys/types.h>
1.174     dtucker    16: #include <sys/socket.h>
1.136     stevesk    17: #include <sys/stat.h>
1.151     stevesk    18: #include <sys/param.h>
1.19      markus     19:
                     20: #include <openssl/evp.h>
                     21: #include <openssl/pem.h>
1.145     stevesk    22:
1.148     stevesk    23: #include <errno.h>
1.147     stevesk    24: #include <fcntl.h>
1.145     stevesk    25: #include <pwd.h>
1.153     stevesk    26: #include <stdio.h>
1.152     stevesk    27: #include <stdlib.h>
1.150     stevesk    28: #include <string.h>
1.149     stevesk    29: #include <unistd.h>
1.1       deraadt    30:
                     31: #include "xmalloc.h"
1.19      markus     32: #include "key.h"
1.53      markus     33: #include "rsa.h"
1.19      markus     34: #include "authfile.h"
                     35: #include "uuencode.h"
1.32      markus     36: #include "buffer.h"
1.40      markus     37: #include "pathnames.h"
1.41      markus     38: #include "log.h"
1.114     djm        39: #include "misc.h"
1.119     djm        40: #include "match.h"
                     41: #include "hostfile.h"
1.146     stevesk    42: #include "dns.h"
1.179     djm        43: #include "ssh2.h"
1.32      markus     44:
1.177     markus     45: #ifdef ENABLE_PKCS11
                     46: #include "ssh-pkcs11.h"
1.106     djm        47: #endif
1.66      markus     48:
1.130     markus     49: /* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
                     50: #define DEFAULT_BITS           2048
                     51: #define DEFAULT_BITS_DSA       1024
                     52: u_int32_t bits = 0;
1.1       deraadt    53:
1.14      markus     54: /*
                     55:  * Flag indicating that we just want to change the passphrase.  This can be
                     56:  * set on the command line.
                     57:  */
1.1       deraadt    58: int change_passphrase = 0;
                     59:
1.14      markus     60: /*
                     61:  * Flag indicating that we just want to change the comment.  This can be set
                     62:  * on the command line.
                     63:  */
1.1       deraadt    64: int change_comment = 0;
                     65:
1.2       provos     66: int quiet = 0;
                     67:
1.169     grunk      68: int log_level = SYSLOG_LEVEL_INFO;
                     69:
1.119     djm        70: /* Flag indicating that we want to hash a known_hosts file */
                     71: int hash_hosts = 0;
                     72: /* Flag indicating that we want lookup a host in known_hosts file */
                     73: int find_host = 0;
                     74: /* Flag indicating that we want to delete a host from a known_hosts file */
                     75: int delete_host = 0;
                     76:
1.182     djm        77: /* Flag indicating that we want to show the contents of a certificate */
                     78: int show_cert = 0;
                     79:
1.8       markus     80: /* Flag indicating that we just want to see the key fingerprint */
                     81: int print_fingerprint = 0;
1.49      markus     82: int print_bubblebabble = 0;
1.8       markus     83:
1.10      markus     84: /* The identity file name, given on the command line or entered by the user. */
                     85: char identity_file[1024];
                     86: int have_identity = 0;
1.1       deraadt    87:
                     88: /* This is set to the passphrase if given on the command line. */
                     89: char *identity_passphrase = NULL;
                     90:
                     91: /* This is set to the new passphrase if given on the command line. */
                     92: char *identity_new_passphrase = NULL;
                     93:
                     94: /* This is set to the new comment if given on the command line. */
                     95: char *identity_comment = NULL;
                     96:
1.179     djm        97: /* Path to CA key when certifying keys. */
                     98: char *ca_key_path = NULL;
                     99:
1.186     djm       100: /* Certificate serial number */
                    101: long long cert_serial = 0;
                    102:
1.179     djm       103: /* Key type when certifying */
                    104: u_int cert_key_type = SSH2_CERT_TYPE_USER;
                    105:
                    106: /* "key ID" of signed key */
                    107: char *cert_key_id = NULL;
                    108:
                    109: /* Comma-separated list of principal names for certifying keys */
                    110: char *cert_principals = NULL;
                    111:
                    112: /* Validity period for certificates */
                    113: u_int64_t cert_valid_from = 0;
                    114: u_int64_t cert_valid_to = ~0ULL;
                    115:
1.186     djm       116: /* Certificate options */
1.190     djm       117: #define CERTOPT_X_FWD  (1)
                    118: #define CERTOPT_AGENT_FWD      (1<<1)
                    119: #define CERTOPT_PORT_FWD       (1<<2)
                    120: #define CERTOPT_PTY            (1<<3)
                    121: #define CERTOPT_USER_RC        (1<<4)
                    122: #define CERTOPT_DEFAULT        (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
                    123:                         CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
                    124: u_int32_t certflags_flags = CERTOPT_DEFAULT;
                    125: char *certflags_command = NULL;
                    126: char *certflags_src_addr = NULL;
1.179     djm       127:
1.19      markus    128: /* Dump public key file in format used by real and the original SSH 2 */
                    129: int convert_to_ssh2 = 0;
                    130: int convert_from_ssh2 = 0;
                    131: int print_public = 0;
1.105     jakob     132: int print_generic = 0;
1.33      markus    133:
1.87      djm       134: char *key_type_name = NULL;
1.19      markus    135:
1.10      markus    136: /* argv0 */
                    137: extern char *__progname;
1.1       deraadt   138:
1.19      markus    139: char hostname[MAXHOSTNAMELEN];
                    140:
1.115     djm       141: /* moduli.c */
1.124     avsm      142: int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
1.115     djm       143: int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
                    144:
1.63      itojun    145: static void
1.10      markus    146: ask_filename(struct passwd *pw, const char *prompt)
1.1       deraadt   147: {
1.12      markus    148:        char buf[1024];
1.35      markus    149:        char *name = NULL;
                    150:
1.92      stevesk   151:        if (key_type_name == NULL)
1.40      markus    152:                name = _PATH_SSH_CLIENT_ID_RSA;
1.140     deraadt   153:        else {
1.92      stevesk   154:                switch (key_type_from_name(key_type_name)) {
                    155:                case KEY_RSA1:
                    156:                        name = _PATH_SSH_CLIENT_IDENTITY;
                    157:                        break;
1.186     djm       158:                case KEY_DSA_CERT:
                    159:                case KEY_DSA_CERT_V00:
1.92      stevesk   160:                case KEY_DSA:
                    161:                        name = _PATH_SSH_CLIENT_ID_DSA;
                    162:                        break;
1.186     djm       163:                case KEY_RSA_CERT:
                    164:                case KEY_RSA_CERT_V00:
1.92      stevesk   165:                case KEY_RSA:
                    166:                        name = _PATH_SSH_CLIENT_ID_RSA;
                    167:                        break;
                    168:                default:
1.173     tobias    169:                        fprintf(stderr, "bad key type\n");
1.92      stevesk   170:                        exit(1);
                    171:                        break;
                    172:                }
1.140     deraadt   173:        }
1.35      markus    174:        snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
1.37      markus    175:        fprintf(stderr, "%s (%s): ", prompt, identity_file);
1.12      markus    176:        if (fgets(buf, sizeof(buf), stdin) == NULL)
                    177:                exit(1);
1.162     gilles    178:        buf[strcspn(buf, "\n")] = '\0';
1.12      markus    179:        if (strcmp(buf, "") != 0)
                    180:                strlcpy(identity_file, buf, sizeof(identity_file));
                    181:        have_identity = 1;
1.7       markus    182: }
                    183:
1.63      itojun    184: static Key *
1.61      markus    185: load_identity(char *filename)
1.19      markus    186: {
1.52      markus    187:        char *pass;
                    188:        Key *prv;
                    189:
1.55      markus    190:        prv = key_load_private(filename, "", NULL);
1.52      markus    191:        if (prv == NULL) {
1.61      markus    192:                if (identity_passphrase)
                    193:                        pass = xstrdup(identity_passphrase);
                    194:                else
1.65      markus    195:                        pass = read_passphrase("Enter passphrase: ",
                    196:                            RP_ALLOW_STDIN);
1.52      markus    197:                prv = key_load_private(filename, pass, NULL);
1.19      markus    198:                memset(pass, 0, strlen(pass));
                    199:                xfree(pass);
                    200:        }
1.52      markus    201:        return prv;
1.19      markus    202: }
                    203:
1.32      markus    204: #define SSH_COM_PUBLIC_BEGIN           "---- BEGIN SSH2 PUBLIC KEY ----"
1.100     deraadt   205: #define SSH_COM_PUBLIC_END             "---- END SSH2 PUBLIC KEY ----"
1.32      markus    206: #define SSH_COM_PRIVATE_BEGIN          "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
1.42      stevesk   207: #define        SSH_COM_PRIVATE_KEY_MAGIC       0x3f6ff9eb
1.19      markus    208:
1.63      itojun    209: static void
1.19      markus    210: do_convert_to_ssh2(struct passwd *pw)
                    211: {
1.59      markus    212:        Key *k;
1.94      markus    213:        u_int len;
1.36      markus    214:        u_char *blob;
1.176     djm       215:        char comment[61];
1.19      markus    216:        struct stat st;
                    217:
                    218:        if (!have_identity)
                    219:                ask_filename(pw, "Enter file in which the key is");
                    220:        if (stat(identity_file, &st) < 0) {
                    221:                perror(identity_file);
                    222:                exit(1);
                    223:        }
1.59      markus    224:        if ((k = key_load_public(identity_file, NULL)) == NULL) {
1.61      markus    225:                if ((k = load_identity(identity_file)) == NULL) {
1.59      markus    226:                        fprintf(stderr, "load failed\n");
                    227:                        exit(1);
                    228:                }
1.104     markus    229:        }
                    230:        if (k->type == KEY_RSA1) {
                    231:                fprintf(stderr, "version 1 keys are not supported\n");
                    232:                exit(1);
1.19      markus    233:        }
1.81      markus    234:        if (key_to_blob(k, &blob, &len) <= 0) {
                    235:                fprintf(stderr, "key_to_blob failed\n");
                    236:                exit(1);
                    237:        }
1.176     djm       238:        /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
                    239:        snprintf(comment, sizeof(comment),
                    240:            "%u-bit %s, converted by %s@%s from OpenSSH",
1.59      markus    241:            key_size(k), key_type(k),
1.19      markus    242:            pw->pw_name, hostname);
1.176     djm       243:
                    244:        fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
                    245:        fprintf(stdout, "Comment: \"%s\"\n", comment);
1.19      markus    246:        dump_base64(stdout, blob, len);
1.32      markus    247:        fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
1.59      markus    248:        key_free(k);
1.21      markus    249:        xfree(blob);
1.19      markus    250:        exit(0);
                    251: }
                    252:
1.63      itojun    253: static void
1.32      markus    254: buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
                    255: {
1.116     avsm      256:        u_int bignum_bits = buffer_get_int(b);
                    257:        u_int bytes = (bignum_bits + 7) / 8;
1.53      markus    258:
1.32      markus    259:        if (buffer_len(b) < bytes)
1.53      markus    260:                fatal("buffer_get_bignum_bits: input buffer too small: "
                    261:                    "need %d have %d", bytes, buffer_len(b));
1.155     markus    262:        if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL)
                    263:                fatal("buffer_get_bignum_bits: BN_bin2bn failed");
1.32      markus    264:        buffer_consume(b, bytes);
                    265: }
                    266:
1.63      itojun    267: static Key *
1.93      markus    268: do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
1.32      markus    269: {
                    270:        Buffer b;
                    271:        Key *key = NULL;
1.64      markus    272:        char *type, *cipher;
1.69      stevesk   273:        u_char *sig, data[] = "abcde12345";
1.62      markus    274:        int magic, rlen, ktype, i1, i2, i3, i4;
1.64      markus    275:        u_int slen;
1.62      markus    276:        u_long e;
1.32      markus    277:
                    278:        buffer_init(&b);
                    279:        buffer_append(&b, blob, blen);
                    280:
1.160     stevesk   281:        magic = buffer_get_int(&b);
1.32      markus    282:        if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
                    283:                error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
                    284:                buffer_free(&b);
                    285:                return NULL;
                    286:        }
1.62      markus    287:        i1 = buffer_get_int(&b);
1.32      markus    288:        type   = buffer_get_string(&b, NULL);
                    289:        cipher = buffer_get_string(&b, NULL);
1.62      markus    290:        i2 = buffer_get_int(&b);
                    291:        i3 = buffer_get_int(&b);
                    292:        i4 = buffer_get_int(&b);
1.158     stevesk   293:        debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
1.32      markus    294:        if (strcmp(cipher, "none") != 0) {
                    295:                error("unsupported cipher %s", cipher);
                    296:                xfree(cipher);
                    297:                buffer_free(&b);
1.53      markus    298:                xfree(type);
1.32      markus    299:                return NULL;
                    300:        }
                    301:        xfree(cipher);
                    302:
1.53      markus    303:        if (strstr(type, "dsa")) {
                    304:                ktype = KEY_DSA;
                    305:        } else if (strstr(type, "rsa")) {
                    306:                ktype = KEY_RSA;
                    307:        } else {
1.118     markus    308:                buffer_free(&b);
1.53      markus    309:                xfree(type);
1.32      markus    310:                return NULL;
                    311:        }
1.53      markus    312:        key = key_new_private(ktype);
                    313:        xfree(type);
                    314:
                    315:        switch (key->type) {
                    316:        case KEY_DSA:
                    317:                buffer_get_bignum_bits(&b, key->dsa->p);
                    318:                buffer_get_bignum_bits(&b, key->dsa->g);
                    319:                buffer_get_bignum_bits(&b, key->dsa->q);
                    320:                buffer_get_bignum_bits(&b, key->dsa->pub_key);
                    321:                buffer_get_bignum_bits(&b, key->dsa->priv_key);
                    322:                break;
                    323:        case KEY_RSA:
1.160     stevesk   324:                e = buffer_get_char(&b);
1.62      markus    325:                debug("e %lx", e);
                    326:                if (e < 30) {
                    327:                        e <<= 8;
                    328:                        e += buffer_get_char(&b);
                    329:                        debug("e %lx", e);
                    330:                        e <<= 8;
                    331:                        e += buffer_get_char(&b);
                    332:                        debug("e %lx", e);
                    333:                }
                    334:                if (!BN_set_word(key->rsa->e, e)) {
1.53      markus    335:                        buffer_free(&b);
                    336:                        key_free(key);
                    337:                        return NULL;
                    338:                }
                    339:                buffer_get_bignum_bits(&b, key->rsa->d);
                    340:                buffer_get_bignum_bits(&b, key->rsa->n);
                    341:                buffer_get_bignum_bits(&b, key->rsa->iqmp);
                    342:                buffer_get_bignum_bits(&b, key->rsa->q);
                    343:                buffer_get_bignum_bits(&b, key->rsa->p);
1.68      markus    344:                rsa_generate_additional_parameters(key->rsa);
1.53      markus    345:                break;
                    346:        }
1.32      markus    347:        rlen = buffer_len(&b);
1.85      deraadt   348:        if (rlen != 0)
1.53      markus    349:                error("do_convert_private_ssh2_from_blob: "
                    350:                    "remaining bytes in key blob %d", rlen);
1.32      markus    351:        buffer_free(&b);
1.64      markus    352:
                    353:        /* try the key */
                    354:        key_sign(key, &sig, &slen, data, sizeof(data));
                    355:        key_verify(key, sig, slen, data, sizeof(data));
                    356:        xfree(sig);
1.32      markus    357:        return key;
                    358: }
                    359:
1.137     dtucker   360: static int
                    361: get_line(FILE *fp, char *line, size_t len)
                    362: {
                    363:        int c;
                    364:        size_t pos = 0;
                    365:
                    366:        line[0] = '\0';
                    367:        while ((c = fgetc(fp)) != EOF) {
                    368:                if (pos >= len - 1) {
                    369:                        fprintf(stderr, "input line too long.\n");
                    370:                        exit(1);
                    371:                }
1.140     deraadt   372:                switch (c) {
1.137     dtucker   373:                case '\r':
                    374:                        c = fgetc(fp);
                    375:                        if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
                    376:                                fprintf(stderr, "unget: %s\n", strerror(errno));
                    377:                                exit(1);
                    378:                        }
                    379:                        return pos;
                    380:                case '\n':
                    381:                        return pos;
                    382:                }
                    383:                line[pos++] = c;
                    384:                line[pos] = '\0';
                    385:        }
1.157     stevesk   386:        /* We reached EOF */
                    387:        return -1;
1.137     dtucker   388: }
                    389:
1.63      itojun    390: static void
1.19      markus    391: do_convert_from_ssh2(struct passwd *pw)
                    392: {
                    393:        Key *k;
                    394:        int blen;
1.98      markus    395:        u_int len;
1.137     dtucker   396:        char line[1024];
1.80      stevesk   397:        u_char blob[8096];
1.19      markus    398:        char encoded[8096];
                    399:        struct stat st;
1.32      markus    400:        int escaped = 0, private = 0, ok;
1.19      markus    401:        FILE *fp;
                    402:
                    403:        if (!have_identity)
                    404:                ask_filename(pw, "Enter file in which the key is");
                    405:        if (stat(identity_file, &st) < 0) {
                    406:                perror(identity_file);
                    407:                exit(1);
                    408:        }
1.191     djm       409:        if ((fp = fopen(identity_file, "r")) == NULL)
                    410:                fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
1.19      markus    411:        encoded[0] = '\0';
1.137     dtucker   412:        while ((blen = get_line(fp, line, sizeof(line))) != -1) {
                    413:                if (line[blen - 1] == '\\')
1.25      markus    414:                        escaped++;
1.19      markus    415:                if (strncmp(line, "----", 4) == 0 ||
                    416:                    strstr(line, ": ") != NULL) {
1.32      markus    417:                        if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
                    418:                                private = 1;
1.64      markus    419:                        if (strstr(line, " END ") != NULL) {
                    420:                                break;
                    421:                        }
1.60      markus    422:                        /* fprintf(stderr, "ignore: %s", line); */
1.19      markus    423:                        continue;
                    424:                }
1.25      markus    425:                if (escaped) {
                    426:                        escaped--;
1.60      markus    427:                        /* fprintf(stderr, "escaped: %s", line); */
1.25      markus    428:                        continue;
1.19      markus    429:                }
                    430:                strlcat(encoded, line, sizeof(encoded));
                    431:        }
1.98      markus    432:        len = strlen(encoded);
                    433:        if (((len % 4) == 3) &&
                    434:            (encoded[len-1] == '=') &&
                    435:            (encoded[len-2] == '=') &&
                    436:            (encoded[len-3] == '='))
                    437:                encoded[len-3] = '\0';
1.91      stevesk   438:        blen = uudecode(encoded, blob, sizeof(blob));
1.19      markus    439:        if (blen < 0) {
                    440:                fprintf(stderr, "uudecode failed.\n");
                    441:                exit(1);
                    442:        }
1.32      markus    443:        k = private ?
                    444:            do_convert_private_ssh2_from_blob(blob, blen) :
1.33      markus    445:            key_from_blob(blob, blen);
1.32      markus    446:        if (k == NULL) {
                    447:                fprintf(stderr, "decode blob failed.\n");
                    448:                exit(1);
                    449:        }
                    450:        ok = private ?
1.53      markus    451:            (k->type == KEY_DSA ?
                    452:                 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
                    453:                 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
1.32      markus    454:            key_write(k, stdout);
                    455:        if (!ok) {
1.173     tobias    456:                fprintf(stderr, "key write failed\n");
1.32      markus    457:                exit(1);
                    458:        }
1.19      markus    459:        key_free(k);
1.90      markus    460:        if (!private)
                    461:                fprintf(stdout, "\n");
1.19      markus    462:        fclose(fp);
                    463:        exit(0);
                    464: }
                    465:
1.63      itojun    466: static void
1.19      markus    467: do_print_public(struct passwd *pw)
                    468: {
1.52      markus    469:        Key *prv;
1.19      markus    470:        struct stat st;
                    471:
                    472:        if (!have_identity)
                    473:                ask_filename(pw, "Enter file in which the key is");
                    474:        if (stat(identity_file, &st) < 0) {
                    475:                perror(identity_file);
                    476:                exit(1);
                    477:        }
1.61      markus    478:        prv = load_identity(identity_file);
1.52      markus    479:        if (prv == NULL) {
1.19      markus    480:                fprintf(stderr, "load failed\n");
                    481:                exit(1);
                    482:        }
1.52      markus    483:        if (!key_write(prv, stdout))
1.19      markus    484:                fprintf(stderr, "key_write failed");
1.52      markus    485:        key_free(prv);
1.19      markus    486:        fprintf(stdout, "\n");
                    487:        exit(0);
                    488: }
                    489:
1.66      markus    490: static void
1.178     djm       491: do_download(struct passwd *pw, char *pkcs11provider)
1.75      markus    492: {
1.177     markus    493: #ifdef ENABLE_PKCS11
1.97      markus    494:        Key **keys = NULL;
1.177     markus    495:        int i, nkeys;
1.75      markus    496:
1.177     markus    497:        pkcs11_init(0);
                    498:        nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
                    499:        if (nkeys <= 0)
                    500:                fatal("cannot read public key from pkcs11");
                    501:        for (i = 0; i < nkeys; i++) {
1.97      markus    502:                key_write(keys[i], stdout);
                    503:                key_free(keys[i]);
                    504:                fprintf(stdout, "\n");
                    505:        }
                    506:        xfree(keys);
1.177     markus    507:        pkcs11_terminate();
1.75      markus    508:        exit(0);
1.177     markus    509: #else
                    510:        fatal("no pkcs11 support");
                    511: #endif /* ENABLE_PKCS11 */
1.75      markus    512: }
1.66      markus    513:
1.63      itojun    514: static void
1.8       markus    515: do_fingerprint(struct passwd *pw)
                    516: {
1.15      markus    517:        FILE *f;
1.19      markus    518:        Key *public;
1.167     grunk     519:        char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
1.165     djm       520:        int i, skip = 0, num = 0, invalid = 1;
1.84      stevesk   521:        enum fp_rep rep;
                    522:        enum fp_type fptype;
1.12      markus    523:        struct stat st;
                    524:
1.52      markus    525:        fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
                    526:        rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
1.49      markus    527:
1.12      markus    528:        if (!have_identity)
                    529:                ask_filename(pw, "Enter file in which the key is");
                    530:        if (stat(identity_file, &st) < 0) {
                    531:                perror(identity_file);
                    532:                exit(1);
                    533:        }
1.52      markus    534:        public = key_load_public(identity_file, &comment);
                    535:        if (public != NULL) {
                    536:                fp = key_fingerprint(public, fptype, rep);
1.175     djm       537:                ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
1.170     grunk     538:                printf("%u %s %s (%s)\n", key_size(public), fp, comment,
                    539:                    key_type(public));
1.169     grunk     540:                if (log_level >= SYSLOG_LEVEL_VERBOSE)
                    541:                        printf("%s\n", ra);
1.33      markus    542:                key_free(public);
                    543:                xfree(comment);
1.167     grunk     544:                xfree(ra);
1.49      markus    545:                xfree(fp);
1.15      markus    546:                exit(0);
                    547:        }
1.144     markus    548:        if (comment) {
1.52      markus    549:                xfree(comment);
1.144     markus    550:                comment = NULL;
                    551:        }
1.15      markus    552:
1.191     djm       553:        if ((f = fopen(identity_file, "r")) == NULL)
                    554:                fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
                    555:
                    556:        while (fgets(line, sizeof(line), f)) {
                    557:                if ((cp = strchr(line, '\n')) == NULL) {
                    558:                        error("line %d too long: %.40s...",
                    559:                            num + 1, line);
                    560:                        skip = 1;
                    561:                        continue;
                    562:                }
                    563:                num++;
                    564:                if (skip) {
                    565:                        skip = 0;
                    566:                        continue;
                    567:                }
                    568:                *cp = '\0';
                    569:
                    570:                /* Skip leading whitespace, empty and comment lines. */
                    571:                for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
                    572:                        ;
                    573:                if (!*cp || *cp == '\n' || *cp == '#')
                    574:                        continue;
                    575:                i = strtol(cp, &ep, 10);
                    576:                if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
                    577:                        int quoted = 0;
                    578:                        comment = cp;
                    579:                        for (; *cp && (quoted || (*cp != ' ' &&
                    580:                            *cp != '\t')); cp++) {
                    581:                                if (*cp == '\\' && cp[1] == '"')
                    582:                                        cp++;   /* Skip both */
                    583:                                else if (*cp == '"')
                    584:                                        quoted = !quoted;
1.15      markus    585:                        }
1.191     djm       586:                        if (!*cp)
1.15      markus    587:                                continue;
1.191     djm       588:                        *cp++ = '\0';
                    589:                }
                    590:                ep = cp;
                    591:                public = key_new(KEY_RSA1);
                    592:                if (key_read(public, &cp) != 1) {
                    593:                        cp = ep;
                    594:                        key_free(public);
                    595:                        public = key_new(KEY_UNSPEC);
1.38      markus    596:                        if (key_read(public, &cp) != 1) {
                    597:                                key_free(public);
1.191     djm       598:                                continue;
1.12      markus    599:                        }
                    600:                }
1.191     djm       601:                comment = *cp ? cp : comment;
                    602:                fp = key_fingerprint(public, fptype, rep);
                    603:                ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
                    604:                printf("%u %s %s (%s)\n", key_size(public), fp,
                    605:                    comment ? comment : "no comment", key_type(public));
                    606:                if (log_level >= SYSLOG_LEVEL_VERBOSE)
                    607:                        printf("%s\n", ra);
                    608:                xfree(ra);
                    609:                xfree(fp);
                    610:                key_free(public);
                    611:                invalid = 0;
1.15      markus    612:        }
1.191     djm       613:        fclose(f);
                    614:
1.15      markus    615:        if (invalid) {
1.83      markus    616:                printf("%s is not a public key file.\n", identity_file);
1.15      markus    617:                exit(1);
1.12      markus    618:        }
                    619:        exit(0);
1.8       markus    620: }
                    621:
1.119     djm       622: static void
1.179     djm       623: printhost(FILE *f, const char *name, Key *public, int ca, int hash)
1.119     djm       624: {
1.166     djm       625:        if (print_fingerprint) {
                    626:                enum fp_rep rep;
                    627:                enum fp_type fptype;
1.167     grunk     628:                char *fp, *ra;
1.166     djm       629:
                    630:                fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
                    631:                rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
                    632:                fp = key_fingerprint(public, fptype, rep);
1.175     djm       633:                ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
1.171     sthen     634:                printf("%u %s %s (%s)\n", key_size(public), fp, name,
                    635:                    key_type(public));
                    636:                if (log_level >= SYSLOG_LEVEL_VERBOSE)
                    637:                        printf("%s\n", ra);
1.167     grunk     638:                xfree(ra);
1.166     djm       639:                xfree(fp);
                    640:        } else {
                    641:                if (hash && (name = host_hash(name, NULL, 0)) == NULL)
                    642:                        fatal("hash_host failed");
1.179     djm       643:                fprintf(f, "%s%s%s ", ca ? CA_MARKER : "", ca ? " " : "", name);
1.166     djm       644:                if (!key_write(public, f))
                    645:                        fatal("key_write failed");
                    646:                fprintf(f, "\n");
                    647:        }
1.119     djm       648: }
                    649:
                    650: static void
                    651: do_known_hosts(struct passwd *pw, const char *name)
                    652: {
                    653:        FILE *in, *out = stdout;
1.179     djm       654:        Key *pub;
1.119     djm       655:        char *cp, *cp2, *kp, *kp2;
                    656:        char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
1.165     djm       657:        int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
1.179     djm       658:        int ca;
1.119     djm       659:
                    660:        if (!have_identity) {
                    661:                cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
                    662:                if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
                    663:                    sizeof(identity_file))
                    664:                        fatal("Specified known hosts path too long");
                    665:                xfree(cp);
                    666:                have_identity = 1;
                    667:        }
                    668:        if ((in = fopen(identity_file, "r")) == NULL)
1.191     djm       669:                fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
1.119     djm       670:
                    671:        /*
                    672:         * Find hosts goes to stdout, hash and deletions happen in-place
                    673:         * A corner case is ssh-keygen -HF foo, which should go to stdout
                    674:         */
                    675:        if (!find_host && (hash_hosts || delete_host)) {
                    676:                if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
                    677:                    strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
                    678:                    strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
                    679:                    strlcat(old, ".old", sizeof(old)) >= sizeof(old))
                    680:                        fatal("known_hosts path too long");
                    681:                umask(077);
                    682:                if ((c = mkstemp(tmp)) == -1)
                    683:                        fatal("mkstemp: %s", strerror(errno));
                    684:                if ((out = fdopen(c, "w")) == NULL) {
                    685:                        c = errno;
                    686:                        unlink(tmp);
                    687:                        fatal("fdopen: %s", strerror(c));
                    688:                }
                    689:                inplace = 1;
                    690:        }
                    691:
                    692:        while (fgets(line, sizeof(line), in)) {
1.163     chl       693:                if ((cp = strchr(line, '\n')) == NULL) {
1.165     djm       694:                        error("line %d too long: %.40s...", num + 1, line);
1.119     djm       695:                        skip = 1;
                    696:                        invalid = 1;
                    697:                        continue;
                    698:                }
1.163     chl       699:                num++;
1.119     djm       700:                if (skip) {
                    701:                        skip = 0;
                    702:                        continue;
                    703:                }
1.163     chl       704:                *cp = '\0';
1.119     djm       705:
                    706:                /* Skip leading whitespace, empty and comment lines. */
                    707:                for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
                    708:                        ;
                    709:                if (!*cp || *cp == '\n' || *cp == '#') {
                    710:                        if (inplace)
                    711:                                fprintf(out, "%s\n", cp);
                    712:                        continue;
                    713:                }
1.179     djm       714:                /* Check whether this is a CA key */
                    715:                if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 &&
                    716:                    (cp[sizeof(CA_MARKER) - 1] == ' ' ||
                    717:                    cp[sizeof(CA_MARKER) - 1] == '\t')) {
                    718:                        ca = 1;
                    719:                        cp += sizeof(CA_MARKER);
                    720:                } else
                    721:                        ca = 0;
                    722:
1.119     djm       723:                /* Find the end of the host name portion. */
                    724:                for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
                    725:                        ;
1.179     djm       726:
1.119     djm       727:                if (*kp == '\0' || *(kp + 1) == '\0') {
                    728:                        error("line %d missing key: %.40s...",
                    729:                            num, line);
                    730:                        invalid = 1;
                    731:                        continue;
                    732:                }
                    733:                *kp++ = '\0';
                    734:                kp2 = kp;
                    735:
1.179     djm       736:                pub = key_new(KEY_RSA1);
                    737:                if (key_read(pub, &kp) != 1) {
1.119     djm       738:                        kp = kp2;
1.179     djm       739:                        key_free(pub);
                    740:                        pub = key_new(KEY_UNSPEC);
                    741:                        if (key_read(pub, &kp) != 1) {
1.119     djm       742:                                error("line %d invalid key: %.40s...",
                    743:                                    num, line);
1.179     djm       744:                                key_free(pub);
1.119     djm       745:                                invalid = 1;
                    746:                                continue;
                    747:                        }
                    748:                }
                    749:
                    750:                if (*cp == HASH_DELIM) {
                    751:                        if (find_host || delete_host) {
                    752:                                cp2 = host_hash(name, cp, strlen(cp));
                    753:                                if (cp2 == NULL) {
                    754:                                        error("line %d: invalid hashed "
                    755:                                            "name: %.64s...", num, line);
                    756:                                        invalid = 1;
                    757:                                        continue;
                    758:                                }
                    759:                                c = (strcmp(cp2, cp) == 0);
                    760:                                if (find_host && c) {
                    761:                                        printf("# Host %s found: "
1.179     djm       762:                                            "line %d type %s%s\n", name,
                    763:                                            num, key_type(pub),
                    764:                                            ca ? " (CA key)" : "");
                    765:                                        printhost(out, cp, pub, ca, 0);
1.119     djm       766:                                }
1.179     djm       767:                                if (delete_host && !c && !ca)
                    768:                                        printhost(out, cp, pub, ca, 0);
1.119     djm       769:                        } else if (hash_hosts)
1.179     djm       770:                                printhost(out, cp, pub, ca, 0);
1.119     djm       771:                } else {
                    772:                        if (find_host || delete_host) {
                    773:                                c = (match_hostname(name, cp,
                    774:                                    strlen(cp)) == 1);
                    775:                                if (find_host && c) {
                    776:                                        printf("# Host %s found: "
1.179     djm       777:                                            "line %d type %s%s\n", name,
                    778:                                            num, key_type(pub),
                    779:                                            ca ? " (CA key)" : "");
                    780:                                        printhost(out, name, pub,
                    781:                                            ca, hash_hosts && !ca);
1.119     djm       782:                                }
1.179     djm       783:                                if (delete_host && !c && !ca)
                    784:                                        printhost(out, cp, pub, ca, 0);
1.119     djm       785:                        } else if (hash_hosts) {
1.121     deraadt   786:                                for (cp2 = strsep(&cp, ",");
1.119     djm       787:                                    cp2 != NULL && *cp2 != '\0';
1.120     djm       788:                                    cp2 = strsep(&cp, ",")) {
1.179     djm       789:                                        if (ca) {
                    790:                                                fprintf(stderr, "Warning: "
                    791:                                                    "ignoring CA key for host: "
                    792:                                                    "%.64s\n", cp2);
                    793:                                                printhost(out, cp2, pub, ca, 0);
                    794:                                        } else if (strcspn(cp2, "*?!") !=
                    795:                                            strlen(cp2)) {
1.120     djm       796:                                                fprintf(stderr, "Warning: "
                    797:                                                    "ignoring host name with "
                    798:                                                    "metacharacters: %.64s\n",
                    799:                                                    cp2);
1.179     djm       800:                                                printhost(out, cp2, pub, ca, 0);
                    801:                                        } else
                    802:                                                printhost(out, cp2, pub, ca, 1);
1.120     djm       803:                                }
1.119     djm       804:                                has_unhashed = 1;
                    805:                        }
                    806:                }
1.179     djm       807:                key_free(pub);
1.119     djm       808:        }
                    809:        fclose(in);
                    810:
                    811:        if (invalid) {
1.165     djm       812:                fprintf(stderr, "%s is not a valid known_hosts file.\n",
1.119     djm       813:                    identity_file);
                    814:                if (inplace) {
                    815:                        fprintf(stderr, "Not replacing existing known_hosts "
1.122     markus    816:                            "file because of errors\n");
1.119     djm       817:                        fclose(out);
                    818:                        unlink(tmp);
                    819:                }
                    820:                exit(1);
                    821:        }
                    822:
                    823:        if (inplace) {
                    824:                fclose(out);
                    825:
                    826:                /* Backup existing file */
                    827:                if (unlink(old) == -1 && errno != ENOENT)
                    828:                        fatal("unlink %.100s: %s", old, strerror(errno));
                    829:                if (link(identity_file, old) == -1)
                    830:                        fatal("link %.100s to %.100s: %s", identity_file, old,
                    831:                            strerror(errno));
                    832:                /* Move new one into place */
                    833:                if (rename(tmp, identity_file) == -1) {
                    834:                        error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
                    835:                            strerror(errno));
                    836:                        unlink(tmp);
                    837:                        unlink(old);
                    838:                        exit(1);
                    839:                }
                    840:
                    841:                fprintf(stderr, "%s updated.\n", identity_file);
                    842:                fprintf(stderr, "Original contents retained as %s\n", old);
                    843:                if (has_unhashed) {
                    844:                        fprintf(stderr, "WARNING: %s contains unhashed "
                    845:                            "entries\n", old);
                    846:                        fprintf(stderr, "Delete this file to ensure privacy "
1.128     djm       847:                            "of hostnames\n");
1.119     djm       848:                }
                    849:        }
                    850:
                    851:        exit(0);
                    852: }
                    853:
1.13      deraadt   854: /*
                    855:  * Perform changing a passphrase.  The argument is the passwd structure
                    856:  * for the current user.
                    857:  */
1.63      itojun    858: static void
1.7       markus    859: do_change_passphrase(struct passwd *pw)
                    860: {
1.12      markus    861:        char *comment;
                    862:        char *old_passphrase, *passphrase1, *passphrase2;
                    863:        struct stat st;
1.19      markus    864:        Key *private;
1.12      markus    865:
                    866:        if (!have_identity)
                    867:                ask_filename(pw, "Enter file in which the key is");
                    868:        if (stat(identity_file, &st) < 0) {
                    869:                perror(identity_file);
                    870:                exit(1);
                    871:        }
                    872:        /* Try to load the file with empty passphrase. */
1.52      markus    873:        private = key_load_private(identity_file, "", &comment);
                    874:        if (private == NULL) {
1.12      markus    875:                if (identity_passphrase)
                    876:                        old_passphrase = xstrdup(identity_passphrase);
                    877:                else
1.65      markus    878:                        old_passphrase =
                    879:                            read_passphrase("Enter old passphrase: ",
                    880:                            RP_ALLOW_STDIN);
                    881:                private = key_load_private(identity_file, old_passphrase,
                    882:                    &comment);
1.52      markus    883:                memset(old_passphrase, 0, strlen(old_passphrase));
                    884:                xfree(old_passphrase);
                    885:                if (private == NULL) {
1.12      markus    886:                        printf("Bad passphrase.\n");
                    887:                        exit(1);
                    888:                }
                    889:        }
                    890:        printf("Key has comment '%s'\n", comment);
                    891:
                    892:        /* Ask the new passphrase (twice). */
                    893:        if (identity_new_passphrase) {
                    894:                passphrase1 = xstrdup(identity_new_passphrase);
                    895:                passphrase2 = NULL;
                    896:        } else {
                    897:                passphrase1 =
1.65      markus    898:                        read_passphrase("Enter new passphrase (empty for no "
                    899:                            "passphrase): ", RP_ALLOW_STDIN);
                    900:                passphrase2 = read_passphrase("Enter same passphrase again: ",
1.86      deraadt   901:                    RP_ALLOW_STDIN);
1.12      markus    902:
                    903:                /* Verify that they are the same. */
                    904:                if (strcmp(passphrase1, passphrase2) != 0) {
                    905:                        memset(passphrase1, 0, strlen(passphrase1));
                    906:                        memset(passphrase2, 0, strlen(passphrase2));
                    907:                        xfree(passphrase1);
                    908:                        xfree(passphrase2);
                    909:                        printf("Pass phrases do not match.  Try again.\n");
                    910:                        exit(1);
                    911:                }
                    912:                /* Destroy the other copy. */
                    913:                memset(passphrase2, 0, strlen(passphrase2));
                    914:                xfree(passphrase2);
                    915:        }
                    916:
                    917:        /* Save the file using the new passphrase. */
1.52      markus    918:        if (!key_save_private(private, identity_file, passphrase1, comment)) {
1.56      markus    919:                printf("Saving the key failed: %s.\n", identity_file);
1.12      markus    920:                memset(passphrase1, 0, strlen(passphrase1));
                    921:                xfree(passphrase1);
1.19      markus    922:                key_free(private);
1.12      markus    923:                xfree(comment);
                    924:                exit(1);
                    925:        }
                    926:        /* Destroy the passphrase and the copy of the key in memory. */
                    927:        memset(passphrase1, 0, strlen(passphrase1));
                    928:        xfree(passphrase1);
1.19      markus    929:        key_free(private);               /* Destroys contents */
1.12      markus    930:        xfree(comment);
1.1       deraadt   931:
1.12      markus    932:        printf("Your identification has been saved with the new passphrase.\n");
                    933:        exit(0);
1.1       deraadt   934: }
                    935:
1.105     jakob     936: /*
                    937:  * Print the SSHFP RR.
                    938:  */
1.138     jakob     939: static int
                    940: do_print_resource_record(struct passwd *pw, char *fname, char *hname)
1.105     jakob     941: {
                    942:        Key *public;
                    943:        char *comment = NULL;
                    944:        struct stat st;
                    945:
1.138     jakob     946:        if (fname == NULL)
1.105     jakob     947:                ask_filename(pw, "Enter file in which the key is");
1.138     jakob     948:        if (stat(fname, &st) < 0) {
                    949:                if (errno == ENOENT)
                    950:                        return 0;
                    951:                perror(fname);
1.105     jakob     952:                exit(1);
                    953:        }
1.138     jakob     954:        public = key_load_public(fname, &comment);
1.105     jakob     955:        if (public != NULL) {
1.116     avsm      956:                export_dns_rr(hname, public, stdout, print_generic);
1.105     jakob     957:                key_free(public);
                    958:                xfree(comment);
1.138     jakob     959:                return 1;
1.105     jakob     960:        }
                    961:        if (comment)
                    962:                xfree(comment);
                    963:
1.138     jakob     964:        printf("failed to read v2 public key from %s.\n", fname);
1.105     jakob     965:        exit(1);
                    966: }
                    967:
1.13      deraadt   968: /*
                    969:  * Change the comment of a private key file.
                    970:  */
1.63      itojun    971: static void
1.2       provos    972: do_change_comment(struct passwd *pw)
1.1       deraadt   973: {
1.46      deraadt   974:        char new_comment[1024], *comment, *passphrase;
1.52      markus    975:        Key *private;
                    976:        Key *public;
1.12      markus    977:        struct stat st;
                    978:        FILE *f;
1.46      deraadt   979:        int fd;
1.12      markus    980:
                    981:        if (!have_identity)
                    982:                ask_filename(pw, "Enter file in which the key is");
                    983:        if (stat(identity_file, &st) < 0) {
                    984:                perror(identity_file);
                    985:                exit(1);
                    986:        }
1.52      markus    987:        private = key_load_private(identity_file, "", &comment);
                    988:        if (private == NULL) {
1.12      markus    989:                if (identity_passphrase)
                    990:                        passphrase = xstrdup(identity_passphrase);
                    991:                else if (identity_new_passphrase)
                    992:                        passphrase = xstrdup(identity_new_passphrase);
                    993:                else
1.65      markus    994:                        passphrase = read_passphrase("Enter passphrase: ",
                    995:                            RP_ALLOW_STDIN);
1.12      markus    996:                /* Try to load using the passphrase. */
1.52      markus    997:                private = key_load_private(identity_file, passphrase, &comment);
                    998:                if (private == NULL) {
1.12      markus    999:                        memset(passphrase, 0, strlen(passphrase));
                   1000:                        xfree(passphrase);
                   1001:                        printf("Bad passphrase.\n");
                   1002:                        exit(1);
                   1003:                }
1.52      markus   1004:        } else {
                   1005:                passphrase = xstrdup("");
1.12      markus   1006:        }
1.52      markus   1007:        if (private->type != KEY_RSA1) {
                   1008:                fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
                   1009:                key_free(private);
                   1010:                exit(1);
1.86      deraadt  1011:        }
1.12      markus   1012:        printf("Key now has comment '%s'\n", comment);
                   1013:
                   1014:        if (identity_comment) {
                   1015:                strlcpy(new_comment, identity_comment, sizeof(new_comment));
                   1016:        } else {
                   1017:                printf("Enter new comment: ");
                   1018:                fflush(stdout);
                   1019:                if (!fgets(new_comment, sizeof(new_comment), stdin)) {
                   1020:                        memset(passphrase, 0, strlen(passphrase));
1.19      markus   1021:                        key_free(private);
1.12      markus   1022:                        exit(1);
                   1023:                }
1.162     gilles   1024:                new_comment[strcspn(new_comment, "\n")] = '\0';
1.12      markus   1025:        }
                   1026:
                   1027:        /* Save the file using the new passphrase. */
1.52      markus   1028:        if (!key_save_private(private, identity_file, passphrase, new_comment)) {
1.56      markus   1029:                printf("Saving the key failed: %s.\n", identity_file);
1.12      markus   1030:                memset(passphrase, 0, strlen(passphrase));
                   1031:                xfree(passphrase);
1.19      markus   1032:                key_free(private);
1.12      markus   1033:                xfree(comment);
                   1034:                exit(1);
                   1035:        }
                   1036:        memset(passphrase, 0, strlen(passphrase));
                   1037:        xfree(passphrase);
1.52      markus   1038:        public = key_from_private(private);
1.19      markus   1039:        key_free(private);
1.12      markus   1040:
                   1041:        strlcat(identity_file, ".pub", sizeof(identity_file));
1.46      deraadt  1042:        fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
                   1043:        if (fd == -1) {
1.12      markus   1044:                printf("Could not save your public key in %s\n", identity_file);
                   1045:                exit(1);
                   1046:        }
1.46      deraadt  1047:        f = fdopen(fd, "w");
                   1048:        if (f == NULL) {
1.173     tobias   1049:                printf("fdopen %s failed\n", identity_file);
1.46      deraadt  1050:                exit(1);
                   1051:        }
1.19      markus   1052:        if (!key_write(public, f))
1.173     tobias   1053:                fprintf(stderr, "write key failed\n");
1.19      markus   1054:        key_free(public);
                   1055:        fprintf(f, " %s\n", new_comment);
1.12      markus   1056:        fclose(f);
1.1       deraadt  1057:
1.12      markus   1058:        xfree(comment);
1.1       deraadt  1059:
1.12      markus   1060:        printf("The comment in your key file has been changed.\n");
                   1061:        exit(0);
1.1       deraadt  1062: }
                   1063:
1.179     djm      1064: static const char *
1.182     djm      1065: fmt_validity(u_int64_t valid_from, u_int64_t valid_to)
1.179     djm      1066: {
                   1067:        char from[32], to[32];
                   1068:        static char ret[64];
                   1069:        time_t tt;
                   1070:        struct tm *tm;
                   1071:
                   1072:        *from = *to = '\0';
1.182     djm      1073:        if (valid_from == 0 && valid_to == 0xffffffffffffffffULL)
1.179     djm      1074:                return "forever";
                   1075:
1.182     djm      1076:        if (valid_from != 0) {
1.179     djm      1077:                /* XXX revisit INT_MAX in 2038 :) */
1.182     djm      1078:                tt = valid_from > INT_MAX ? INT_MAX : valid_from;
1.179     djm      1079:                tm = localtime(&tt);
                   1080:                strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
                   1081:        }
1.182     djm      1082:        if (valid_to != 0xffffffffffffffffULL) {
1.179     djm      1083:                /* XXX revisit INT_MAX in 2038 :) */
1.182     djm      1084:                tt = valid_to > INT_MAX ? INT_MAX : valid_to;
1.179     djm      1085:                tm = localtime(&tt);
                   1086:                strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
                   1087:        }
                   1088:
1.182     djm      1089:        if (valid_from == 0) {
1.179     djm      1090:                snprintf(ret, sizeof(ret), "before %s", to);
                   1091:                return ret;
                   1092:        }
1.182     djm      1093:        if (valid_to == 0xffffffffffffffffULL) {
1.179     djm      1094:                snprintf(ret, sizeof(ret), "after %s", from);
                   1095:                return ret;
                   1096:        }
                   1097:
                   1098:        snprintf(ret, sizeof(ret), "from %s to %s", from, to);
                   1099:        return ret;
                   1100: }
                   1101:
                   1102: static void
1.186     djm      1103: add_flag_option(Buffer *c, const char *name)
1.179     djm      1104: {
                   1105:        debug3("%s: %s", __func__, name);
                   1106:        buffer_put_cstring(c, name);
                   1107:        buffer_put_string(c, NULL, 0);
                   1108: }
                   1109:
                   1110: static void
1.186     djm      1111: add_string_option(Buffer *c, const char *name, const char *value)
1.179     djm      1112: {
                   1113:        Buffer b;
                   1114:
                   1115:        debug3("%s: %s=%s", __func__, name, value);
                   1116:        buffer_init(&b);
                   1117:        buffer_put_cstring(&b, value);
                   1118:
                   1119:        buffer_put_cstring(c, name);
                   1120:        buffer_put_string(c, buffer_ptr(&b), buffer_len(&b));
                   1121:
                   1122:        buffer_free(&b);
                   1123: }
                   1124:
1.190     djm      1125: #define OPTIONS_CRITICAL       1
                   1126: #define OPTIONS_EXTENSIONS     2
1.179     djm      1127: static void
1.190     djm      1128: prepare_options_buf(Buffer *c, int which)
1.179     djm      1129: {
                   1130:        buffer_clear(c);
1.190     djm      1131:        if ((which & OPTIONS_EXTENSIONS) != 0 &&
                   1132:            (certflags_flags & CERTOPT_X_FWD) != 0)
1.186     djm      1133:                add_flag_option(c, "permit-X11-forwarding");
1.190     djm      1134:        if ((which & OPTIONS_EXTENSIONS) != 0 &&
                   1135:            (certflags_flags & CERTOPT_AGENT_FWD) != 0)
1.186     djm      1136:                add_flag_option(c, "permit-agent-forwarding");
1.190     djm      1137:        if ((which & OPTIONS_EXTENSIONS) != 0 &&
                   1138:            (certflags_flags & CERTOPT_PORT_FWD) != 0)
1.186     djm      1139:                add_flag_option(c, "permit-port-forwarding");
1.190     djm      1140:        if ((which & OPTIONS_EXTENSIONS) != 0 &&
                   1141:            (certflags_flags & CERTOPT_PTY) != 0)
1.186     djm      1142:                add_flag_option(c, "permit-pty");
1.190     djm      1143:        if ((which & OPTIONS_EXTENSIONS) != 0 &&
                   1144:            (certflags_flags & CERTOPT_USER_RC) != 0)
1.186     djm      1145:                add_flag_option(c, "permit-user-rc");
1.190     djm      1146:        if ((which & OPTIONS_CRITICAL) != 0 &&
                   1147:            certflags_command != NULL)
                   1148:                add_string_option(c, "force-command", certflags_command);
                   1149:        if ((which & OPTIONS_CRITICAL) != 0 &&
                   1150:            certflags_src_addr != NULL)
                   1151:                add_string_option(c, "source-address", certflags_src_addr);
1.179     djm      1152: }
                   1153:
                   1154: static void
                   1155: do_ca_sign(struct passwd *pw, int argc, char **argv)
                   1156: {
                   1157:        int i, fd;
                   1158:        u_int n;
                   1159:        Key *ca, *public;
                   1160:        char *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
                   1161:        FILE *f;
1.186     djm      1162:        int v00 = 0; /* legacy keys */
1.179     djm      1163:
                   1164:        tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
                   1165:        if ((ca = load_identity(tmp)) == NULL)
                   1166:                fatal("Couldn't load CA key \"%s\"", tmp);
                   1167:        xfree(tmp);
                   1168:
1.186     djm      1169:        if (key_type_name != NULL) {
                   1170:                switch (key_type_from_name(key_type_name)) {
                   1171:                case KEY_RSA_CERT_V00:
                   1172:                case KEY_DSA_CERT_V00:
                   1173:                        v00 = 1;
                   1174:                        break;
                   1175:                case KEY_UNSPEC:
                   1176:                        if (strcasecmp(key_type_name, "v00") == 0) {
                   1177:                                v00 = 1;
                   1178:                                break;
                   1179:                        } else if (strcasecmp(key_type_name, "v01") == 0)
                   1180:                                break;
                   1181:                        /* FALLTHROUGH */
                   1182:                default:
                   1183:                        fprintf(stderr, "unknown key type %s\n", key_type_name);
                   1184:                        exit(1);
                   1185:                }
                   1186:        }
                   1187:
1.179     djm      1188:        for (i = 0; i < argc; i++) {
                   1189:                /* Split list of principals */
                   1190:                n = 0;
                   1191:                if (cert_principals != NULL) {
                   1192:                        otmp = tmp = xstrdup(cert_principals);
                   1193:                        plist = NULL;
                   1194:                        for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
                   1195:                                plist = xrealloc(plist, n + 1, sizeof(*plist));
                   1196:                                if (*(plist[n] = xstrdup(cp)) == '\0')
                   1197:                                        fatal("Empty principal name");
                   1198:                        }
                   1199:                        xfree(otmp);
                   1200:                }
                   1201:
                   1202:                tmp = tilde_expand_filename(argv[i], pw->pw_uid);
                   1203:                if ((public = key_load_public(tmp, &comment)) == NULL)
                   1204:                        fatal("%s: unable to open \"%s\"", __func__, tmp);
                   1205:                if (public->type != KEY_RSA && public->type != KEY_DSA)
                   1206:                        fatal("%s: key \"%s\" type %s cannot be certified",
                   1207:                            __func__, tmp, key_type(public));
                   1208:
                   1209:                /* Prepare certificate to sign */
1.186     djm      1210:                if (key_to_certified(public, v00) != 0)
1.179     djm      1211:                        fatal("Could not upgrade key %s to certificate", tmp);
                   1212:                public->cert->type = cert_key_type;
1.186     djm      1213:                public->cert->serial = (u_int64_t)cert_serial;
1.179     djm      1214:                public->cert->key_id = xstrdup(cert_key_id);
                   1215:                public->cert->nprincipals = n;
                   1216:                public->cert->principals = plist;
                   1217:                public->cert->valid_after = cert_valid_from;
                   1218:                public->cert->valid_before = cert_valid_to;
1.190     djm      1219:                if (v00) {
                   1220:                        prepare_options_buf(&public->cert->critical,
                   1221:                            OPTIONS_CRITICAL|OPTIONS_EXTENSIONS);
                   1222:                } else {
                   1223:                        prepare_options_buf(&public->cert->critical,
                   1224:                            OPTIONS_CRITICAL);
                   1225:                        prepare_options_buf(&public->cert->extensions,
                   1226:                            OPTIONS_EXTENSIONS);
                   1227:                }
1.179     djm      1228:                public->cert->signature_key = key_from_private(ca);
                   1229:
                   1230:                if (key_certify(public, ca) != 0)
                   1231:                        fatal("Couldn't not certify key %s", tmp);
                   1232:
                   1233:                if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
                   1234:                        *cp = '\0';
                   1235:                xasprintf(&out, "%s-cert.pub", tmp);
                   1236:                xfree(tmp);
                   1237:
                   1238:                if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
                   1239:                        fatal("Could not open \"%s\" for writing: %s", out,
                   1240:                            strerror(errno));
                   1241:                if ((f = fdopen(fd, "w")) == NULL)
                   1242:                        fatal("%s: fdopen: %s", __func__, strerror(errno));
                   1243:                if (!key_write(public, f))
                   1244:                        fatal("Could not write certified key to %s", out);
                   1245:                fprintf(f, " %s\n", comment);
                   1246:                fclose(f);
                   1247:
1.186     djm      1248:                if (!quiet) {
                   1249:                        logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
                   1250:                            "valid %s", key_cert_type(public),
                   1251:                            out, public->cert->key_id, public->cert->serial,
1.179     djm      1252:                            cert_principals != NULL ? " for " : "",
                   1253:                            cert_principals != NULL ? cert_principals : "",
1.182     djm      1254:                            fmt_validity(cert_valid_from, cert_valid_to));
1.186     djm      1255:                }
1.179     djm      1256:
                   1257:                key_free(public);
                   1258:                xfree(out);
                   1259:        }
                   1260:        exit(0);
                   1261: }
                   1262:
                   1263: static u_int64_t
                   1264: parse_relative_time(const char *s, time_t now)
                   1265: {
                   1266:        int64_t mul, secs;
                   1267:
                   1268:        mul = *s == '-' ? -1 : 1;
                   1269:
                   1270:        if ((secs = convtime(s + 1)) == -1)
                   1271:                fatal("Invalid relative certificate time %s", s);
                   1272:        if (mul == -1 && secs > now)
                   1273:                fatal("Certificate time %s cannot be represented", s);
                   1274:        return now + (u_int64_t)(secs * mul);
                   1275: }
                   1276:
                   1277: static u_int64_t
                   1278: parse_absolute_time(const char *s)
                   1279: {
                   1280:        struct tm tm;
                   1281:        time_t tt;
1.180     djm      1282:        char buf[32], *fmt;
1.179     djm      1283:
1.180     djm      1284:        /*
                   1285:         * POSIX strptime says "The application shall ensure that there
                   1286:         * is white-space or other non-alphanumeric characters between
                   1287:         * any two conversion specifications" so arrange things this way.
                   1288:         */
                   1289:        switch (strlen(s)) {
                   1290:        case 8:
1.184     djm      1291:                fmt = "%Y-%m-%d";
                   1292:                snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6);
1.180     djm      1293:                break;
                   1294:        case 14:
1.184     djm      1295:                fmt = "%Y-%m-%dT%H:%M:%S";
                   1296:                snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s",
1.180     djm      1297:                    s, s + 4, s + 6, s + 8, s + 10, s + 12);
                   1298:                break;
                   1299:        default:
1.179     djm      1300:                fatal("Invalid certificate time format %s", s);
1.180     djm      1301:        }
1.179     djm      1302:
                   1303:        bzero(&tm, sizeof(tm));
1.180     djm      1304:        if (strptime(buf, fmt, &tm) == NULL)
1.179     djm      1305:                fatal("Invalid certificate time %s", s);
                   1306:        if ((tt = mktime(&tm)) < 0)
                   1307:                fatal("Certificate time %s cannot be represented", s);
                   1308:        return (u_int64_t)tt;
                   1309: }
                   1310:
                   1311: static void
                   1312: parse_cert_times(char *timespec)
                   1313: {
                   1314:        char *from, *to;
                   1315:        time_t now = time(NULL);
                   1316:        int64_t secs;
                   1317:
                   1318:        /* +timespec relative to now */
                   1319:        if (*timespec == '+' && strchr(timespec, ':') == NULL) {
                   1320:                if ((secs = convtime(timespec + 1)) == -1)
                   1321:                        fatal("Invalid relative certificate life %s", timespec);
                   1322:                cert_valid_to = now + secs;
                   1323:                /*
                   1324:                 * Backdate certificate one minute to avoid problems on hosts
                   1325:                 * with poorly-synchronised clocks.
                   1326:                 */
                   1327:                cert_valid_from = ((now - 59)/ 60) * 60;
                   1328:                return;
                   1329:        }
                   1330:
                   1331:        /*
                   1332:         * from:to, where
                   1333:         * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
                   1334:         *   to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS
                   1335:         */
                   1336:        from = xstrdup(timespec);
                   1337:        to = strchr(from, ':');
                   1338:        if (to == NULL || from == to || *(to + 1) == '\0')
1.181     djm      1339:                fatal("Invalid certificate life specification %s", timespec);
1.179     djm      1340:        *to++ = '\0';
                   1341:
                   1342:        if (*from == '-' || *from == '+')
                   1343:                cert_valid_from = parse_relative_time(from, now);
                   1344:        else
                   1345:                cert_valid_from = parse_absolute_time(from);
                   1346:
                   1347:        if (*to == '-' || *to == '+')
                   1348:                cert_valid_to = parse_relative_time(to, cert_valid_from);
                   1349:        else
                   1350:                cert_valid_to = parse_absolute_time(to);
                   1351:
                   1352:        if (cert_valid_to <= cert_valid_from)
                   1353:                fatal("Empty certificate validity interval");
                   1354:        xfree(from);
                   1355: }
                   1356:
                   1357: static void
1.186     djm      1358: add_cert_option(char *opt)
1.179     djm      1359: {
                   1360:        char *val;
                   1361:
                   1362:        if (strcmp(opt, "clear") == 0)
1.190     djm      1363:                certflags_flags = 0;
1.179     djm      1364:        else if (strcasecmp(opt, "no-x11-forwarding") == 0)
1.190     djm      1365:                certflags_flags &= ~CERTOPT_X_FWD;
1.179     djm      1366:        else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
1.190     djm      1367:                certflags_flags |= CERTOPT_X_FWD;
1.179     djm      1368:        else if (strcasecmp(opt, "no-agent-forwarding") == 0)
1.190     djm      1369:                certflags_flags &= ~CERTOPT_AGENT_FWD;
1.179     djm      1370:        else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
1.190     djm      1371:                certflags_flags |= CERTOPT_AGENT_FWD;
1.179     djm      1372:        else if (strcasecmp(opt, "no-port-forwarding") == 0)
1.190     djm      1373:                certflags_flags &= ~CERTOPT_PORT_FWD;
1.179     djm      1374:        else if (strcasecmp(opt, "permit-port-forwarding") == 0)
1.190     djm      1375:                certflags_flags |= CERTOPT_PORT_FWD;
1.179     djm      1376:        else if (strcasecmp(opt, "no-pty") == 0)
1.190     djm      1377:                certflags_flags &= ~CERTOPT_PTY;
1.179     djm      1378:        else if (strcasecmp(opt, "permit-pty") == 0)
1.190     djm      1379:                certflags_flags |= CERTOPT_PTY;
1.179     djm      1380:        else if (strcasecmp(opt, "no-user-rc") == 0)
1.190     djm      1381:                certflags_flags &= ~CERTOPT_USER_RC;
1.179     djm      1382:        else if (strcasecmp(opt, "permit-user-rc") == 0)
1.190     djm      1383:                certflags_flags |= CERTOPT_USER_RC;
1.179     djm      1384:        else if (strncasecmp(opt, "force-command=", 14) == 0) {
                   1385:                val = opt + 14;
                   1386:                if (*val == '\0')
1.186     djm      1387:                        fatal("Empty force-command option");
1.190     djm      1388:                if (certflags_command != NULL)
1.179     djm      1389:                        fatal("force-command already specified");
1.190     djm      1390:                certflags_command = xstrdup(val);
1.179     djm      1391:        } else if (strncasecmp(opt, "source-address=", 15) == 0) {
                   1392:                val = opt + 15;
                   1393:                if (*val == '\0')
1.186     djm      1394:                        fatal("Empty source-address option");
1.190     djm      1395:                if (certflags_src_addr != NULL)
1.179     djm      1396:                        fatal("source-address already specified");
                   1397:                if (addr_match_cidr_list(NULL, val) != 0)
                   1398:                        fatal("Invalid source-address list");
1.190     djm      1399:                certflags_src_addr = xstrdup(val);
1.179     djm      1400:        } else
1.186     djm      1401:                fatal("Unsupported certificate option \"%s\"", opt);
1.179     djm      1402: }
                   1403:
1.63      itojun   1404: static void
1.192   ! djm      1405: show_options(const Buffer *optbuf, int v00, int in_critical)
        !          1406: {
        !          1407:        u_char *name, *data;
        !          1408:        u_int dlen;
        !          1409:        Buffer options, option;
        !          1410:
        !          1411:        buffer_init(&options);
        !          1412:        buffer_append(&options, buffer_ptr(optbuf), buffer_len(optbuf));
        !          1413:
        !          1414:        buffer_init(&option);
        !          1415:        while (buffer_len(&options) != 0) {
        !          1416:                name = buffer_get_string(&options, NULL);
        !          1417:                data = buffer_get_string_ptr(&options, &dlen);
        !          1418:                buffer_append(&option, data, dlen);
        !          1419:                printf("                %s", name);
        !          1420:                if ((v00 || !in_critical) &&
        !          1421:                    (strcmp(name, "permit-X11-forwarding") == 0 ||
        !          1422:                    strcmp(name, "permit-agent-forwarding") == 0 ||
        !          1423:                    strcmp(name, "permit-port-forwarding") == 0 ||
        !          1424:                    strcmp(name, "permit-pty") == 0 ||
        !          1425:                    strcmp(name, "permit-user-rc") == 0))
        !          1426:                        printf("\n");
        !          1427:                else if ((v00 || in_critical) &&
        !          1428:                    (strcmp(name, "force-command") == 0 ||
        !          1429:                    strcmp(name, "source-address") == 0)) {
        !          1430:                        data = buffer_get_string(&option, NULL);
        !          1431:                        printf(" %s\n", data);
        !          1432:                        xfree(data);
        !          1433:                } else {
        !          1434:                        printf(" UNKNOWN OPTION (len %u)\n",
        !          1435:                            buffer_len(&option));
        !          1436:                        buffer_clear(&option);
        !          1437:                }
        !          1438:                xfree(name);
        !          1439:                if (buffer_len(&option) != 0)
        !          1440:                        fatal("Option corrupt: extra data at end");
        !          1441:        }
        !          1442:        buffer_free(&option);
        !          1443:        buffer_free(&options);
        !          1444: }
        !          1445:
        !          1446: static void
1.182     djm      1447: do_show_cert(struct passwd *pw)
                   1448: {
                   1449:        Key *key;
                   1450:        struct stat st;
                   1451:        char *key_fp, *ca_fp;
1.192   ! djm      1452:        u_int i, v00;
1.182     djm      1453:
                   1454:        if (!have_identity)
                   1455:                ask_filename(pw, "Enter file in which the key is");
1.191     djm      1456:        if (stat(identity_file, &st) < 0)
                   1457:                fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
1.182     djm      1458:        if ((key = key_load_public(identity_file, NULL)) == NULL)
                   1459:                fatal("%s is not a public key", identity_file);
                   1460:        if (!key_is_cert(key))
                   1461:                fatal("%s is not a certificate", identity_file);
1.186     djm      1462:        v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
                   1463:
1.182     djm      1464:        key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
                   1465:        ca_fp = key_fingerprint(key->cert->signature_key,
                   1466:            SSH_FP_MD5, SSH_FP_HEX);
                   1467:
                   1468:        printf("%s:\n", identity_file);
1.186     djm      1469:        printf("        Type: %s %s certificate\n", key_ssh_name(key),
                   1470:            key_cert_type(key));
                   1471:        printf("        Public key: %s %s\n", key_type(key), key_fp);
                   1472:        printf("        Signing CA: %s %s\n",
1.182     djm      1473:            key_type(key->cert->signature_key), ca_fp);
1.186     djm      1474:        printf("        Key ID: \"%s\"\n", key->cert->key_id);
                   1475:        if (!v00)
                   1476:                printf("        Serial: %llu\n", key->cert->serial);
1.182     djm      1477:        printf("        Valid: %s\n",
                   1478:            fmt_validity(key->cert->valid_after, key->cert->valid_before));
                   1479:        printf("        Principals: ");
                   1480:        if (key->cert->nprincipals == 0)
                   1481:                printf("(none)\n");
                   1482:        else {
                   1483:                for (i = 0; i < key->cert->nprincipals; i++)
                   1484:                        printf("\n                %s",
                   1485:                            key->cert->principals[i]);
                   1486:                printf("\n");
                   1487:        }
1.186     djm      1488:        printf("        Critical Options: ");
                   1489:        if (buffer_len(&key->cert->critical) == 0)
1.182     djm      1490:                printf("(none)\n");
                   1491:        else {
                   1492:                printf("\n");
1.192   ! djm      1493:                show_options(&key->cert->critical, v00, 1);
1.186     djm      1494:        }
                   1495:        if (!v00) {
                   1496:                printf("        Extensions: ");
                   1497:                if (buffer_len(&key->cert->extensions) == 0)
                   1498:                        printf("(none)\n");
                   1499:                else {
                   1500:                        printf("\n");
1.192   ! djm      1501:                        show_options(&key->cert->extensions, v00, 0);
1.182     djm      1502:                }
                   1503:        }
                   1504:        exit(0);
                   1505: }
                   1506:
                   1507: static void
1.10      markus   1508: usage(void)
                   1509: {
1.161     sobrado  1510:        fprintf(stderr, "usage: %s [options]\n", __progname);
1.77      jakob    1511:        fprintf(stderr, "Options:\n");
1.123     otto     1512:        fprintf(stderr, "  -a trials   Number of trials for screening DH-GEX moduli.\n");
                   1513:        fprintf(stderr, "  -B          Show bubblebabble digest of key file.\n");
1.77      jakob    1514:        fprintf(stderr, "  -b bits     Number of bits in the key to create.\n");
1.123     otto     1515:        fprintf(stderr, "  -C comment  Provide new comment.\n");
1.77      jakob    1516:        fprintf(stderr, "  -c          Change comment in private and public key files.\n");
1.177     markus   1517: #ifdef ENABLE_PKCS11
                   1518:        fprintf(stderr, "  -D pkcs11   Download public key from pkcs11 token.\n");
                   1519: #endif
1.159     jmc      1520:        fprintf(stderr, "  -e          Convert OpenSSH to RFC 4716 key file.\n");
1.123     otto     1521:        fprintf(stderr, "  -F hostname Find hostname in known hosts file.\n");
1.77      jakob    1522:        fprintf(stderr, "  -f filename Filename of the key file.\n");
1.123     otto     1523:        fprintf(stderr, "  -G file     Generate candidates for DH-GEX moduli.\n");
1.105     jakob    1524:        fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
1.123     otto     1525:        fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
1.179     djm      1526:        fprintf(stderr, "  -h          Generate host certificate instead of a user certificate.\n");
                   1527:        fprintf(stderr, "  -I key_id   Key identifier to include in certificate.\n");
1.159     jmc      1528:        fprintf(stderr, "  -i          Convert RFC 4716 to OpenSSH key file.\n");
1.182     djm      1529:        fprintf(stderr, "  -L          Print the contents of a certificate.\n");
1.77      jakob    1530:        fprintf(stderr, "  -l          Show fingerprint of key file.\n");
1.123     otto     1531:        fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1.179     djm      1532:        fprintf(stderr, "  -n name,... User/host principal names to include in certificate\n");
1.123     otto     1533:        fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
1.187     jmc      1534:        fprintf(stderr, "  -O option   Specify a certificate option.\n");
1.123     otto     1535:        fprintf(stderr, "  -P phrase   Provide old passphrase.\n");
1.77      jakob    1536:        fprintf(stderr, "  -p          Change passphrase of private key file.\n");
                   1537:        fprintf(stderr, "  -q          Quiet.\n");
1.123     otto     1538:        fprintf(stderr, "  -R hostname Remove host from known_hosts file.\n");
                   1539:        fprintf(stderr, "  -r hostname Print DNS resource record.\n");
1.179     djm      1540:        fprintf(stderr, "  -s ca_key   Certify keys with CA key.\n");
1.123     otto     1541:        fprintf(stderr, "  -S start    Start point (hex) for generating DH-GEX moduli.\n");
                   1542:        fprintf(stderr, "  -T file     Screen candidates for DH-GEX moduli.\n");
1.77      jakob    1543:        fprintf(stderr, "  -t type     Specify type of key to create.\n");
1.179     djm      1544:        fprintf(stderr, "  -V from:to  Specify certificate validity interval.\n");
1.123     otto     1545:        fprintf(stderr, "  -v          Verbose.\n");
                   1546:        fprintf(stderr, "  -W gen      Generator to use for generating DH-GEX moduli.\n");
                   1547:        fprintf(stderr, "  -y          Read private key file and print public key.\n");
1.187     jmc      1548:        fprintf(stderr, "  -z serial   Specify a serial number.\n");
1.107     djm      1549:
1.12      markus   1550:        exit(1);
1.10      markus   1551: }
                   1552:
1.13      deraadt  1553: /*
                   1554:  * Main program for key management.
                   1555:  */
1.2       provos   1556: int
1.156     deraadt  1557: main(int argc, char **argv)
1.1       deraadt  1558: {
1.87      djm      1559:        char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1.177     markus   1560:        char out_file[MAXPATHLEN], *pkcs11provider = NULL;
1.119     djm      1561:        char *rr_hostname = NULL;
1.46      deraadt  1562:        Key *private, *public;
1.12      markus   1563:        struct passwd *pw;
                   1564:        struct stat st;
1.177     markus   1565:        int opt, type, fd;
1.189     djm      1566:        u_int maxbits;
1.126     dtucker  1567:        u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1.107     djm      1568:        int do_gen_candidates = 0, do_screen_candidates = 0;
                   1569:        BIGNUM *start = NULL;
1.12      markus   1570:        FILE *f;
1.125     avsm     1571:        const char *errstr;
1.33      markus   1572:
1.12      markus   1573:        extern int optind;
                   1574:        extern char *optarg;
1.129     djm      1575:
                   1576:        /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
                   1577:        sanitise_stdfd();
1.12      markus   1578:
1.26      markus   1579:        SSLeay_add_all_algorithms();
1.156     deraadt  1580:        log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
1.19      markus   1581:
1.14      markus   1582:        /* we need this for the home * directory.  */
1.12      markus   1583:        pw = getpwuid(getuid());
                   1584:        if (!pw) {
                   1585:                printf("You don't exist, go away!\n");
                   1586:                exit(1);
                   1587:        }
1.19      markus   1588:        if (gethostname(hostname, sizeof(hostname)) < 0) {
                   1589:                perror("gethostname");
                   1590:                exit(1);
                   1591:        }
1.14      markus   1592:
1.182     djm      1593:        while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:"
1.186     djm      1594:            "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
1.12      markus   1595:                switch (opt) {
                   1596:                case 'b':
1.142     deraadt  1597:                        bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1.125     avsm     1598:                        if (errstr)
                   1599:                                fatal("Bits has bad value %s (%s)",
                   1600:                                        optarg, errstr);
1.12      markus   1601:                        break;
1.119     djm      1602:                case 'F':
                   1603:                        find_host = 1;
                   1604:                        rr_hostname = optarg;
                   1605:                        break;
                   1606:                case 'H':
                   1607:                        hash_hosts = 1;
                   1608:                        break;
1.179     djm      1609:                case 'I':
                   1610:                        cert_key_id = optarg;
                   1611:                        break;
1.119     djm      1612:                case 'R':
                   1613:                        delete_host = 1;
                   1614:                        rr_hostname = optarg;
                   1615:                        break;
1.182     djm      1616:                case 'L':
                   1617:                        show_cert = 1;
                   1618:                        break;
1.12      markus   1619:                case 'l':
                   1620:                        print_fingerprint = 1;
                   1621:                        break;
1.49      markus   1622:                case 'B':
                   1623:                        print_bubblebabble = 1;
                   1624:                        break;
1.179     djm      1625:                case 'n':
                   1626:                        cert_principals = optarg;
                   1627:                        break;
1.12      markus   1628:                case 'p':
                   1629:                        change_passphrase = 1;
                   1630:                        break;
                   1631:                case 'c':
                   1632:                        change_comment = 1;
                   1633:                        break;
                   1634:                case 'f':
1.124     avsm     1635:                        if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
                   1636:                            sizeof(identity_file))
                   1637:                                fatal("Identity filename too long");
1.12      markus   1638:                        have_identity = 1;
                   1639:                        break;
1.105     jakob    1640:                case 'g':
                   1641:                        print_generic = 1;
                   1642:                        break;
1.12      markus   1643:                case 'P':
                   1644:                        identity_passphrase = optarg;
                   1645:                        break;
                   1646:                case 'N':
                   1647:                        identity_new_passphrase = optarg;
                   1648:                        break;
1.179     djm      1649:                case 'O':
1.186     djm      1650:                        add_cert_option(optarg);
1.179     djm      1651:                        break;
1.12      markus   1652:                case 'C':
                   1653:                        identity_comment = optarg;
                   1654:                        break;
                   1655:                case 'q':
                   1656:                        quiet = 1;
1.20      deraadt  1657:                        break;
1.57      markus   1658:                case 'e':
1.19      markus   1659:                case 'x':
1.57      markus   1660:                        /* export key */
1.19      markus   1661:                        convert_to_ssh2 = 1;
                   1662:                        break;
1.179     djm      1663:                case 'h':
                   1664:                        cert_key_type = SSH2_CERT_TYPE_HOST;
1.190     djm      1665:                        certflags_flags = 0;
1.179     djm      1666:                        break;
1.57      markus   1667:                case 'i':
1.19      markus   1668:                case 'X':
1.57      markus   1669:                        /* import key */
1.19      markus   1670:                        convert_from_ssh2 = 1;
                   1671:                        break;
                   1672:                case 'y':
                   1673:                        print_public = 1;
1.47      jakob    1674:                        break;
1.19      markus   1675:                case 'd':
1.33      markus   1676:                        key_type_name = "dsa";
1.19      markus   1677:                        break;
1.179     djm      1678:                case 's':
                   1679:                        ca_key_path = optarg;
                   1680:                        break;
1.33      markus   1681:                case 't':
                   1682:                        key_type_name = optarg;
                   1683:                        break;
1.75      markus   1684:                case 'D':
1.177     markus   1685:                        pkcs11provider = optarg;
1.66      markus   1686:                        break;
1.113     djm      1687:                case 'v':
                   1688:                        if (log_level == SYSLOG_LEVEL_INFO)
                   1689:                                log_level = SYSLOG_LEVEL_DEBUG1;
                   1690:                        else {
1.117     deraadt  1691:                                if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
1.113     djm      1692:                                    log_level < SYSLOG_LEVEL_DEBUG3)
                   1693:                                        log_level++;
                   1694:                        }
                   1695:                        break;
1.105     jakob    1696:                case 'r':
1.119     djm      1697:                        rr_hostname = optarg;
1.105     jakob    1698:                        break;
1.107     djm      1699:                case 'W':
1.142     deraadt  1700:                        generator_wanted = (u_int32_t)strtonum(optarg, 1,
                   1701:                            UINT_MAX, &errstr);
1.124     avsm     1702:                        if (errstr)
                   1703:                                fatal("Desired generator has bad value: %s (%s)",
                   1704:                                        optarg, errstr);
1.107     djm      1705:                        break;
                   1706:                case 'a':
1.142     deraadt  1707:                        trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1.124     avsm     1708:                        if (errstr)
                   1709:                                fatal("Invalid number of trials: %s (%s)",
                   1710:                                        optarg, errstr);
1.107     djm      1711:                        break;
                   1712:                case 'M':
1.142     deraadt  1713:                        memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1.186     djm      1714:                        if (errstr)
1.124     avsm     1715:                                fatal("Memory limit is %s: %s", errstr, optarg);
1.107     djm      1716:                        break;
                   1717:                case 'G':
                   1718:                        do_gen_candidates = 1;
1.124     avsm     1719:                        if (strlcpy(out_file, optarg, sizeof(out_file)) >=
                   1720:                            sizeof(out_file))
                   1721:                                fatal("Output filename too long");
1.107     djm      1722:                        break;
                   1723:                case 'T':
                   1724:                        do_screen_candidates = 1;
1.124     avsm     1725:                        if (strlcpy(out_file, optarg, sizeof(out_file)) >=
                   1726:                            sizeof(out_file))
                   1727:                                fatal("Output filename too long");
1.107     djm      1728:                        break;
                   1729:                case 'S':
                   1730:                        /* XXX - also compare length against bits */
                   1731:                        if (BN_hex2bn(&start, optarg) == 0)
                   1732:                                fatal("Invalid start point.");
                   1733:                        break;
1.179     djm      1734:                case 'V':
                   1735:                        parse_cert_times(optarg);
1.186     djm      1736:                        break;
                   1737:                case 'z':
                   1738:                        cert_serial = strtonum(optarg, 0, LLONG_MAX, &errstr);
                   1739:                        if (errstr)
                   1740:                                fatal("Invalid serial number: %s", errstr);
1.179     djm      1741:                        break;
1.12      markus   1742:                case '?':
                   1743:                default:
                   1744:                        usage();
                   1745:                }
                   1746:        }
1.113     djm      1747:
                   1748:        /* reinit */
1.156     deraadt  1749:        log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
1.113     djm      1750:
1.179     djm      1751:        argv += optind;
                   1752:        argc -= optind;
                   1753:
                   1754:        if (ca_key_path != NULL) {
                   1755:                if (argc < 1) {
                   1756:                        printf("Too few arguments.\n");
                   1757:                        usage();
                   1758:                }
                   1759:        } else if (argc > 0) {
1.12      markus   1760:                printf("Too many arguments.\n");
1.87      djm      1761:                usage();
                   1762:        }
1.12      markus   1763:        if (change_passphrase && change_comment) {
                   1764:                printf("Can only have one of -p and -c.\n");
1.166     djm      1765:                usage();
                   1766:        }
                   1767:        if (print_fingerprint && (delete_host || hash_hosts)) {
                   1768:                printf("Cannot use -l with -D or -R.\n");
1.12      markus   1769:                usage();
1.179     djm      1770:        }
                   1771:        if (ca_key_path != NULL) {
                   1772:                if (cert_key_id == NULL)
                   1773:                        fatal("Must specify key id (-I) when certifying");
                   1774:                do_ca_sign(pw, argc, argv);
1.12      markus   1775:        }
1.182     djm      1776:        if (show_cert)
                   1777:                do_show_cert(pw);
1.119     djm      1778:        if (delete_host || hash_hosts || find_host)
                   1779:                do_known_hosts(pw, rr_hostname);
1.49      markus   1780:        if (print_fingerprint || print_bubblebabble)
1.12      markus   1781:                do_fingerprint(pw);
                   1782:        if (change_passphrase)
                   1783:                do_change_passphrase(pw);
                   1784:        if (change_comment)
                   1785:                do_change_comment(pw);
1.19      markus   1786:        if (convert_to_ssh2)
                   1787:                do_convert_to_ssh2(pw);
                   1788:        if (convert_from_ssh2)
                   1789:                do_convert_from_ssh2(pw);
                   1790:        if (print_public)
                   1791:                do_print_public(pw);
1.119     djm      1792:        if (rr_hostname != NULL) {
1.138     jakob    1793:                unsigned int n = 0;
                   1794:
                   1795:                if (have_identity) {
                   1796:                        n = do_print_resource_record(pw,
                   1797:                            identity_file, rr_hostname);
                   1798:                        if (n == 0) {
                   1799:                                perror(identity_file);
                   1800:                                exit(1);
                   1801:                        }
                   1802:                        exit(0);
                   1803:                } else {
                   1804:
                   1805:                        n += do_print_resource_record(pw,
                   1806:                            _PATH_HOST_RSA_KEY_FILE, rr_hostname);
                   1807:                        n += do_print_resource_record(pw,
                   1808:                            _PATH_HOST_DSA_KEY_FILE, rr_hostname);
                   1809:
                   1810:                        if (n == 0)
                   1811:                                fatal("no keys found.");
                   1812:                        exit(0);
                   1813:                }
1.105     jakob    1814:        }
1.177     markus   1815:        if (pkcs11provider != NULL)
                   1816:                do_download(pw, pkcs11provider);
1.107     djm      1817:
                   1818:        if (do_gen_candidates) {
                   1819:                FILE *out = fopen(out_file, "w");
1.111     djm      1820:
1.107     djm      1821:                if (out == NULL) {
                   1822:                        error("Couldn't open modulus candidate file \"%s\": %s",
                   1823:                            out_file, strerror(errno));
                   1824:                        return (1);
                   1825:                }
1.130     markus   1826:                if (bits == 0)
                   1827:                        bits = DEFAULT_BITS;
1.107     djm      1828:                if (gen_candidates(out, memory, bits, start) != 0)
1.131     stevesk  1829:                        fatal("modulus candidate generation failed");
1.107     djm      1830:
                   1831:                return (0);
                   1832:        }
                   1833:
                   1834:        if (do_screen_candidates) {
                   1835:                FILE *in;
                   1836:                FILE *out = fopen(out_file, "w");
                   1837:
                   1838:                if (have_identity && strcmp(identity_file, "-") != 0) {
                   1839:                        if ((in = fopen(identity_file, "r")) == NULL) {
                   1840:                                fatal("Couldn't open modulus candidate "
1.111     djm      1841:                                    "file \"%s\": %s", identity_file,
1.107     djm      1842:                                    strerror(errno));
                   1843:                        }
                   1844:                } else
                   1845:                        in = stdin;
                   1846:
                   1847:                if (out == NULL) {
                   1848:                        fatal("Couldn't open moduli file \"%s\": %s",
                   1849:                            out_file, strerror(errno));
                   1850:                }
                   1851:                if (prime_test(in, out, trials, generator_wanted) != 0)
1.131     stevesk  1852:                        fatal("modulus screening failed");
1.108     markus   1853:                return (0);
1.75      markus   1854:        }
1.12      markus   1855:
                   1856:        arc4random_stir();
                   1857:
1.133     djm      1858:        if (key_type_name == NULL)
                   1859:                key_type_name = "rsa";
                   1860:
1.35      markus   1861:        type = key_type_from_name(key_type_name);
                   1862:        if (type == KEY_UNSPEC) {
                   1863:                fprintf(stderr, "unknown key type %s\n", key_type_name);
                   1864:                exit(1);
1.19      markus   1865:        }
1.135     dtucker  1866:        if (bits == 0)
                   1867:                bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS;
1.189     djm      1868:        maxbits = (type == KEY_DSA) ?
                   1869:            OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
                   1870:        if (bits > maxbits) {
                   1871:                fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
                   1872:                exit(1);
                   1873:        }
1.134     dtucker  1874:        if (type == KEY_DSA && bits != 1024)
                   1875:                fatal("DSA keys must be 1024 bits");
1.33      markus   1876:        if (!quiet)
1.35      markus   1877:                printf("Generating public/private %s key pair.\n", key_type_name);
1.33      markus   1878:        private = key_generate(type, bits);
                   1879:        if (private == NULL) {
1.173     tobias   1880:                fprintf(stderr, "key_generate failed\n");
1.33      markus   1881:                exit(1);
                   1882:        }
                   1883:        public  = key_from_private(private);
1.12      markus   1884:
                   1885:        if (!have_identity)
                   1886:                ask_filename(pw, "Enter file in which to save the key");
                   1887:
1.132     djm      1888:        /* Create ~/.ssh directory if it doesn't already exist. */
1.188     djm      1889:        snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
                   1890:            pw->pw_dir, _PATH_SSH_USER_DIR);
                   1891:        if (strstr(identity_file, dotsshdir) != NULL) {
                   1892:                if (stat(dotsshdir, &st) < 0) {
                   1893:                        if (errno != ENOENT) {
                   1894:                                error("Could not stat %s: %s", dotsshdir,
                   1895:                                    strerror(errno));
                   1896:                        } else if (mkdir(dotsshdir, 0700) < 0) {
                   1897:                                error("Could not create directory '%s': %s",
                   1898:                                    dotsshdir, strerror(errno));
                   1899:                        } else if (!quiet)
                   1900:                                printf("Created directory '%s'.\n", dotsshdir);
                   1901:                }
1.12      markus   1902:        }
                   1903:        /* If the file already exists, ask the user to confirm. */
                   1904:        if (stat(identity_file, &st) >= 0) {
                   1905:                char yesno[3];
                   1906:                printf("%s already exists.\n", identity_file);
                   1907:                printf("Overwrite (y/n)? ");
                   1908:                fflush(stdout);
                   1909:                if (fgets(yesno, sizeof(yesno), stdin) == NULL)
                   1910:                        exit(1);
                   1911:                if (yesno[0] != 'y' && yesno[0] != 'Y')
                   1912:                        exit(1);
                   1913:        }
                   1914:        /* Ask for a passphrase (twice). */
                   1915:        if (identity_passphrase)
                   1916:                passphrase1 = xstrdup(identity_passphrase);
                   1917:        else if (identity_new_passphrase)
                   1918:                passphrase1 = xstrdup(identity_new_passphrase);
                   1919:        else {
                   1920: passphrase_again:
                   1921:                passphrase1 =
1.65      markus   1922:                        read_passphrase("Enter passphrase (empty for no "
                   1923:                            "passphrase): ", RP_ALLOW_STDIN);
                   1924:                passphrase2 = read_passphrase("Enter same passphrase again: ",
                   1925:                    RP_ALLOW_STDIN);
1.12      markus   1926:                if (strcmp(passphrase1, passphrase2) != 0) {
1.65      markus   1927:                        /*
                   1928:                         * The passphrases do not match.  Clear them and
                   1929:                         * retry.
                   1930:                         */
1.12      markus   1931:                        memset(passphrase1, 0, strlen(passphrase1));
                   1932:                        memset(passphrase2, 0, strlen(passphrase2));
                   1933:                        xfree(passphrase1);
                   1934:                        xfree(passphrase2);
                   1935:                        printf("Passphrases do not match.  Try again.\n");
                   1936:                        goto passphrase_again;
                   1937:                }
                   1938:                /* Clear the other copy of the passphrase. */
                   1939:                memset(passphrase2, 0, strlen(passphrase2));
                   1940:                xfree(passphrase2);
                   1941:        }
                   1942:
                   1943:        if (identity_comment) {
                   1944:                strlcpy(comment, identity_comment, sizeof(comment));
                   1945:        } else {
1.172     stevesk  1946:                /* Create default comment field for the passphrase. */
1.12      markus   1947:                snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
                   1948:        }
                   1949:
                   1950:        /* Save the key with the given passphrase and comment. */
1.52      markus   1951:        if (!key_save_private(private, identity_file, passphrase1, comment)) {
1.56      markus   1952:                printf("Saving the key failed: %s.\n", identity_file);
1.12      markus   1953:                memset(passphrase1, 0, strlen(passphrase1));
                   1954:                xfree(passphrase1);
                   1955:                exit(1);
                   1956:        }
                   1957:        /* Clear the passphrase. */
                   1958:        memset(passphrase1, 0, strlen(passphrase1));
                   1959:        xfree(passphrase1);
                   1960:
                   1961:        /* Clear the private key and the random number generator. */
1.33      markus   1962:        key_free(private);
1.12      markus   1963:        arc4random_stir();
                   1964:
                   1965:        if (!quiet)
                   1966:                printf("Your identification has been saved in %s.\n", identity_file);
                   1967:
                   1968:        strlcat(identity_file, ".pub", sizeof(identity_file));
1.46      deraadt  1969:        fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
                   1970:        if (fd == -1) {
1.12      markus   1971:                printf("Could not save your public key in %s\n", identity_file);
1.46      deraadt  1972:                exit(1);
                   1973:        }
                   1974:        f = fdopen(fd, "w");
                   1975:        if (f == NULL) {
1.173     tobias   1976:                printf("fdopen %s failed\n", identity_file);
1.12      markus   1977:                exit(1);
                   1978:        }
1.19      markus   1979:        if (!key_write(public, f))
1.173     tobias   1980:                fprintf(stderr, "write key failed\n");
1.19      markus   1981:        fprintf(f, " %s\n", comment);
1.12      markus   1982:        fclose(f);
                   1983:
                   1984:        if (!quiet) {
1.50      markus   1985:                char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1.167     grunk    1986:                char *ra = key_fingerprint(public, SSH_FP_MD5,
                   1987:                    SSH_FP_RANDOMART);
1.19      markus   1988:                printf("Your public key has been saved in %s.\n",
                   1989:                    identity_file);
1.12      markus   1990:                printf("The key fingerprint is:\n");
1.50      markus   1991:                printf("%s %s\n", fp, comment);
1.167     grunk    1992:                printf("The key's randomart image is:\n");
                   1993:                printf("%s\n", ra);
                   1994:                xfree(ra);
1.50      markus   1995:                xfree(fp);
1.12      markus   1996:        }
1.19      markus   1997:
                   1998:        key_free(public);
1.12      markus   1999:        exit(0);
1.1       deraadt  2000: }