[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.187

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