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

Diff for /src/usr.bin/ssh/authfile.c between version 1.85 and 1.86

version 1.85, 2010/10/28 11:22:09 version 1.86, 2010/11/21 10:57:07
Line 69 
Line 69 
     "SSH PRIVATE KEY FILE FORMAT 1.1\n";      "SSH PRIVATE KEY FILE FORMAT 1.1\n";
   
 /*  /*
  * Saves the authentication (private) key in a file, encrypting it with   * Serialises the authentication (private) key to a blob, encrypting it with
  * passphrase.  The identification of the file (lowest 64 bits of n) will   * passphrase.  The identification of the blob (lowest 64 bits of n) will
  * precede the key to provide identification of the key without needing a   * precede the key to provide identification of the key without needing a
  * passphrase.   * passphrase.
  */   */
   
 static int  static int
 key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,  key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
     const char *comment)      const char *comment)
 {  {
         Buffer buffer, encrypted;          Buffer buffer, encrypted;
         u_char buf[100], *cp;          u_char buf[100], *cp;
         int fd, i, cipher_num;          int i, cipher_num;
         CipherContext ciphercontext;          CipherContext ciphercontext;
         Cipher *cipher;          Cipher *cipher;
         u_int32_t rnd;          u_int32_t rnd;
Line 152 
Line 151 
         memset(buf, 0, sizeof(buf));          memset(buf, 0, sizeof(buf));
         buffer_free(&buffer);          buffer_free(&buffer);
   
         fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);          buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted));
         if (fd < 0) {  
                 error("open %s failed: %s.", filename, strerror(errno));  
                 buffer_free(&encrypted);  
                 return 0;  
         }  
         if (atomicio(vwrite, fd, buffer_ptr(&encrypted),  
             buffer_len(&encrypted)) != buffer_len(&encrypted)) {  
                 error("write to key file %s failed: %s", filename,  
                     strerror(errno));  
                 buffer_free(&encrypted);  
                 close(fd);  
                 unlink(filename);  
                 return 0;  
         }  
         close(fd);  
         buffer_free(&encrypted);          buffer_free(&encrypted);
   
         return 1;          return 1;
 }  }
   
 /* save SSH v2 key in OpenSSL PEM format */  /* convert SSH v2 key in OpenSSL PEM format */
 static int  static int
 key_save_private_pem(Key *key, const char *filename, const char *_passphrase,  key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase,
     const char *comment)      const char *comment)
 {  {
         FILE *fp;  
         int fd;  
         int success = 0;          int success = 0;
         int len = strlen(_passphrase);          int blen, len = strlen(_passphrase);
         u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;          u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
         const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;          const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
           const u_char *bptr;
           BIO *bio;
   
         if (len > 0 && len <= 4) {          if (len > 0 && len <= 4) {
                 error("passphrase too short: have %d bytes, need > 4", len);                  error("passphrase too short: have %d bytes, need > 4", len);
                 return 0;                  return 0;
         }          }
         fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);          if ((bio = BIO_new(BIO_s_mem())) == NULL) {
         if (fd < 0) {                  error("%s: BIO_new failed", __func__);
                 error("open %s failed: %s.", filename, strerror(errno));  
                 return 0;                  return 0;
         }          }
         fp = fdopen(fd, "w");  
         if (fp == NULL) {  
                 error("fdopen %s failed: %s.", filename, strerror(errno));  
                 close(fd);  
                 return 0;  
         }  
         switch (key->type) {          switch (key->type) {
         case KEY_DSA:          case KEY_DSA:
                 success = PEM_write_DSAPrivateKey(fp, key->dsa,                  success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
                     cipher, passphrase, len, NULL, NULL);                      cipher, passphrase, len, NULL, NULL);
                 break;                  break;
         case KEY_ECDSA:          case KEY_ECDSA:
                 success = PEM_write_ECPrivateKey(fp, key->ecdsa,                  success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
                     cipher, passphrase, len, NULL, NULL);                      cipher, passphrase, len, NULL, NULL);
                 break;                  break;
         case KEY_RSA:          case KEY_RSA:
                 success = PEM_write_RSAPrivateKey(fp, key->rsa,                  success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
                     cipher, passphrase, len, NULL, NULL);                      cipher, passphrase, len, NULL, NULL);
                 break;                  break;
         }          }
         fclose(fp);          if (success) {
                   if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
                           success = 0;
                   else
                           buffer_append(blob, bptr, blen);
           }
           BIO_free(bio);
         return success;          return success;
 }  }
   
 int  /* Save a key blob to a file */
 key_save_private(Key *key, const char *filename, const char *passphrase,  static int
   key_save_private_blob(Buffer *keybuf, const char *filename)
   {
           int fd;
   
           if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
                   error("open %s failed: %s.", filename, strerror(errno));
                   return 0;
           }
           if (atomicio(vwrite, fd, buffer_ptr(keybuf),
               buffer_len(keybuf)) != buffer_len(keybuf)) {
                   error("write to key file %s failed: %s", filename,
                       strerror(errno));
                   close(fd);
                   unlink(filename);
                   return 0;
           }
           close(fd);
           return 1;
   }
   
   /* Serialise "key" to buffer "blob" */
   static int
   key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
     const char *comment)      const char *comment)
 {  {
         switch (key->type) {          switch (key->type) {
         case KEY_RSA1:          case KEY_RSA1:
                 return key_save_private_rsa1(key, filename, passphrase,                  return key_private_rsa1_to_blob(key, blob, passphrase, comment);
                     comment);  
         case KEY_DSA:          case KEY_DSA:
         case KEY_ECDSA:          case KEY_ECDSA:
         case KEY_RSA:          case KEY_RSA:
                 return key_save_private_pem(key, filename, passphrase,                  return key_private_pem_to_blob(key, blob, passphrase, comment);
                     comment);  
         default:          default:
                 break;                  error("%s: cannot save key type %d", __func__, key->type);
                   return 0;
         }          }
         error("key_save_private: cannot save key type %d", key->type);  
         return 0;  
 }  }
   
   int
   key_save_private(Key *key, const char *filename, const char *passphrase,
       const char *comment)
   {
           Buffer keyblob;
           int success = 0;
   
           buffer_init(&keyblob);
           if (!key_private_to_blob(key, &keyblob, passphrase, comment))
                   goto out;
           if (!key_save_private_blob(&keyblob, filename))
                   goto out;
           success = 1;
    out:
           buffer_free(&keyblob);
           return success;
   }
   
 /*  /*
  * Loads the public part of the ssh v1 key file.  Returns NULL if an error was   * Parse the public, unencrypted portion of a RSA1 key.
  * encountered (the file does not exist or is not readable), and the key  
  * otherwise.  
  */   */
   
 static Key *  static Key *
 key_load_public_rsa1(int fd, const char *filename, char **commentp)  key_parse_public_rsa1(Buffer *blob, char **commentp)
 {  {
         Buffer buffer;  
         Key *pub;          Key *pub;
         struct stat st;  
         char *cp;          /* Check that it is at least big enough to contain the ID string. */
         u_int i;          if (buffer_len(blob) < sizeof(authfile_id_string)) {
                   debug3("Truncated RSA1 identifier");
                   return NULL;
           }
   
           /*
            * Make sure it begins with the id string.  Consume the id string
            * from the buffer.
            */
           if (memcmp(buffer_ptr(blob), authfile_id_string,
               sizeof(authfile_id_string)) != 0) {
                   debug3("Incorrect RSA1 identifier");
                   return NULL;
           }
           buffer_consume(blob, sizeof(authfile_id_string));
   
           /* Skip cipher type and reserved data. */
           (void) buffer_get_char(blob);   /* cipher type */
           (void) buffer_get_int(blob);            /* reserved */
   
           /* Read the public key from the buffer. */
           (void) buffer_get_int(blob);
           pub = key_new(KEY_RSA1);
           buffer_get_bignum(blob, pub->rsa->n);
           buffer_get_bignum(blob, pub->rsa->e);
           if (commentp)
                   *commentp = buffer_get_string(blob, NULL);
           /* The encrypted private part is not parsed by this function. */
           buffer_clear(blob);
   
           return pub;
   }
   
   /* Load the contents of a key file into a buffer */
   static int
   key_load_file(int fd, const char *filename, Buffer *blob)
   {
         size_t len;          size_t len;
           u_char *cp;
           struct stat st;
   
         if (fstat(fd, &st) < 0) {          if (fstat(fd, &st) < 0) {
                 error("fstat for key file %.200s failed: %.100s",                  error("%s: fstat of key file %.200s%sfailed: %.100s", __func__,
                     filename, strerror(errno));                      filename == NULL ? "" : filename,
                 return NULL;                      filename == NULL ? "" : " ",
                       strerror(errno));
                   close(fd);
                   return 0;
         }          }
         if (st.st_size > 1*1024*1024) {          if (st.st_size > 1*1024*1024) {
                 error("key file %.200s too large", filename);                  error("%s: key file %.200s%stoo large", __func__,
                 return NULL;                      filename == NULL ? "" : filename,
                       filename == NULL ? "" : " ");
                   close(fd);
                   return 0;
         }          }
         len = (size_t)st.st_size;               /* truncated */          len = (size_t)st.st_size;               /* truncated */
   
         buffer_init(&buffer);          buffer_init(blob);
         cp = buffer_append_space(&buffer, len);          cp = buffer_append_space(blob, len);
   
         if (atomicio(read, fd, cp, len) != len) {          if (atomicio(read, fd, cp, len) != len) {
                 debug("Read from key file %.200s failed: %.100s", filename,                  debug("%s: read from key file %.200s%sfailed: %.100s", __func__,
                       filename == NULL ? "" : filename,
                       filename == NULL ? "" : " ",
                     strerror(errno));                      strerror(errno));
                 buffer_free(&buffer);                  buffer_clear(blob);
                 return NULL;                  close(fd);
                   return 0;
         }          }
           return 1;
   }
   
         /* Check that it is at least big enough to contain the ID string. */  /*
         if (len < sizeof(authfile_id_string)) {   * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
                 debug3("Not a RSA1 key file %.200s.", filename);   * encountered (the file does not exist or is not readable), and the key
    * otherwise.
    */
   static Key *
   key_load_public_rsa1(int fd, const char *filename, char **commentp)
   {
           Buffer buffer;
           Key *pub;
   
           buffer_init(&buffer);
           if (!key_load_file(fd, filename, &buffer)) {
                 buffer_free(&buffer);                  buffer_free(&buffer);
                 return NULL;                  return NULL;
         }          }
         /*  
          * Make sure it begins with the id string.  Consume the id string  
          * from the buffer.  
          */  
         for (i = 0; i < sizeof(authfile_id_string); i++)  
                 if (buffer_get_char(&buffer) != authfile_id_string[i]) {  
                         debug3("Not a RSA1 key file %.200s.", filename);  
                         buffer_free(&buffer);  
                         return NULL;  
                 }  
         /* Skip cipher type and reserved data. */  
         (void) buffer_get_char(&buffer);        /* cipher type */  
         (void) buffer_get_int(&buffer);         /* reserved */  
   
         /* Read the public key from the buffer. */          pub = key_parse_public_rsa1(&buffer, commentp);
         (void) buffer_get_int(&buffer);          if (pub == NULL)
         pub = key_new(KEY_RSA1);                  debug3("Could not load \"%s\" as a RSA1 public key", filename);
         buffer_get_bignum(&buffer, pub->rsa->n);  
         buffer_get_bignum(&buffer, pub->rsa->e);  
         if (commentp)  
                 *commentp = buffer_get_string(&buffer, NULL);  
         /* The encrypted private part is not parsed by this function. */  
   
         buffer_free(&buffer);          buffer_free(&buffer);
         return pub;          return pub;
 }  }
