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

1.1       deraadt     1: /*
1.13      deraadt     2:  * Author: Tatu Ylonen <ylo@cs.hut.fi>
                      3:  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
                      4:  *                    All rights reserved
                      5:  * Identity and host key generation and maintenance.
1.31      deraadt     6:  *
                      7:  * As far as I am concerned, the code I have written for this software
                      8:  * can be used freely for any purpose.  Any derived versions of this
                      9:  * software must be clearly marked as such, and if the derived work is
                     10:  * incompatible with the protocol description in the RFC file, it must be
                     11:  * called by a name other than "ssh" or "Secure Shell".
1.13      deraadt    12:  */
1.1       deraadt    13:
                     14: #include "includes.h"
1.46    ! deraadt    15: RCSID("$OpenBSD: ssh-keygen.c,v 1.45 2001/02/22 08:03:51 deraadt Exp $");
1.19      markus     16:
                     17: #include <openssl/evp.h>
                     18: #include <openssl/pem.h>
1.1       deraadt    19:
                     20: #include "xmalloc.h"
1.19      markus     21: #include "key.h"
                     22: #include "authfile.h"
                     23: #include "uuencode.h"
1.32      markus     24: #include "buffer.h"
                     25: #include "bufaux.h"
1.40      markus     26: #include "pathnames.h"
1.41      markus     27: #include "log.h"
                     28: #include "readpass.h"
1.32      markus     29:
1.19      markus     30: /* Number of bits in the RSA/DSA key.  This value can be changed on the command line. */
1.1       deraadt    31: int bits = 1024;
                     32:
1.14      markus     33: /*
                     34:  * Flag indicating that we just want to change the passphrase.  This can be
                     35:  * set on the command line.
                     36:  */
1.1       deraadt    37: int change_passphrase = 0;
                     38:
1.14      markus     39: /*
                     40:  * Flag indicating that we just want to change the comment.  This can be set
                     41:  * on the command line.
                     42:  */
1.1       deraadt    43: int change_comment = 0;
                     44:
1.2       provos     45: int quiet = 0;
                     46:
1.8       markus     47: /* Flag indicating that we just want to see the key fingerprint */
                     48: int print_fingerprint = 0;
                     49:
1.10      markus     50: /* The identity file name, given on the command line or entered by the user. */
                     51: char identity_file[1024];
                     52: int have_identity = 0;
1.1       deraadt    53:
                     54: /* This is set to the passphrase if given on the command line. */
                     55: char *identity_passphrase = NULL;
                     56:
                     57: /* This is set to the new passphrase if given on the command line. */
                     58: char *identity_new_passphrase = NULL;
                     59:
                     60: /* This is set to the new comment if given on the command line. */
                     61: char *identity_comment = NULL;
                     62:
1.19      markus     63: /* Dump public key file in format used by real and the original SSH 2 */
                     64: int convert_to_ssh2 = 0;
                     65: int convert_from_ssh2 = 0;
                     66: int print_public = 0;
1.33      markus     67:
1.35      markus     68: /* default to RSA for SSH-1 */
                     69: char *key_type_name = "rsa1";
1.19      markus     70:
1.10      markus     71: /* argv0 */
                     72: extern char *__progname;
1.1       deraadt    73:
1.19      markus     74: char hostname[MAXHOSTNAMELEN];
                     75:
1.10      markus     76: void
                     77: ask_filename(struct passwd *pw, const char *prompt)
1.1       deraadt    78: {
1.12      markus     79:        char buf[1024];
1.35      markus     80:        char *name = NULL;
                     81:
                     82:        switch (key_type_from_name(key_type_name)) {
                     83:        case KEY_RSA1:
1.40      markus     84:                name = _PATH_SSH_CLIENT_IDENTITY;
1.35      markus     85:                break;
                     86:        case KEY_DSA:
1.40      markus     87:                name = _PATH_SSH_CLIENT_ID_DSA;
1.35      markus     88:                break;
                     89:        case KEY_RSA:
1.40      markus     90:                name = _PATH_SSH_CLIENT_ID_RSA;
1.35      markus     91:                break;
                     92:        default:
                     93:                fprintf(stderr, "bad key type");
                     94:                exit(1);
                     95:                break;
                     96:        }
                     97:        snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
1.37      markus     98:        fprintf(stderr, "%s (%s): ", prompt, identity_file);
                     99:        fflush(stderr);
1.12      markus    100:        if (fgets(buf, sizeof(buf), stdin) == NULL)
                    101:                exit(1);
                    102:        if (strchr(buf, '\n'))
                    103:                *strchr(buf, '\n') = 0;
                    104:        if (strcmp(buf, "") != 0)
                    105:                strlcpy(identity_file, buf, sizeof(identity_file));
                    106:        have_identity = 1;
1.7       markus    107: }
                    108:
