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

Diff for /src/usr.bin/ssh/ssh-keygen.c between version 1.1 and 1.7

version 1.1, 1999/09/26 20:53:37 version 1.7, 1999/11/16 22:27:54
Line 16 
Line 16 
 #include "includes.h"  #include "includes.h"
 RCSID("$Id$");  RCSID("$Id$");
   
 #ifndef HAVE_GETHOSTNAME  
 #include <sys/utsname.h>  
 #endif  
 #include "randoms.h"  
 #include "rsa.h"  #include "rsa.h"
 #include "ssh.h"  #include "ssh.h"
 #include "xmalloc.h"  #include "xmalloc.h"
   
 /* Generated private key. */  /* Generated private key. */
 RSAPrivateKey private_key;  RSA *private_key;
   
 /* Generated public key. */  /* Generated public key. */
 RSAPublicKey public_key;  RSA *public_key;
   
 /* Random number generator state. */  
 RandomState state;  
   
 /* Number of bits in the RSA key.  This value can be changed on the command  /* Number of bits in the RSA key.  This value can be changed on the command
    line. */     line. */
 int bits = 1024;  int bits = 1024;
Line 45 
Line 38 
    on the command line. */     on the command line. */
 int change_comment = 0;  int change_comment = 0;
   
   int quiet = 0;
   
 /* This is set to the identity file name if given on the command line. */  /* This is set to the identity file name if given on the command line. */
 char *identity_file = NULL;  char *identity_file = NULL;
   
Line 60 
Line 55 
 /* Perform changing a passphrase.  The argument is the passwd structure  /* Perform changing a passphrase.  The argument is the passwd structure
    for the current user. */     for the current user. */
   
 void do_change_passphrase(struct passwd *pw)  char *
   get_filename(struct passwd *pw, const char *prompt)
 {  {
   char buf[1024], *comment;    char buf[1024], default_file[1024];
   RSAPrivateKey private_key;  
   char *old_passphrase, *passphrase1, *passphrase2;  
   struct stat st;  
   
   /* Read key file name. */    /* Read key file name. */
   if (identity_file != NULL)    if (identity_file != NULL) {
     {      return xstrdup(identity_file);
       strncpy(buf, identity_file, sizeof(buf));    } else {
       buf[sizeof(buf) - 1] = '\0';      snprintf(default_file, sizeof default_file, "%s/%s",
     }               pw->pw_dir, SSH_CLIENT_IDENTITY);
   else      printf("%s (%s): ", prompt, default_file);
     {      fflush(stdout);
       printf("Enter file in which the key is ($HOME/%s): ",      if (fgets(buf, sizeof(buf), stdin) == NULL)
              SSH_CLIENT_IDENTITY);        exit(1);
       fflush(stdout);      if (strchr(buf, '\n'))
       if (fgets(buf, sizeof(buf), stdin) == NULL)        *strchr(buf, '\n') = 0;
         exit(1);      if (strcmp(buf, "") == 0)
       if (strchr(buf, '\n'))        return xstrdup(default_file);
         *strchr(buf, '\n') = 0;    }
       if (strcmp(buf, "") == 0)    return xstrdup(buf);
         sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);  }
     }  
   
   void
   do_change_passphrase(struct passwd *pw)
   {
     char *file, *comment;
     char *old_passphrase, *passphrase1, *passphrase2;
     struct stat st;
     RSA *private_key;
   
     file = get_filename(pw, "Enter file in which the key is");
   /* Check if the file exists. */    /* Check if the file exists. */
   if (stat(buf, &st) < 0)    if (stat(file, &st) < 0)
     {      {
       perror(buf);        perror(file);
       exit(1);        exit(1);
     }      }
   
   /* Try to load the public key from the file the verify that it is    /* Try to load the public key from the file the verify that it is
      readable and of the proper format. */       readable and of the proper format. */
   if (!load_public_key(buf, &public_key, NULL))    public_key = RSA_new();
     if (!load_public_key(file, public_key, NULL))
     {      {
       printf("%s is not a valid key file.\n", buf);        printf("%s is not a valid key file.\n", file);
       exit(1);        exit(1);
     }      }
   /* Clear the public key since we are just about to load the whole file. */    /* Clear the public key since we are just about to load the whole file. */
   rsa_clear_public_key(&public_key);    RSA_free(public_key);
   
   /* Try to load the file with empty passphrase. */    /* Try to load the file with empty passphrase. */
   if (!load_private_key(buf, "", &private_key, &comment))    private_key = RSA_new();
     {    if (!load_private_key(file, "", private_key, &comment)) {
       /* Read passphrase from the user. */      /* Read passphrase from the user. */
       if (identity_passphrase)      if (identity_passphrase)
         old_passphrase = xstrdup(identity_passphrase);        old_passphrase = xstrdup(identity_passphrase);
       else      else
         old_passphrase = read_passphrase("Enter old passphrase: ", 1);        old_passphrase = read_passphrase("Enter old passphrase: ", 1);
       /* Try to load using the passphrase. */      /* Try to load using the passphrase. */
       if (!load_private_key(buf, old_passphrase, &private_key, &comment))      if (!load_private_key(file, old_passphrase, private_key, &comment))
         {        {
           memset(old_passphrase, 0, strlen(old_passphrase));          memset(old_passphrase, 0, strlen(old_passphrase));
           xfree(old_passphrase);          xfree(old_passphrase);
           printf("Bad passphrase.\n");          printf("Bad passphrase.\n");
           exit(1);          exit(1);
         }        }
       /* Destroy the passphrase. */      /* Destroy the passphrase. */
       memset(old_passphrase, 0, strlen(old_passphrase));      memset(old_passphrase, 0, strlen(old_passphrase));
       xfree(old_passphrase);      xfree(old_passphrase);
     }    }
   printf("Key has comment '%s'\n", comment);    printf("Key has comment '%s'\n", comment);
   
   /* Ask the new passphrase (twice). */    /* Ask the new passphrase (twice). */
Line 153 
Line 155 
     }      }
   
   /* Save the file using the new passphrase. */    /* Save the file using the new passphrase. */
   if (!save_private_key(buf, passphrase1, &private_key, comment, &state))    if (!save_private_key(file, passphrase1, private_key, comment))
     {      {
       printf("Saving the key failed: %s: %s.\n",        printf("Saving the key failed: %s: %s.\n",
              buf, strerror(errno));               file, strerror(errno));
       memset(passphrase1, 0, strlen(passphrase1));        memset(passphrase1, 0, strlen(passphrase1));
       xfree(passphrase1);        xfree(passphrase1);
       rsa_clear_private_key(&private_key);        RSA_free(private_key);
       xfree(comment);        xfree(comment);
       exit(1);        exit(1);
     }      }
   /* Destroy the passphrase and the copy of the key in memory. */    /* Destroy the passphrase and the copy of the key in memory. */
   memset(passphrase1, 0, strlen(passphrase1));    memset(passphrase1, 0, strlen(passphrase1));
   xfree(passphrase1);    xfree(passphrase1);
   rsa_clear_private_key(&private_key);    RSA_free(private_key); /* Destroys contents */
   xfree(comment);    xfree(comment);
   
   printf("Your identification has been saved with the new passphrase.\n");    printf("Your identification has been saved with the new passphrase.\n");