Line 325 
Line 383 
         return NULL;          return NULL;
 }  }
   
 /*  
  * Loads the private key from the file.  Returns 0 if an error is encountered  
  * (file does not exist or is not readable, or passphrase is bad). This  
  * initializes the private key.  
  * Assumes we are called under uid of the owner of the file.  
  */  
   
 static Key *  static Key *
 key_load_private_rsa1(int fd, const char *filename, const char *passphrase,  key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
     char **commentp)  
 {  {
         u_int i;  
         int check1, check2, cipher_type;          int check1, check2, cipher_type;
         size_t len;          Buffer decrypted;
         Buffer buffer, decrypted;  
         u_char *cp;          u_char *cp;
         CipherContext ciphercontext;          CipherContext ciphercontext;
         Cipher *cipher;          Cipher *cipher;
         Key *prv = NULL;          Key *prv = NULL;
         struct stat st;  
   
         if (fstat(fd, &st) < 0) {  
                 error("fstat for key file %.200s failed: %.100s",  
                     filename, strerror(errno));  
                 close(fd);  
                 return NULL;  
         }  
         if (st.st_size > 1*1024*1024) {  
                 error("key file %.200s too large", filename);  
                 close(fd);  
                 return (NULL);  
         }  
         len = (size_t)st.st_size;               /* truncated */  
   
         buffer_init(&buffer);  
         cp = buffer_append_space(&buffer, len);  
   
         if (atomicio(read, fd, cp, len) != len) {  
                 debug("Read from key file %.200s failed: %.100s", filename,  
                     strerror(errno));  
                 buffer_free(&buffer);  
                 close(fd);  
                 return NULL;  
         }  
   
         /* Check that it is at least big enough to contain the ID string. */          /* Check that it is at least big enough to contain the ID string. */
         if (len < sizeof(authfile_id_string)) {          if (buffer_len(blob) < sizeof(authfile_id_string)) {
                 debug3("Not a RSA1 key file %.200s.", filename);                  debug3("Truncated RSA1 identifier");
                 buffer_free(&buffer);  
                 close(fd);  
                 return NULL;                  return NULL;
         }          }
   
         /*          /*
          * Make sure it begins with the id string.  Consume the id string           * Make sure it begins with the id string.  Consume the id string
          * from the buffer.           * from the buffer.
          */           */
         for (i = 0; i < sizeof(authfile_id_string); i++)          if (memcmp(buffer_ptr(blob), authfile_id_string,
                 if (buffer_get_char(&buffer) != authfile_id_string[i]) {              sizeof(authfile_id_string)) != 0) {
                         debug3("Not a RSA1 key file %.200s.", filename);                  debug3("Incorrect RSA1 identifier");
                         buffer_free(&buffer);                  return NULL;
                         close(fd);          }
                         return NULL;          buffer_consume(blob, sizeof(authfile_id_string));
                 }  
   
         /* Read cipher type. */          /* Read cipher type. */
         cipher_type = buffer_get_char(&buffer);          cipher_type = buffer_get_char(blob);
         (void) buffer_get_int(&buffer); /* Reserved data. */          (void) buffer_get_int(blob);    /* Reserved data. */
   
         /* Read the public key from the buffer. */          /* Read the public key from the buffer. */
         (void) buffer_get_int(&buffer);          (void) buffer_get_int(blob);
         prv = key_new_private(KEY_RSA1);          prv = key_new_private(KEY_RSA1);
   
         buffer_get_bignum(&buffer, prv->rsa->n);          buffer_get_bignum(blob, prv->rsa->n);
         buffer_get_bignum(&buffer, prv->rsa->e);          buffer_get_bignum(blob, prv->rsa->e);
         if (commentp)          if (commentp)
                 *commentp = buffer_get_string(&buffer, NULL);                  *commentp = buffer_get_string(blob, NULL);
         else          else
                 xfree(buffer_get_string(&buffer, NULL));                  (void)buffer_get_string_ptr(blob, NULL);
   
         /* Check that it is a supported cipher. */          /* Check that it is a supported cipher. */
         cipher = cipher_by_number(cipher_type);          cipher = cipher_by_number(cipher_type);
         if (cipher == NULL) {          if (cipher == NULL) {
                 debug("Unsupported cipher %d used in key file %.200s.",                  debug("Unsupported RSA1 cipher %d", cipher_type);
                     cipher_type, filename);  
                 buffer_free(&buffer);  
                 goto fail;                  goto fail;
         }          }
         /* Initialize space for decrypted data. */          /* Initialize space for decrypted data. */
         buffer_init(&decrypted);          buffer_init(&decrypted);
         cp = buffer_append_space(&decrypted, buffer_len(&buffer));          cp = buffer_append_space(&decrypted, buffer_len(blob));
   
         /* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */          /* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
         cipher_set_key_string(&ciphercontext, cipher, passphrase,          cipher_set_key_string(&ciphercontext, cipher, passphrase,
             CIPHER_DECRYPT);              CIPHER_DECRYPT);
         cipher_crypt(&ciphercontext, cp,          cipher_crypt(&ciphercontext, cp,
             buffer_ptr(&buffer), buffer_len(&buffer));              buffer_ptr(blob), buffer_len(blob));
         cipher_cleanup(&ciphercontext);          cipher_cleanup(&ciphercontext);
         memset(&ciphercontext, 0, sizeof(ciphercontext));          memset(&ciphercontext, 0, sizeof(ciphercontext));
         buffer_free(&buffer);          buffer_clear(blob);
   
         check1 = buffer_get_char(&decrypted);          check1 = buffer_get_char(&decrypted);
         check2 = buffer_get_char(&decrypted);          check2 = buffer_get_char(&decrypted);
         if (check1 != buffer_get_char(&decrypted) ||          if (check1 != buffer_get_char(&decrypted) ||
             check2 != buffer_get_char(&decrypted)) {              check2 != buffer_get_char(&decrypted)) {
                 if (strcmp(passphrase, "") != 0)                  if (strcmp(passphrase, "") != 0)
                         debug("Bad passphrase supplied for key file %.200s.",                          debug("Bad passphrase supplied for RSA1 key");
                             filename);  
                 /* Bad passphrase. */                  /* Bad passphrase. */
                 buffer_free(&decrypted);                  buffer_free(&decrypted);
                 goto fail;                  goto fail;
Line 450 
Line 468 
   
         /* enable blinding */          /* enable blinding */
         if (RSA_blinding_on(prv->rsa, NULL) != 1) {          if (RSA_blinding_on(prv->rsa, NULL) != 1) {
                 error("key_load_private_rsa1: RSA_blinding_on failed");                  error("%s: RSA_blinding_on failed", __func__);
                 goto fail;                  goto fail;
         }          }
         close(fd);  
         return prv;          return prv;
   
 fail:  fail:
         if (commentp)          if (commentp)
                 xfree(*commentp);                  xfree(*commentp);
         close(fd);  
         key_free(prv);          key_free(prv);
         return NULL;          return NULL;
 }  }
   
 Key *  static Key *
 key_load_private_pem(int fd, int type, const char *passphrase,  key_parse_private_pem(Buffer *blob, int type, const char *passphrase,
     char **commentp)      char **commentp)
 {  {
         FILE *fp;  
         EVP_PKEY *pk = NULL;          EVP_PKEY *pk = NULL;
         Key *prv = NULL;          Key *prv = NULL;
         char *name = "<no key>";          char *name = "<no key>";
           BIO *bio;
   
         fp = fdopen(fd, "r");          if ((bio = BIO_new_mem_buf(buffer_ptr(blob),
         if (fp == NULL) {              buffer_len(blob))) == NULL) {
                 error("fdopen failed: %s", strerror(errno));                  error("%s: BIO_new_mem_buf failed", __func__);
                 close(fd);  
                 return NULL;                  return NULL;
         }          }
         pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);  
           pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase);
           BIO_free(bio);
         if (pk == NULL) {          if (pk == NULL) {
                 debug("PEM_read_PrivateKey failed");                  debug("%s: PEM_read_PrivateKey failed", __func__);
                 (void)ERR_get_error();                  (void)ERR_get_error();
         } else if (pk->type == EVP_PKEY_RSA &&          } else if (pk->type == EVP_PKEY_RSA &&
             (type == KEY_UNSPEC||type==KEY_RSA)) {              (type == KEY_UNSPEC||type==KEY_RSA)) {
Line 493 
Line 510 
                 RSA_print_fp(stderr, prv->rsa, 8);                  RSA_print_fp(stderr, prv->rsa, 8);
 #endif  #endif
                 if (RSA_blinding_on(prv->rsa, NULL) != 1) {                  if (RSA_blinding_on(prv->rsa, NULL) != 1) {
                         error("key_load_private_pem: RSA_blinding_on failed");                          error("%s: RSA_blinding_on failed", __func__);
                         key_free(prv);                          key_free(prv);
                         prv = NULL;                          prv = NULL;
                 }                  }
Line 526 
Line 543 
                         key_dump_ec_key(prv->ecdsa);                          key_dump_ec_key(prv->ecdsa);
 #endif  #endif
         } else {          } else {
                 error("PEM_read_PrivateKey: mismatch or "                  error("%s: PEM_read_PrivateKey: mismatch or "
                     "unknown EVP_PKEY save_type %d", pk->save_type);                      "unknown EVP_PKEY save_type %d", __func__, pk->save_type);
         }          }
         fclose(fp);  
         if (pk != NULL)          if (pk != NULL)
                 EVP_PKEY_free(pk);                  EVP_PKEY_free(pk);
         if (prv != NULL && commentp)          if (prv != NULL && commentp)