1.19      markus    109: int
                    110: try_load_key(char *filename, Key *k)
                    111: {
                    112:        int success = 1;
                    113:        if (!load_private_key(filename, "", k, NULL)) {
                    114:                char *pass = read_passphrase("Enter passphrase: ", 1);
                    115:                if (!load_private_key(filename, pass, k, NULL)) {
                    116:                        success = 0;
                    117:                }
                    118:                memset(pass, 0, strlen(pass));
                    119:                xfree(pass);
                    120:        }
                    121:        return success;
                    122: }
                    123:
1.32      markus    124: #define SSH_COM_PUBLIC_BEGIN           "---- BEGIN SSH2 PUBLIC KEY ----"
                    125: #define SSH_COM_PUBLIC_END             "---- END SSH2 PUBLIC KEY ----"
                    126: #define SSH_COM_PRIVATE_BEGIN          "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
1.42      stevesk   127: #define        SSH_COM_PRIVATE_KEY_MAGIC       0x3f6ff9eb
1.19      markus    128:
                    129: void
                    130: do_convert_to_ssh2(struct passwd *pw)
                    131: {
                    132:        Key *k;
                    133:        int len;
1.36      markus    134:        u_char *blob;
1.19      markus    135:        struct stat st;
                    136:
                    137:        if (!have_identity)
                    138:                ask_filename(pw, "Enter file in which the key is");
                    139:        if (stat(identity_file, &st) < 0) {
                    140:                perror(identity_file);
                    141:                exit(1);
                    142:        }
1.33      markus    143:        k = key_new(KEY_UNSPEC);
1.19      markus    144:        if (!try_load_key(identity_file, k)) {
                    145:                fprintf(stderr, "load failed\n");
                    146:                exit(1);
                    147:        }
1.33      markus    148:        key_to_blob(k, &blob, &len);
1.32      markus    149:        fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
1.19      markus    150:        fprintf(stdout,
1.32      markus    151:            "Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
                    152:            key_size(k), key_type(k),
1.19      markus    153:            pw->pw_name, hostname);
                    154:        dump_base64(stdout, blob, len);
1.32      markus    155:        fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
1.19      markus    156:        key_free(k);
1.21      markus    157:        xfree(blob);
1.19      markus    158:        exit(0);
                    159: }
                    160:
                    161: void
1.32      markus    162: buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
                    163: {
                    164:        int bits = buffer_get_int(b);
                    165:        int bytes = (bits + 7) / 8;
                    166:        if (buffer_len(b) < bytes)
                    167:                fatal("buffer_get_bignum_bits: input buffer too small");
1.36      markus    168:        BN_bin2bn((u_char *)buffer_ptr(b), bytes, value);
1.32      markus    169:        buffer_consume(b, bytes);
                    170: }
                    171:
                    172: Key *
                    173: do_convert_private_ssh2_from_blob(char *blob, int blen)
                    174: {
                    175:        Buffer b;
                    176:        DSA *dsa;
                    177:        Key *key = NULL;
                    178:        int ignore, magic, rlen;
                    179:        char *type, *cipher;
                    180:
                    181:        buffer_init(&b);
                    182:        buffer_append(&b, blob, blen);
                    183:
                    184:        magic  = buffer_get_int(&b);
                    185:        if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
                    186:                error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
                    187:                buffer_free(&b);
                    188:                return NULL;
                    189:        }
                    190:        ignore = buffer_get_int(&b);
                    191:        type   = buffer_get_string(&b, NULL);
                    192:        cipher = buffer_get_string(&b, NULL);
                    193:        ignore = buffer_get_int(&b);
                    194:        ignore = buffer_get_int(&b);
                    195:        ignore = buffer_get_int(&b);
                    196:        xfree(type);
                    197:
                    198:        if (strcmp(cipher, "none") != 0) {
                    199:                error("unsupported cipher %s", cipher);
                    200:                xfree(cipher);
                    201:                buffer_free(&b);
                    202:                return NULL;
                    203:        }
                    204:        xfree(cipher);
                    205:
                    206:        key = key_new(KEY_DSA);
                    207:        dsa = key->dsa;
                    208:        dsa->priv_key = BN_new();
                    209:        if (dsa->priv_key == NULL) {
                    210:                error("alloc priv_key failed");
                    211:                key_free(key);
                    212:                return NULL;
                    213:        }
                    214:        buffer_get_bignum_bits(&b, dsa->p);
                    215:        buffer_get_bignum_bits(&b, dsa->g);
                    216:        buffer_get_bignum_bits(&b, dsa->q);
                    217:        buffer_get_bignum_bits(&b, dsa->pub_key);
                    218:        buffer_get_bignum_bits(&b, dsa->priv_key);
                    219:        rlen = buffer_len(&b);
                    220:        if(rlen != 0)
                    221:                error("do_convert_private_ssh2_from_blob: remaining bytes in key blob %d", rlen);
                    222:        buffer_free(&b);
                    223:        return key;
                    224: }
                    225:
                    226: void
