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

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