Line 539 
Line 555 
         return prv;          return prv;
 }  }
   
   Key *
   key_load_private_pem(int fd, int type, const char *passphrase,
       char **commentp)
   {
           Buffer buffer;
           Key *prv;
   
           buffer_init(&buffer);
           if (!key_load_file(fd, NULL, &buffer)) {
                   buffer_free(&buffer);
                   return NULL;
           }
           prv = key_parse_private_pem(&buffer, type, passphrase, commentp);
           buffer_free(&buffer);
           return prv;
   }
   
 int  int
 key_perm_ok(int fd, const char *filename)  key_perm_ok(int fd, const char *filename)
 {  {
Line 564 
Line 597 
         return 1;          return 1;
 }  }
   
   static Key *
   key_parse_private_type(Buffer *blob, int type, const char *passphrase,
       char **commentp)
   {
           switch (type) {
           case KEY_RSA1:
                   return key_parse_private_rsa1(blob, passphrase, commentp);
           case KEY_DSA:
           case KEY_ECDSA:
           case KEY_RSA:
           case KEY_UNSPEC:
                   return key_parse_private_pem(blob, type, passphrase, commentp);
           default:
                   break;
           }
           return NULL;
   }
   
 Key *  Key *
 key_load_private_type(int type, const char *filename, const char *passphrase,  key_load_private_type(int type, const char *filename, const char *passphrase,
     char **commentp, int *perm_ok)      char **commentp, int *perm_ok)
 {  {
         int fd;          int fd;
           Key *ret;
           Buffer buffer;
   
         fd = open(filename, O_RDONLY);          fd = open(filename, O_RDONLY);
         if (fd < 0) {          if (fd < 0) {
Line 587 
Line 640 
         }          }
         if (perm_ok != NULL)          if (perm_ok != NULL)
                 *perm_ok = 1;                  *perm_ok = 1;
         switch (type) {  
         case KEY_RSA1:          buffer_init(&buffer);
                 return key_load_private_rsa1(fd, filename, passphrase,          if (!key_load_file(fd, filename, &buffer)) {
                     commentp);                  buffer_free(&buffer);
                 /* closes fd */  
         case KEY_DSA:  
         case KEY_ECDSA:  
         case KEY_RSA:  
         case KEY_UNSPEC:  
                 return key_load_private_pem(fd, type, passphrase, commentp);  
                 /* closes fd */  
         default:  
                 close(fd);                  close(fd);
                 break;                  return NULL;
         }          }
         return NULL;          close(fd);
           ret = key_parse_private_type(&buffer, type, passphrase, commentp);
           buffer_free(&buffer);
           return ret;
 }  }
   
 Key *  Key *