1.19      markus    227: do_convert_from_ssh2(struct passwd *pw)
                    228: {
                    229:        Key *k;
                    230:        int blen;
                    231:        char line[1024], *p;
                    232:        char blob[8096];
                    233:        char encoded[8096];
                    234:        struct stat st;
1.32      markus    235:        int escaped = 0, private = 0, ok;
1.19      markus    236:        FILE *fp;
                    237:
                    238:        if (!have_identity)
                    239:                ask_filename(pw, "Enter file in which the key is");
                    240:        if (stat(identity_file, &st) < 0) {
                    241:                perror(identity_file);
                    242:                exit(1);
                    243:        }
                    244:        fp = fopen(identity_file, "r");
                    245:        if (fp == NULL) {
                    246:                perror(identity_file);
                    247:                exit(1);
                    248:        }
                    249:        encoded[0] = '\0';
                    250:        while (fgets(line, sizeof(line), fp)) {
1.25      markus    251:                if (!(p = strchr(line, '\n'))) {
                    252:                        fprintf(stderr, "input line too long.\n");
                    253:                        exit(1);
                    254:                }
                    255:                if (p > line && p[-1] == '\\')
                    256:                        escaped++;
1.19      markus    257:                if (strncmp(line, "----", 4) == 0 ||
                    258:                    strstr(line, ": ") != NULL) {
1.32      markus    259:                        if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
                    260:                                private = 1;
1.19      markus    261:                        fprintf(stderr, "ignore: %s", line);
                    262:                        continue;
                    263:                }
1.25      markus    264:                if (escaped) {
                    265:                        escaped--;
                    266:                        fprintf(stderr, "escaped: %s", line);
                    267:                        continue;
1.19      markus    268:                }
                    269:                *p = '\0';
                    270:                strlcat(encoded, line, sizeof(encoded));
                    271:        }
1.36      markus    272:        blen = uudecode(encoded, (u_char *)blob, sizeof(blob));
1.19      markus    273:        if (blen < 0) {
                    274:                fprintf(stderr, "uudecode failed.\n");
                    275:                exit(1);
                    276:        }
1.32      markus    277:        k = private ?
                    278:            do_convert_private_ssh2_from_blob(blob, blen) :
1.33      markus    279:            key_from_blob(blob, blen);
1.32      markus    280:        if (k == NULL) {
                    281:                fprintf(stderr, "decode blob failed.\n");
                    282:                exit(1);
                    283:        }
                    284:        ok = private ?
                    285:            PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
                    286:            key_write(k, stdout);
                    287:        if (!ok) {
                    288:                fprintf(stderr, "key write failed");
                    289:                exit(1);
                    290:        }
1.19      markus    291:        key_free(k);
                    292:        fprintf(stdout, "\n");
                    293:        fclose(fp);
                    294:        exit(0);
                    295: }
                    296:
                    297: void
                    298: do_print_public(struct passwd *pw)
                    299: {
                    300:        Key *k;
                    301:        struct stat st;
                    302:
                    303:        if (!have_identity)
                    304:                ask_filename(pw, "Enter file in which the key is");
                    305:        if (stat(identity_file, &st) < 0) {
                    306:                perror(identity_file);
                    307:                exit(1);
                    308:        }
1.33      markus    309:        k = key_new(KEY_UNSPEC);
1.19      markus    310:        if (!try_load_key(identity_file, k)) {
                    311:                fprintf(stderr, "load failed\n");
                    312:                exit(1);
                    313:        }
                    314:        if (!key_write(k, stdout))
                    315:                fprintf(stderr, "key_write failed");
                    316:        key_free(k);
                    317:        fprintf(stdout, "\n");
                    318:        exit(0);
                    319: }
                    320:
1.7       markus    321: void
1.8       markus    322: do_fingerprint(struct passwd *pw)
                    323: {
1.30      markus    324:
1.15      markus    325:        FILE *f;
1.19      markus    326:        Key *public;
1.16      markus    327:        char *comment = NULL, *cp, *ep, line[16*1024];
1.33      markus    328:        int i, skip = 0, num = 1, invalid = 1, success = 0;
1.12      markus    329:        struct stat st;
                    330:
                    331:        if (!have_identity)
                    332:                ask_filename(pw, "Enter file in which the key is");
                    333:        if (stat(identity_file, &st) < 0) {
                    334:                perror(identity_file);
                    335:                exit(1);
                    336:        }
1.33      markus    337:        public = key_new(KEY_RSA1);
1.19      markus    338:        if (load_public_key(identity_file, public, &comment)) {
1.33      markus    339:                success = 1;
                    340:        } else {
1.19      markus    341:                key_free(public);
1.33      markus    342:                public = key_new(KEY_UNSPEC);
                    343:                if (try_load_public_key(identity_file, public, &comment))
                    344:                        success = 1;
                    345:                else
1.38      markus    346:                        debug("try_load_public_key KEY_UNSPEC failed");
1.33      markus    347:        }
                    348:        if (success) {
                    349:                printf("%d %s %s\n", key_size(public), key_fingerprint(public), comment);
                    350:                key_free(public);
                    351:                xfree(comment);
1.15      markus    352:                exit(0);
                    353:        }
                    354:
                    355:        f = fopen(identity_file, "r");
                    356:        if (f != NULL) {
                    357:                while (fgets(line, sizeof(line), f)) {
                    358:                        i = strlen(line) - 1;
                    359:                        if (line[i] != '\n') {
                    360:                                error("line %d too long: %.40s...", num, line);
                    361:                                skip = 1;
                    362:                                continue;
                    363:                        }
                    364:                        num++;
                    365:                        if (skip) {
                    366:                                skip = 0;
                    367:                                continue;
                    368:                        }
                    369:                        line[i] = '\0';
                    370:
                    371:                        /* Skip leading whitespace, empty and comment lines. */
                    372:                        for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
                    373:                                ;
                    374:                        if (!*cp || *cp == '\n' || *cp == '#')
                    375:                                continue ;
                    376:                        i = strtol(cp, &ep, 10);
                    377:                        if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
                    378:                                int quoted = 0;
                    379:                                comment = cp;
                    380:                                for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
                    381:                                        if (*cp == '\\' && cp[1] == '"')
                    382:                                                cp++;   /* Skip both */
                    383:                                        else if (*cp == '"')
                    384:                                                quoted = !quoted;
                    385:                                }
                    386:                                if (!*cp)
                    387:                                        continue;
                    388:                                *cp++ = '\0';
                    389:                        }
                    390:                        ep = cp;
1.38      markus    391:                        public = key_new(KEY_RSA1);
                    392:                        if (key_read(public, &cp) != 1) {
                    393:                                cp = ep;
                    394:                                key_free(public);
                    395:                                public = key_new(KEY_UNSPEC);
                    396:                                if (key_read(public, &cp) != 1) {
                    397:                                        key_free(public);
                    398:                                        continue;
                    399:                                }
1.12      markus    400:                        }
1.38      markus    401:                        comment = *cp ? cp : comment;
                    402:                        printf("%d %s %s\n", key_size(public),
                    403:                            key_fingerprint(public),
                    404:                            comment ? comment : "no comment");
                    405:                        invalid = 0;
1.12      markus    406:                }
1.15      markus    407:                fclose(f);
                    408:        }
1.30      markus    409:        key_free(public);
1.15      markus    410:        if (invalid) {
                    411:                printf("%s is not a valid key file.\n", identity_file);
                    412:                exit(1);
1.12      markus    413:        }
                    414:        exit(0);
1.8       markus    415: }
                    416:
1.13      deraadt   417: /*
                    418:  * Perform changing a passphrase.  The argument is the passwd structure
                    419:  * for the current user.
                    420:  */