Line 175 
Line 177 
   
 /* Change the comment of a private key file. */  /* Change the comment of a private key file. */
   
 void do_change_comment(struct passwd *pw)  void
   do_change_comment(struct passwd *pw)
 {  {
   char buf[1024], new_comment[1024], *comment;    char new_comment[1024], *file, *comment;
   RSAPrivateKey private_key;    RSA *private_key;
   char *passphrase;    char *passphrase;
   struct stat st;    struct stat st;
   FILE *f;    FILE *f;
     char *tmpbuf;
   
   /* Read key file name. */    file = get_filename(pw, "Enter file in which the key is");
   if (identity_file)  
     {  
       strncpy(buf, identity_file, sizeof(buf));  
       buf[sizeof(buf) - 1] = '\0';  
     }  
   else  
     {  
       printf("Enter file in which the key is ($HOME/%s): ",  
              SSH_CLIENT_IDENTITY);  
       fflush(stdout);  
       if (fgets(buf, sizeof(buf), stdin) == NULL)  
         exit(1);  
       if (strchr(buf, '\n'))  
         *strchr(buf, '\n') = 0;  
       if (strcmp(buf, "") == 0)  
         sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);  
     }  
   
   /* Check if the file exists. */    /* Check if the file exists. */
   if (stat(buf, &st) < 0)    if (stat(file, &st) < 0)
     {      {
       perror(buf);        perror(file);
       exit(1);        exit(1);
     }      }
   
   /* Try to load the public key from the file the verify that it is    /* Try to load the public key from the file the verify that it is
      readable and of the proper format. */       readable and of the proper format. */
   if (!load_public_key(buf, &public_key, NULL))    public_key = RSA_new();
     if (!load_public_key(file, public_key, NULL))
     {      {
       printf("%s is not a valid key file.\n", buf);        printf("%s is not a valid key file.\n", file);
       exit(1);        exit(1);
     }      }
   
     private_key = RSA_new();
   /* Try to load the file with empty passphrase. */    /* Try to load the file with empty passphrase. */
   if (load_private_key(buf, "", &private_key, &comment))    if (load_private_key(file, "", private_key, &comment))
     passphrase = xstrdup("");      passphrase = xstrdup("");
   else    else
     {      {
Line 231 
Line 219 
         else          else
           passphrase = read_passphrase("Enter passphrase: ", 1);            passphrase = read_passphrase("Enter passphrase: ", 1);
       /* Try to load using the passphrase. */        /* Try to load using the passphrase. */
       if (!load_private_key(buf, passphrase, &private_key, &comment))        if (!load_private_key(file, passphrase, private_key, &comment))
         {          {
           memset(passphrase, 0, strlen(passphrase));            memset(passphrase, 0, strlen(passphrase));
           xfree(passphrase);            xfree(passphrase);
Line 243 
Line 231 
   
   if (identity_comment)    if (identity_comment)
     {      {
       strncpy(new_comment, identity_comment, sizeof(new_comment));        strlcpy(new_comment, identity_comment, sizeof(new_comment));
       new_comment[sizeof(new_comment) - 1] = '\0';  
     }      }
   else    else
     {      {
Line 253 
Line 240 
       if (!fgets(new_comment, sizeof(new_comment), stdin))        if (!fgets(new_comment, sizeof(new_comment), stdin))
         {          {
           memset(passphrase, 0, strlen(passphrase));            memset(passphrase, 0, strlen(passphrase));
           rsa_clear_private_key(&private_key);            RSA_free(private_key);
           exit(1);            exit(1);
         }          }
   
Line 263 
Line 250 
     }      }
   
   /* Save the file using the new passphrase. */    /* Save the file using the new passphrase. */
   if (!save_private_key(buf, passphrase, &private_key, new_comment,    if (!save_private_key(file, passphrase, private_key, new_comment))
                         &state))  
     {      {
       printf("Saving the key failed: %s: %s.\n",        printf("Saving the key failed: %s: %s.\n",
              buf, strerror(errno));               file, strerror(errno));
       memset(passphrase, 0, strlen(passphrase));        memset(passphrase, 0, strlen(passphrase));
       xfree(passphrase);        xfree(passphrase);
       rsa_clear_private_key(&private_key);        RSA_free(private_key);
       xfree(comment);        xfree(comment);
       exit(1);        exit(1);
     }      }
Line 278 
Line 264 
   /* Destroy the passphrase and the private key in memory. */    /* Destroy the passphrase and the private key in memory. */
   memset(passphrase, 0, strlen(passphrase));    memset(passphrase, 0, strlen(passphrase));
   xfree(passphrase);    xfree(passphrase);
   rsa_clear_private_key(&private_key);    RSA_free(private_key);
   
   /* Save the public key in text format in a file with the same name but    /* Save the public key in text format in a file with the same name but
      .pub appended. */       .pub appended. */
   strcat(buf, ".pub");    strcat(file, ".pub");
   f = fopen(buf, "w");    f = fopen(file, "w");
   if (!f)    if (!f)
     {      {
       printf("Could not save your public key in %s\n", buf);        printf("Could not save your public key in %s\n", file);
       exit(1);        exit(1);
     }      }
   fprintf(f, "%d ", public_key.bits);    fprintf(f, "%d ", BN_num_bits(public_key->n));
   mpz_out_str(f, 10, &public_key.e);    tmpbuf = BN_bn2dec(public_key->e);
   fprintf(f, " ");    fprintf(f, "%s ", tmpbuf);
   mpz_out_str(f, 10, &public_key.n);    free (tmpbuf);
   fprintf(f, " %s\n", new_comment);    tmpbuf = BN_bn2dec(public_key->n);
     fprintf(f, "%s %s\n", tmpbuf, new_comment);
     free (tmpbuf);
   fclose(f);    fclose(f);
   
   xfree(comment);    xfree(comment);
Line 304 
Line 292 
   
 /* Main program for key management. */  /* Main program for key management. */
   
 int main(int ac, char **av)  int
   main(int ac, char **av)
 {  {
   char buf[16384], buf2[1024], *passphrase1, *passphrase2;    char buf[16384], buf2[1024], *passphrase1, *passphrase2;
   struct passwd *pw;    struct passwd *pw;
     char *file, *tmpbuf;
   int opt;    int opt;
   struct stat st;    struct stat st;
   FILE *f;    FILE *f;
 #ifdef HAVE_GETHOSTNAME    char hostname[MAXHOSTNAMELEN];
   char hostname[257];  
 #else  
   struct utsname uts;  
 #endif  
   extern int optind;    extern int optind;
   extern char *optarg;    extern char *optarg;
   
     /* check if RSA support exists */
     if (rsa_alive() == 0) {
       extern char *__progname;
   
       fprintf(stderr,
         "%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
         __progname);
       exit(1);
     }
   
   /* Get user\'s passwd structure.  We need this for the home directory. */    /* Get user\'s passwd structure.  We need this for the home directory. */
   pw = getpwuid(getuid());    pw = getpwuid(getuid());
   if (!pw)    if (!pw)
Line 328 
Line 324 
     }      }
   
   /* Create ~/.ssh directory if it doesn\'t already exist. */    /* Create ~/.ssh directory if it doesn\'t already exist. */
   sprintf(buf, "%s/%s", pw->pw_dir, SSH_USER_DIR);    snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_USER_DIR);
   if (stat(buf, &st) < 0)    if (stat(buf, &st) < 0)
     if (mkdir(buf, 0755) < 0)      if (mkdir(buf, 0755) < 0)
       error("Could not create directory '%s'.", buf);        error("Could not create directory '%s'.", buf);
   
   /* Parse command line arguments. */    /* Parse command line arguments. */
   while ((opt = getopt(ac, av, "pcb:f:P:N:C:")) != EOF)    while ((opt = getopt(ac, av, "qpcb:f:P:N:C:")) != EOF)
     {      {
       switch (opt)        switch (opt)
         {          {
Line 371 
Line 367 
           identity_comment = optarg;            identity_comment = optarg;
           break;            break;
   
           case 'q':
             quiet = 1;
             break;
   
         case '?':          case '?':
         default:          default:
           printf("ssh-keygen version %s\n", SSH_VERSION);            printf("ssh-keygen version %s\n", SSH_VERSION);
Line 399 
Line 399 
   if (change_comment)    if (change_comment)
     do_change_comment(pw);      do_change_comment(pw);
   
   /* Initialize random number generator.  This may take a while if the    arc4random_stir();
      user has no seed file, so display a message to the user. */  
   printf("Initializing random number generator...\n");  
   sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_SEEDFILE);  
   random_initialize(&state, buf);  
   
   /* Save random seed so we don\'t need to do all that time-consuming    if (quiet)
      environmental noise collection the next time. */      rsa_set_verbose(0);
   random_save(&state, buf);  
   
   /* Generate the rsa key pair. */    /* Generate the rsa key pair. */
   rsa_generate_key(&private_key, &public_key, &state, bits);    private_key = RSA_new();
     public_key = RSA_new();
     rsa_generate_key(private_key, public_key, bits);
   
   /* Save the state again, just to remove any fear that the previous state  
      could be used to recreate the key.  (That should not be possible anyway  
      since the pool is stirred after save and some noise is added.) */  
   random_save(&state, buf);  
   
  ask_file_again:   ask_file_again:
   
   /* Ask for a file to save the key in. */    file = get_filename(pw, "Enter file in which to save the key");
   if (identity_file)  
     {  
       strncpy(buf, identity_file, sizeof(buf));  
       buf[sizeof(buf) - 1] = '\0';  
     }  
   else  
     {  
       printf("Enter file in which to save the key ($HOME/%s): ",  
              SSH_CLIENT_IDENTITY);  
       fflush(stdout);  
       if (fgets(buf, sizeof(buf), stdin) == NULL)  
         exit(1);  
       if (strchr(buf, '\n'))  
         *strchr(buf, '\n') = 0;  
       if (strcmp(buf, "") == 0)  
         sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);  
     }  
   
   /* If the file aready exists, ask the user to confirm. */    /* If the file aready exists, ask the user to confirm. */
   if (stat(buf, &st) >= 0)    if (stat(file, &st) >= 0)
     {      {
       printf("%s already exists.\n", buf);        printf("%s already exists.\n", file);
       printf("Overwrite (y/n)? ");        printf("Overwrite (y/n)? ");
       fflush(stdout);        fflush(stdout);
       if (fgets(buf2, sizeof(buf2), stdin) == NULL)        if (fgets(buf2, sizeof(buf2), stdin) == NULL)
Line 481 
Line 456 
      edit this field. */       edit this field. */
   if (identity_comment)    if (identity_comment)
     {      {
       strncpy(buf2, identity_comment, sizeof(buf2));        strlcpy(buf2, identity_comment, sizeof(buf2));
       buf2[sizeof(buf2) - 1] = '\0';  
     }      }
   else    else
     {      {
 #ifdef HAVE_GETHOSTNAME  
       if (gethostname(hostname, sizeof(hostname)) < 0)        if (gethostname(hostname, sizeof(hostname)) < 0)
         {          {
           perror("gethostname");            perror("gethostname");
           exit(1);            exit(1);
         }          }
       sprintf(buf2, "%s@%s", pw->pw_name, hostname);        snprintf(buf2, sizeof buf2, "%s@%s", pw->pw_name, hostname);
 #else  
       if (uname(&uts) < 0)  
         {  
           perror("uname");  
           exit(1);  
         }  
       sprintf(buf2, "%s@%s", pw->pw_name, uts.nodename);  
 #endif  
     }      }
   
   /* Save the key with the given passphrase and comment. */    /* Save the key with the given passphrase and comment. */
   if (!save_private_key(buf, passphrase1, &private_key, buf2, &state))    if (!save_private_key(file, passphrase1, private_key, buf2))
     {      {
       printf("Saving the key failed: %s: %s.\n",        printf("Saving the key failed: %s: %s.\n",
              buf, strerror(errno));               file, strerror(errno));
       memset(passphrase1, 0, strlen(passphrase1));        memset(passphrase1, 0, strlen(passphrase1));
       xfree(passphrase1);        xfree(passphrase1);
         xfree(file);
       goto ask_file_again;        goto ask_file_again;
     }      }
   /* Clear the passphrase. */    /* Clear the passphrase. */
Line 517 
Line 483 
   xfree(passphrase1);    xfree(passphrase1);
   
   /* Clear the private key and the random number generator. */    /* Clear the private key and the random number generator. */
   rsa_clear_private_key(&private_key);    RSA_free(private_key);
   random_clear(&state);    arc4random_stir();
   
   printf("Your identification has been saved in %s.\n", buf);    if (!quiet)
       printf("Your identification has been saved in %s.\n", file);
   
   /* Display the public key on the screen. */    /* Display the public key on the screen. */
   printf("Your public key is:\n");    if (!quiet) {
   printf("%d ", public_key.bits);      printf("Your public key is:\n");
   mpz_out_str(stdout, 10, &public_key.e);      printf("%d ", BN_num_bits(public_key->n));
   printf(" ");      tmpbuf = BN_bn2dec(public_key->e);
   mpz_out_str(stdout, 10, &public_key.n);      printf("%s ", tmpbuf);
   printf(" %s\n", buf2);      free(tmpbuf);
       tmpbuf = BN_bn2dec(public_key->n);
       printf("%s %s\n", tmpbuf, buf2);
       free(tmpbuf);
     }
   
   /* Save the public key in text format in a file with the same name but    /* Save the public key in text format in a file with the same name but
      .pub appended. */       .pub appended. */
   strcat(buf, ".pub");    strcat(file, ".pub");
   f = fopen(buf, "w");    f = fopen(file, "w");
   if (!f)    if (!f)
     {      {
       printf("Could not save your public key in %s\n", buf);        printf("Could not save your public key in %s\n", file);
       exit(1);        exit(1);
     }      }
   fprintf(f, "%d ", public_key.bits);    fprintf(f, "%d ", BN_num_bits(public_key->n));
   mpz_out_str(f, 10, &public_key.e);    tmpbuf = BN_bn2dec(public_key->e);
   fprintf(f, " ");    fprintf(f, "%s ", tmpbuf);
   mpz_out_str(f, 10, &public_key.n);    free(tmpbuf);
   fprintf(f, " %s\n", buf2);    tmpbuf = BN_bn2dec(public_key->n);
     fprintf(f, "%s %s\n", tmpbuf, buf2);
     free(tmpbuf);
   fclose(f);    fclose(f);
   
   printf("Your public key has been saved in %s\n", buf);    if (!quiet)
       printf("Your public key has been saved in %s\n", file);
   
   exit(0);    exit(0);
 }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.7