Line 610 
Line 658 
     char **commentp)      char **commentp)
 {  {
         Key *pub, *prv;          Key *pub, *prv;
           Buffer buffer, pubcopy;
         int fd;          int fd;
   
         fd = open(filename, O_RDONLY);          fd = open(filename, O_RDONLY);
Line 623 
Line 672 
                 close(fd);                  close(fd);
                 return NULL;                  return NULL;
         }          }
         pub = key_load_public_rsa1(fd, filename, commentp);  
         lseek(fd, (off_t) 0, SEEK_SET);         /* rewind */          buffer_init(&buffer);
           if (!key_load_file(fd, filename, &buffer)) {
                   buffer_free(&buffer);
                   close(fd);
                   return NULL;
           }
           close(fd);
   
           buffer_init(&pubcopy);
           buffer_append(&pubcopy, buffer_ptr(&buffer), buffer_len(&buffer));
           /* it's a SSH v1 key if the public key part is readable */
           pub = key_parse_public_rsa1(&pubcopy, commentp);
           buffer_free(&pubcopy);
         if (pub == NULL) {          if (pub == NULL) {
                 /* closes fd */                  prv = key_parse_private_type(&buffer, KEY_UNSPEC,
                 prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);                      passphrase, NULL);
                 /* use the filename as a comment for PEM */                  /* use the filename as a comment for PEM */
                 if (commentp && prv)                  if (commentp && prv)
                         *commentp = xstrdup(filename);                          *commentp = xstrdup(filename);
         } else {          } else {
                 /* it's a SSH v1 key if the public key part is readable */  
                 key_free(pub);                  key_free(pub);
                 /* closes fd */                  prv = key_parse_private_type(&buffer, KEY_RSA1, passphrase,
                 prv = key_load_private_rsa1(fd, filename, passphrase, NULL);                      commentp);
         }          }
           buffer_free(&buffer);
         return prv;          return prv;
 }  }
   

Legend:
Removed from v.1.85  
changed lines
  Added in v.1.86