1.8       markus    421: void
1.7       markus    422: do_change_passphrase(struct passwd *pw)
                    423: {
1.12      markus    424:        char *comment;
                    425:        char *old_passphrase, *passphrase1, *passphrase2;
                    426:        struct stat st;
1.19      markus    427:        Key *private;
                    428:        Key *public;
1.33      markus    429:        int type = KEY_RSA1;
1.12      markus    430:
                    431:        if (!have_identity)
                    432:                ask_filename(pw, "Enter file in which the key is");
                    433:        if (stat(identity_file, &st) < 0) {
                    434:                perror(identity_file);
                    435:                exit(1);
                    436:        }
1.33      markus    437:        public = key_new(type);
                    438:        if (!load_public_key(identity_file, public, NULL)) {
                    439:                type = KEY_UNSPEC;
                    440:        } else {
1.19      markus    441:                /* Clear the public key since we are just about to load the whole file. */
                    442:                key_free(public);
1.12      markus    443:        }
                    444:        /* Try to load the file with empty passphrase. */
1.19      markus    445:        private = key_new(type);
                    446:        if (!load_private_key(identity_file, "", private, &comment)) {
1.12      markus    447:                if (identity_passphrase)
                    448:                        old_passphrase = xstrdup(identity_passphrase);
                    449:                else
                    450:                        old_passphrase = read_passphrase("Enter old passphrase: ", 1);
1.19      markus    451:                if (!load_private_key(identity_file, old_passphrase, private, &comment)) {
1.12      markus    452:                        memset(old_passphrase, 0, strlen(old_passphrase));
                    453:                        xfree(old_passphrase);
                    454:                        printf("Bad passphrase.\n");
                    455:                        exit(1);
                    456:                }
                    457:                memset(old_passphrase, 0, strlen(old_passphrase));
                    458:                xfree(old_passphrase);
                    459:        }
                    460:        printf("Key has comment '%s'\n", comment);
                    461:
                    462:        /* Ask the new passphrase (twice). */
                    463:        if (identity_new_passphrase) {
                    464:                passphrase1 = xstrdup(identity_new_passphrase);
                    465:                passphrase2 = NULL;
                    466:        } else {
                    467:                passphrase1 =
                    468:                        read_passphrase("Enter new passphrase (empty for no passphrase): ", 1);
                    469:                passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
                    470:
                    471:                /* Verify that they are the same. */
                    472:                if (strcmp(passphrase1, passphrase2) != 0) {
                    473:                        memset(passphrase1, 0, strlen(passphrase1));
                    474:                        memset(passphrase2, 0, strlen(passphrase2));
                    475:                        xfree(passphrase1);
                    476:                        xfree(passphrase2);
                    477:                        printf("Pass phrases do not match.  Try again.\n");
                    478:                        exit(1);
                    479:                }
                    480:                /* Destroy the other copy. */
                    481:                memset(passphrase2, 0, strlen(passphrase2));
                    482:                xfree(passphrase2);
                    483:        }
                    484:
                    485:        /* Save the file using the new passphrase. */
1.19      markus    486:        if (!save_private_key(identity_file, passphrase1, private, comment)) {
1.12      markus    487:                printf("Saving the key failed: %s: %s.\n",
                    488:                       identity_file, strerror(errno));
                    489:                memset(passphrase1, 0, strlen(passphrase1));
                    490:                xfree(passphrase1);
1.19      markus    491:                key_free(private);
1.12      markus    492:                xfree(comment);
                    493:                exit(1);
                    494:        }
                    495:        /* Destroy the passphrase and the copy of the key in memory. */
                    496:        memset(passphrase1, 0, strlen(passphrase1));
                    497:        xfree(passphrase1);
1.19      markus    498:        key_free(private);               /* Destroys contents */
1.12      markus    499:        xfree(comment);
1.1       deraadt   500:
1.12      markus    501:        printf("Your identification has been saved with the new passphrase.\n");
                    502:        exit(0);
1.1       deraadt   503: }
                    504:
1.13      deraadt   505: /*
                    506:  * Change the comment of a private key file.
                    507:  */
1.2       provos    508: void
                    509: do_change_comment(struct passwd *pw)
1.1       deraadt   510: {
1.46    ! deraadt   511:        char new_comment[1024], *comment, *passphrase;
        !           512:        Key *private, *public;
1.12      markus    513:        struct stat st;
                    514:        FILE *f;
1.46    ! deraadt   515:        int fd;
1.12      markus    516:
                    517:        if (!have_identity)
                    518:                ask_filename(pw, "Enter file in which the key is");
                    519:        if (stat(identity_file, &st) < 0) {
                    520:                perror(identity_file);
                    521:                exit(1);
                    522:        }
1.14      markus    523:        /*
                    524:         * Try to load the public key from the file the verify that it is
                    525:         * readable and of the proper format.
                    526:         */
1.33      markus    527:        public = key_new(KEY_RSA1);
1.19      markus    528:        if (!load_public_key(identity_file, public, NULL)) {
1.12      markus    529:                printf("%s is not a valid key file.\n", identity_file);
1.43      markus    530:                printf("Comments are only supported in RSA1 keys\n");
1.12      markus    531:                exit(1);
                    532:        }
1.14      markus    533:
1.33      markus    534:        private = key_new(KEY_RSA1);
1.19      markus    535:        if (load_private_key(identity_file, "", private, &comment))
1.12      markus    536:                passphrase = xstrdup("");
                    537:        else {
                    538:                if (identity_passphrase)
                    539:                        passphrase = xstrdup(identity_passphrase);
                    540:                else if (identity_new_passphrase)
                    541:                        passphrase = xstrdup(identity_new_passphrase);
                    542:                else
                    543:                        passphrase = read_passphrase("Enter passphrase: ", 1);
                    544:                /* Try to load using the passphrase. */
1.19      markus    545:                if (!load_private_key(identity_file, passphrase, private, &comment)) {
1.12      markus    546:                        memset(passphrase, 0, strlen(passphrase));
                    547:                        xfree(passphrase);
                    548:                        printf("Bad passphrase.\n");
                    549:                        exit(1);
                    550:                }
                    551:        }
                    552:        printf("Key now has comment '%s'\n", comment);
                    553:
                    554:        if (identity_comment) {
                    555:                strlcpy(new_comment, identity_comment, sizeof(new_comment));
                    556:        } else {
                    557:                printf("Enter new comment: ");
                    558:                fflush(stdout);
                    559:                if (!fgets(new_comment, sizeof(new_comment), stdin)) {
                    560:                        memset(passphrase, 0, strlen(passphrase));
1.19      markus    561:                        key_free(private);
1.12      markus    562:                        exit(1);
                    563:                }
                    564:                if (strchr(new_comment, '\n'))
                    565:                        *strchr(new_comment, '\n') = 0;
                    566:        }
                    567:
                    568:        /* Save the file using the new passphrase. */
1.19      markus    569:        if (!save_private_key(identity_file, passphrase, private, new_comment)) {
1.12      markus    570:                printf("Saving the key failed: %s: %s.\n",
                    571:                       identity_file, strerror(errno));
                    572:                memset(passphrase, 0, strlen(passphrase));
                    573:                xfree(passphrase);
1.19      markus    574:                key_free(private);
1.12      markus    575:                xfree(comment);
                    576:                exit(1);
                    577:        }
                    578:        memset(passphrase, 0, strlen(passphrase));
                    579:        xfree(passphrase);
1.19      markus    580:        key_free(private);
1.12      markus    581:
                    582:        strlcat(identity_file, ".pub", sizeof(identity_file));
1.46    ! deraadt   583:        fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        !           584:        if (fd == -1) {
1.12      markus    585:                printf("Could not save your public key in %s\n", identity_file);
                    586:                exit(1);
                    587:        }
1.46    ! deraadt   588:        f = fdopen(fd, "w");
        !           589:        if (f == NULL) {
        !           590:                printf("fdopen %s failed", identity_file);
        !           591:                exit(1);
        !           592:        }
1.19      markus    593:        if (!key_write(public, f))
                    594:                fprintf(stderr, "write key failed");
                    595:        key_free(public);
                    596:        fprintf(f, " %s\n", new_comment);
1.12      markus    597:        fclose(f);
1.1       deraadt   598:
1.12      markus    599:        xfree(comment);
1.1       deraadt   600:
1.12      markus    601:        printf("The comment in your key file has been changed.\n");
                    602:        exit(0);
1.1       deraadt   603: }
                    604:
1.10      markus    605: void
                    606: usage(void)
                    607: {
1.45      deraadt   608:        printf("Usage: %s [-lpqxXyc] [-t type] [-b bits] [-f file] [-C comment] "
1.44      deraadt   609:            "[-N new-pass] [-P pass]\n", __progname);
1.12      markus    610:        exit(1);
1.10      markus    611: }
                    612:
1.13      deraadt   613: /*
                    614:  * Main program for key management.
                    615:  */
1.2       provos    616: int
                    617: main(int ac, char **av)
1.1       deraadt   618: {
1.12      markus    619:        char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2;
1.46    ! deraadt   620:        Key *private, *public;
1.12      markus    621:        struct passwd *pw;
1.46    ! deraadt   622:        int opt, type, fd;
1.12      markus    623:        struct stat st;
                    624:        FILE *f;
1.33      markus    625:
1.12      markus    626:        extern int optind;
                    627:        extern char *optarg;
                    628:
1.26      markus    629:        SSLeay_add_all_algorithms();
1.19      markus    630:
1.14      markus    631:        /* we need this for the home * directory.  */
1.12      markus    632:        pw = getpwuid(getuid());
                    633:        if (!pw) {
                    634:                printf("You don't exist, go away!\n");
                    635:                exit(1);
                    636:        }
1.19      markus    637:        if (gethostname(hostname, sizeof(hostname)) < 0) {
                    638:                perror("gethostname");
                    639:                exit(1);
                    640:        }
1.14      markus    641:
1.39      markus    642:        while ((opt = getopt(ac, av, "dqpclRxXyb:f:t:P:N:C:")) != -1) {
1.12      markus    643:                switch (opt) {
                    644:                case 'b':
                    645:                        bits = atoi(optarg);
                    646:                        if (bits < 512 || bits > 32768) {
                    647:                                printf("Bits has bad value.\n");
                    648:                                exit(1);
                    649:                        }
                    650:                        break;
                    651:
                    652:                case 'l':
                    653:                        print_fingerprint = 1;
                    654:                        break;
                    655:
                    656:                case 'p':
                    657:                        change_passphrase = 1;
                    658:                        break;
                    659:
                    660:                case 'c':
                    661:                        change_comment = 1;
                    662:                        break;
                    663:
                    664:                case 'f':
                    665:                        strlcpy(identity_file, optarg, sizeof(identity_file));
                    666:                        have_identity = 1;
                    667:                        break;
                    668:
                    669:                case 'P':
                    670:                        identity_passphrase = optarg;
                    671:                        break;
                    672:
                    673:                case 'N':
                    674:                        identity_new_passphrase = optarg;
                    675:                        break;
                    676:
                    677:                case 'C':
                    678:                        identity_comment = optarg;
                    679:                        break;
                    680:
                    681:                case 'q':
                    682:                        quiet = 1;
1.20      deraadt   683:                        break;
                    684:
                    685:                case 'R':
1.33      markus    686:                        /* unused */
                    687:                        exit(0);
1.12      markus    688:                        break;
                    689:
1.19      markus    690:                case 'x':
                    691:                        convert_to_ssh2 = 1;
                    692:                        break;
                    693:
                    694:                case 'X':
                    695:                        convert_from_ssh2 = 1;
                    696:                        break;
                    697:
                    698:                case 'y':
                    699:                        print_public = 1;
                    700:                        break;
                    701:
                    702:                case 'd':
1.33      markus    703:                        key_type_name = "dsa";
1.19      markus    704:                        break;
                    705:
1.33      markus    706:                case 't':
                    707:                        key_type_name = optarg;
                    708:                        break;
                    709:
1.12      markus    710:                case '?':
                    711:                default:
                    712:                        usage();
                    713:                }
                    714:        }
                    715:        if (optind < ac) {
                    716:                printf("Too many arguments.\n");
                    717:                usage();
                    718:        }
                    719:        if (change_passphrase && change_comment) {
                    720:                printf("Can only have one of -p and -c.\n");
                    721:                usage();
                    722:        }
                    723:        if (print_fingerprint)
                    724:                do_fingerprint(pw);
                    725:        if (change_passphrase)
                    726:                do_change_passphrase(pw);
                    727:        if (change_comment)
                    728:                do_change_comment(pw);
1.19      markus    729:        if (convert_to_ssh2)
                    730:                do_convert_to_ssh2(pw);
                    731:        if (convert_from_ssh2)
                    732:                do_convert_from_ssh2(pw);
                    733:        if (print_public)
                    734:                do_print_public(pw);
1.12      markus    735:
                    736:        arc4random_stir();
                    737:
1.35      markus    738:        type = key_type_from_name(key_type_name);
                    739:        if (type == KEY_UNSPEC) {
                    740:                fprintf(stderr, "unknown key type %s\n", key_type_name);
                    741:                exit(1);
1.19      markus    742:        }
1.33      markus    743:        if (!quiet)
1.35      markus    744:                printf("Generating public/private %s key pair.\n", key_type_name);
1.33      markus    745:        private = key_generate(type, bits);
                    746:        if (private == NULL) {
                    747:                fprintf(stderr, "key_generate failed");
                    748:                exit(1);
                    749:        }
                    750:        public  = key_from_private(private);
1.12      markus    751:
                    752:        if (!have_identity)
                    753:                ask_filename(pw, "Enter file in which to save the key");
                    754:
                    755:        /* Create ~/.ssh directory if it doesn\'t already exist. */
1.40      markus    756:        snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1.12      markus    757:        if (strstr(identity_file, dotsshdir) != NULL &&
                    758:            stat(dotsshdir, &st) < 0) {
1.29      djm       759:                if (mkdir(dotsshdir, 0700) < 0)
1.12      markus    760:                        error("Could not create directory '%s'.", dotsshdir);
                    761:                else if (!quiet)
                    762:                        printf("Created directory '%s'.\n", dotsshdir);
                    763:        }
                    764:        /* If the file already exists, ask the user to confirm. */
                    765:        if (stat(identity_file, &st) >= 0) {
                    766:                char yesno[3];
                    767:                printf("%s already exists.\n", identity_file);
                    768:                printf("Overwrite (y/n)? ");
                    769:                fflush(stdout);
                    770:                if (fgets(yesno, sizeof(yesno), stdin) == NULL)
                    771:                        exit(1);
                    772:                if (yesno[0] != 'y' && yesno[0] != 'Y')
                    773:                        exit(1);
                    774:        }
                    775:        /* Ask for a passphrase (twice). */
                    776:        if (identity_passphrase)
                    777:                passphrase1 = xstrdup(identity_passphrase);
                    778:        else if (identity_new_passphrase)
                    779:                passphrase1 = xstrdup(identity_new_passphrase);
                    780:        else {
                    781: passphrase_again:
                    782:                passphrase1 =
                    783:                        read_passphrase("Enter passphrase (empty for no passphrase): ", 1);
                    784:                passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
                    785:                if (strcmp(passphrase1, passphrase2) != 0) {
                    786:                        /* The passphrases do not match.  Clear them and retry. */
                    787:                        memset(passphrase1, 0, strlen(passphrase1));
                    788:                        memset(passphrase2, 0, strlen(passphrase2));
                    789:                        xfree(passphrase1);
                    790:                        xfree(passphrase2);
                    791:                        printf("Passphrases do not match.  Try again.\n");
                    792:                        goto passphrase_again;
                    793:                }
                    794:                /* Clear the other copy of the passphrase. */
                    795:                memset(passphrase2, 0, strlen(passphrase2));
                    796:                xfree(passphrase2);
                    797:        }
                    798:
                    799:        if (identity_comment) {
                    800:                strlcpy(comment, identity_comment, sizeof(comment));
                    801:        } else {
1.18      markus    802:                /* Create default commend field for the passphrase. */
1.12      markus    803:                snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
                    804:        }
                    805:
                    806:        /* Save the key with the given passphrase and comment. */
1.19      markus    807:        if (!save_private_key(identity_file, passphrase1, private, comment)) {
1.12      markus    808:                printf("Saving the key failed: %s: %s.\n",
1.19      markus    809:                    identity_file, strerror(errno));
1.12      markus    810:                memset(passphrase1, 0, strlen(passphrase1));
                    811:                xfree(passphrase1);
                    812:                exit(1);
                    813:        }
                    814:        /* Clear the passphrase. */
                    815:        memset(passphrase1, 0, strlen(passphrase1));
                    816:        xfree(passphrase1);
                    817:
                    818:        /* Clear the private key and the random number generator. */
1.33      markus    819:        key_free(private);
1.12      markus    820:        arc4random_stir();
                    821:
                    822:        if (!quiet)
                    823:                printf("Your identification has been saved in %s.\n", identity_file);
                    824:
                    825:        strlcat(identity_file, ".pub", sizeof(identity_file));
1.46    ! deraadt   826:        fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        !           827:        if (fd == -1) {
1.12      markus    828:                printf("Could not save your public key in %s\n", identity_file);
1.46    ! deraadt   829:                exit(1);
        !           830:        }
        !           831:        f = fdopen(fd, "w");
        !           832:        if (f == NULL) {
        !           833:                printf("fdopen %s failed", identity_file);
1.12      markus    834:                exit(1);
                    835:        }
1.19      markus    836:        if (!key_write(public, f))
                    837:                fprintf(stderr, "write key failed");
                    838:        fprintf(f, " %s\n", comment);
1.12      markus    839:        fclose(f);
                    840:
                    841:        if (!quiet) {
1.19      markus    842:                printf("Your public key has been saved in %s.\n",
                    843:                    identity_file);
1.12      markus    844:                printf("The key fingerprint is:\n");
1.19      markus    845:                printf("%s %s\n", key_fingerprint(public), comment);
1.12      markus    846:        }
1.19      markus    847:
                    848:        key_free(public);
1.12      markus    849:        exit(0);
1.1       deraadt   850: }