[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.28 and 1.29

version 1.28, 2001/02/21 09:05:54 version 1.29, 2001/03/26 08:07:07
Line 51 
Line 51 
 #include "log.h"  #include "log.h"
 #include "authfile.h"  #include "authfile.h"
   
 /* Version identification string for identity files. */  /* Version identification string for SSH v1 identity files. */
 static const char authfile_id_string[] =  static const char authfile_id_string[] =
     "SSH PRIVATE KEY FILE FORMAT 1.1\n";      "SSH PRIVATE KEY FILE FORMAT 1.1\n";
   
Line 63 
Line 63 
  */   */
   
 int  int
 save_private_key_rsa1(const char *filename, const char *passphrase,  key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
     RSA *key, const char *comment)      const char *comment)
 {  {
         Buffer buffer, encrypted;          Buffer buffer, encrypted;
         char buf[100], *cp;          char buf[100], *cp;
Line 100 
Line 100 
          * will be stored in plain text, and storing them also in encrypted           * will be stored in plain text, and storing them also in encrypted
          * format would just give known plaintext).           * format would just give known plaintext).
          */           */
         buffer_put_bignum(&buffer, key->d);          buffer_put_bignum(&buffer, key->rsa->d);
         buffer_put_bignum(&buffer, key->iqmp);          buffer_put_bignum(&buffer, key->rsa->iqmp);
         buffer_put_bignum(&buffer, key->q);     /* reverse from SSL p */          buffer_put_bignum(&buffer, key->rsa->q);        /* reverse from SSL p */
         buffer_put_bignum(&buffer, key->p);     /* reverse from SSL q */          buffer_put_bignum(&buffer, key->rsa->p);        /* reverse from SSL q */
   
         /* Pad the part to be encrypted until its size is a multiple of 8. */          /* Pad the part to be encrypted until its size is a multiple of 8. */
         while (buffer_len(&buffer) % 8 != 0)          while (buffer_len(&buffer) % 8 != 0)
Line 122 
Line 122 
         buffer_put_int(&encrypted, 0);  /* For future extension */          buffer_put_int(&encrypted, 0);  /* For future extension */
   
         /* Store public key.  This will be in plain text. */          /* Store public key.  This will be in plain text. */
         buffer_put_int(&encrypted, BN_num_bits(key->n));          buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
         buffer_put_bignum(&encrypted, key->n);          buffer_put_bignum(&encrypted, key->rsa->n);
         buffer_put_bignum(&encrypted, key->e);          buffer_put_bignum(&encrypted, key->rsa->e);
         buffer_put_string(&encrypted, comment, strlen(comment));          buffer_put_string(&encrypted, comment, strlen(comment));
   
         /* Allocate space for the private part of the key in the buffer. */          /* Allocate space for the private part of the key in the buffer. */
Line 156 
Line 156 
         return 1;          return 1;
 }  }
   
 /* save SSH2 key in OpenSSL PEM format */  /* save SSH v2 key in OpenSSL PEM format */
 int  int
 save_private_key_ssh2(const char *filename, const char *_passphrase,  key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
     Key *key, const char *comment)      const char *comment)
 {  {
         FILE *fp;          FILE *fp;
         int fd;          int fd;
Line 199 
Line 199 
 }  }
   
 int  int
 save_private_key(const char *filename, const char *passphrase, Key *key,  key_save_private(Key *key, const char *filename, const char *passphrase,
     const char *comment)      const char *comment)
 {  {
         switch (key->type) {          switch (key->type) {
         case KEY_RSA1:          case KEY_RSA1:
                 return save_private_key_rsa1(filename, passphrase, key->rsa, comment);                  return key_save_private_rsa1(key, filename, passphrase,
                       comment);
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
         case KEY_RSA:          case KEY_RSA:
                 return save_private_key_ssh2(filename, passphrase, key, comment);                  return key_save_private_pem(key, filename, passphrase,
                       comment);
                 break;                  break;
         default:          default:
                 break;                  break;
Line 217 
Line 219 
 }  }
   
 /*  /*
  * Loads the public part of the key file.  Returns 0 if an error was   * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
  * encountered (the file does not exist or is not readable), and non-zero   * encountered (the file does not exist or is not readable), and the key
  * otherwise.   * otherwise.
  */   */
   
 int  Key *
 load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)  key_load_public_rsa1(int fd, const char *filename, char **commentp)
 {  {
         int fd, i;  
         off_t len;  
         Buffer buffer;          Buffer buffer;
           Key *pub;
         char *cp;          char *cp;
           int i;
           off_t len;
   
         fd = open(filename, O_RDONLY);  
         if (fd < 0)  
                 return 0;  
         len = lseek(fd, (off_t) 0, SEEK_END);          len = lseek(fd, (off_t) 0, SEEK_END);
         lseek(fd, (off_t) 0, SEEK_SET);          lseek(fd, (off_t) 0, SEEK_SET);
   
Line 243 
Line 243 
                 debug("Read from key file %.200s failed: %.100s", filename,                  debug("Read from key file %.200s failed: %.100s", filename,
                     strerror(errno));                      strerror(errno));
                 buffer_free(&buffer);                  buffer_free(&buffer);
                 close(fd);                  return NULL;
                 return 0;  
         }          }
         close(fd);  
   
         /* 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 (len < sizeof(authfile_id_string)) {
                 debug3("Bad RSA1 key file %.200s.", filename);                  debug3("Bad RSA1 key file %.200s.", filename);
                 buffer_free(&buffer);                  buffer_free(&buffer);
                 return 0;                  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
Line 262 
Line 260 
                 if (buffer_get_char(&buffer) != authfile_id_string[i]) {                  if (buffer_get_char(&buffer) != authfile_id_string[i]) {
                         debug3("Bad RSA1 key file %.200s.", filename);                          debug3("Bad RSA1 key file %.200s.", filename);
                         buffer_free(&buffer);                          buffer_free(&buffer);
                         return 0;                          return NULL;
                 }                  }
         /* Skip cipher type and reserved data. */          /* Skip cipher type and reserved data. */
         (void) buffer_get_char(&buffer);        /* cipher type */          (void) buffer_get_char(&buffer);        /* cipher type */
Line 270 
Line 268 
   
         /* Read the public key from the buffer. */          /* Read the public key from the buffer. */
         buffer_get_int(&buffer);          buffer_get_int(&buffer);
         /* XXX alloc */          pub = key_new(KEY_RSA1);
         if (pub->n == NULL)          buffer_get_bignum(&buffer, pub->rsa->n);
                 pub->n = BN_new();          buffer_get_bignum(&buffer, pub->rsa->e);
         buffer_get_bignum(&buffer, pub->n);          if (commentp)
         /* XXX alloc */                  *commentp = buffer_get_string(&buffer, NULL);
         if (pub->e == NULL)  
                 pub->e = BN_new();  
         buffer_get_bignum(&buffer, pub->e);  
         if (comment_return)  
                 *comment_return = buffer_get_string(&buffer, NULL);  
         /* The encrypted private part is not parsed by this function. */          /* The encrypted private part is not parsed by this function. */
   
         buffer_free(&buffer);          buffer_free(&buffer);
           return pub;
         return 1;  
 }  }
   
 /* load public key from private-key file */  /* load public key from private-key file, works only for SSH v1 */
 int  Key *
 load_public_key(const char *filename, Key * key, char **comment_return)  key_load_public_type(int type, const char *filename, char **commentp)
 {  {
         switch (key->type) {          Key *pub;
         case KEY_RSA1:          int fd;
                 return load_public_key_rsa(filename, key->rsa, comment_return);  
                 break;          if (type == KEY_RSA1) {
         case KEY_DSA:                  fd = open(filename, O_RDONLY);
         case KEY_RSA:                  if (fd < 0)
         default:                          return NULL;
                 break;                  pub = key_load_public_rsa1(fd, filename, commentp);
                   close(fd);
                   return pub;
         }          }
         return 0;          return NULL;
 }  }
   
 /*  /*
Line 310 
Line 304 
  * Assumes we are called under uid of the owner of the file.   * Assumes we are called under uid of the owner of the file.
  */   */
   
 int  Key *
 load_private_key_rsa1(int fd, const char *filename,  key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
     const char *passphrase, RSA * prv, char **comment_return)      char **commentp)
 {  {
         int i, check1, check2, cipher_type;          int i, check1, check2, cipher_type;
         off_t len;          off_t len;
Line 322 
Line 316 
         Cipher *cipher;          Cipher *cipher;
         BN_CTX *ctx;          BN_CTX *ctx;
         BIGNUM *aux;          BIGNUM *aux;
           Key *prv = NULL;
   
         len = lseek(fd, (off_t) 0, SEEK_END);          len = lseek(fd, (off_t) 0, SEEK_END);
         lseek(fd, (off_t) 0, SEEK_SET);          lseek(fd, (off_t) 0, SEEK_SET);
Line 334 
Line 329 
                     strerror(errno));                      strerror(errno));
                 buffer_free(&buffer);                  buffer_free(&buffer);
                 close(fd);                  close(fd);
                 return 0;                  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. */
Line 342 
Line 337 
                 debug3("Bad RSA1 key file %.200s.", filename);                  debug3("Bad RSA1 key file %.200s.", filename);
                 buffer_free(&buffer);                  buffer_free(&buffer);
                 close(fd);                  close(fd);
                 return 0;                  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
Line 353 
Line 348 
                         debug3("Bad RSA1 key file %.200s.", filename);                          debug3("Bad RSA1 key file %.200s.", filename);
                         buffer_free(&buffer);                          buffer_free(&buffer);
                         close(fd);                          close(fd);
                         return 0;                          return NULL;
                 }                  }
   
         /* Read cipher type. */          /* Read cipher type. */
Line 362 
Line 357 
   
         /* Read the public key from the buffer. */          /* Read the public key from the buffer. */
         buffer_get_int(&buffer);          buffer_get_int(&buffer);
         prv->n = BN_new();          prv = key_new_private(KEY_RSA1);
         buffer_get_bignum(&buffer, prv->n);  
         prv->e = BN_new();          buffer_get_bignum(&buffer, prv->rsa->n);
         buffer_get_bignum(&buffer, prv->e);          buffer_get_bignum(&buffer, prv->rsa->e);
         if (comment_return)          if (commentp)
                 *comment_return = buffer_get_string(&buffer, NULL);                  *commentp = buffer_get_string(&buffer, NULL);
         else          else
                 xfree(buffer_get_string(&buffer, NULL));                  xfree(buffer_get_string(&buffer, NULL));
   
Line 395 
Line 390 
         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.", filename);                          debug("Bad passphrase supplied for key file %.200s.",
                               filename);
                 /* Bad passphrase. */                  /* Bad passphrase. */
                 buffer_free(&decrypted);                  buffer_free(&decrypted);
 fail:                  goto fail;
                 BN_clear_free(prv->n);  
                 prv->n = NULL;  
                 BN_clear_free(prv->e);  
                 prv->e = NULL;  
                 if (comment_return)  
                         xfree(*comment_return);  
                 close(fd);  
                 return 0;  
         }          }
         /* Read the rest of the private key. */          /* Read the rest of the private key. */
         prv->d = BN_new();          buffer_get_bignum(&decrypted, prv->rsa->d);
         buffer_get_bignum(&decrypted, prv->d);          buffer_get_bignum(&decrypted, prv->rsa->iqmp);          /* u */
         prv->iqmp = BN_new();          /* in SSL and SSH v1 p and q are exchanged */
         buffer_get_bignum(&decrypted, prv->iqmp);       /* u */          buffer_get_bignum(&decrypted, prv->rsa->q);             /* p */
         /* in SSL and SSH p and q are exchanged */          buffer_get_bignum(&decrypted, prv->rsa->p);             /* q */
         prv->q = BN_new();  
         buffer_get_bignum(&decrypted, prv->q);          /* p */  
         prv->p = BN_new();  
         buffer_get_bignum(&decrypted, prv->p);          /* q */  
   
           /* calculate p-1 and q-1 */
         ctx = BN_CTX_new();          ctx = BN_CTX_new();
         aux = BN_new();          aux = BN_new();
   
         BN_sub(aux, prv->q, BN_value_one());          BN_sub(aux, prv->rsa->q, BN_value_one());
         prv->dmq1 = BN_new();          BN_mod(prv->rsa->dmq1, prv->rsa->d, aux, ctx);
         BN_mod(prv->dmq1, prv->d, aux, ctx);  
   
         BN_sub(aux, prv->p, BN_value_one());          BN_sub(aux, prv->rsa->p, BN_value_one());
         prv->dmp1 = BN_new();          BN_mod(prv->rsa->dmp1, prv->rsa->d, aux, ctx);
         BN_mod(prv->dmp1, prv->d, aux, ctx);  
   
         BN_clear_free(aux);          BN_clear_free(aux);
         BN_CTX_free(ctx);          BN_CTX_free(ctx);
   
         buffer_free(&decrypted);          buffer_free(&decrypted);
         close(fd);          close(fd);
         return 1;          return prv;
   
   fail:
           if (commentp)
                   xfree(*commentp);
           close(fd);
           key_free(prv);
           return NULL;
 }  }
   
 int  Key *
 load_private_key_ssh2(int fd, const char *passphrase, Key *k, char **comment_return)  key_load_private_pem(int fd, int type, const char *passphrase,
       char **commentp)
 {  {
         FILE *fp;          FILE *fp;
         int success = 0;  
         EVP_PKEY *pk = NULL;          EVP_PKEY *pk = NULL;
           Key *prv = NULL;
         char *name = "<no key>";          char *name = "<no key>";
   
         fp = fdopen(fd, "r");          fp = fdopen(fd, "r");
         if (fp == NULL) {          if (fp == NULL) {
                 error("fdopen failed");                  error("fdopen failed");
                 close(fd);                  close(fd);
                 return 0;                  return NULL;
         }          }
         pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);          pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
         if (pk == NULL) {          if (pk == NULL) {
                 debug("PEM_read_PrivateKey failed");                  debug("PEM_read_PrivateKey failed");
                 (void)ERR_get_error();                  (void)ERR_get_error();
         } else if (pk->type == EVP_PKEY_RSA) {          } else if (pk->type == EVP_PKEY_RSA &&
                 /* replace k->rsa with loaded key */               (type == KEY_UNSPEC||type==KEY_RSA)) {
                 if (k->type == KEY_RSA || k->type == KEY_UNSPEC) {                  prv = key_new(KEY_UNSPEC);
                         if (k->rsa != NULL)                  prv->rsa = EVP_PKEY_get1_RSA(pk);
                                 RSA_free(k->rsa);                  prv->type = KEY_RSA;
                         k->rsa = EVP_PKEY_get1_RSA(pk);                  name = "rsa w/o comment";
                         k->type = KEY_RSA;  
                         name = "rsa w/o comment";  
                         success = 1;  
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                         RSA_print_fp(stderr, k->rsa, 8);                  RSA_print_fp(stderr, prv->rsa, 8);
 #endif  #endif
                 }          } else if (pk->type == EVP_PKEY_DSA &&
         } else if (pk->type == EVP_PKEY_DSA) {               (type == KEY_UNSPEC||type==KEY_DSA)) {
                 /* replace k->dsa with loaded key */                  prv = key_new(KEY_UNSPEC);
                 if (k->type == KEY_DSA || k->type == KEY_UNSPEC) {                  prv->dsa = EVP_PKEY_get1_DSA(pk);
                         if (k->dsa != NULL)                  prv->type = KEY_DSA;
                                 DSA_free(k->dsa);                  name = "dsa w/o comment";
                         k->dsa = EVP_PKEY_get1_DSA(pk);  
                         k->type = KEY_DSA;  
                         name = "dsa w/o comment";  
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                         DSA_print_fp(stderr, k->dsa, 8);                  DSA_print_fp(stderr, prv->dsa, 8);
 #endif  #endif
                         success = 1;  
                 }  
         } else {          } else {
                 error("PEM_read_PrivateKey: mismatch or "                  error("PEM_read_PrivateKey: mismatch or "
                     "unknown EVP_PKEY save_type %d", pk->save_type);                      "unknown EVP_PKEY save_type %d", pk->save_type);
Line 489 
Line 472 
         fclose(fp);          fclose(fp);
         if (pk != NULL)          if (pk != NULL)
                 EVP_PKEY_free(pk);                  EVP_PKEY_free(pk);
         if (success && comment_return)          if (prv != NULL && commentp)
                 *comment_return = xstrdup(name);                  *commentp = xstrdup(name);
         debug("read SSH2 private key done: name %s success %d", name, success);          debug("read PEM private key done: type %s",
         return success;              prv ? key_type(prv) : "<unknown>");
           return prv;
 }  }
   
 int  int
 load_private_key(const char *filename, const char *passphrase, Key *key,  key_perm_ok(int fd, const char *filename)
     char **comment_return)  
 {  {
         int fd;  
         int ret = 0;  
         struct stat st;          struct stat st;
   
         fd = open(filename, O_RDONLY);  
         if (fd < 0)  
                 return 0;  
   
         /* check owner and modes */          /* check owner and modes */
         if (fstat(fd, &st) < 0 ||          if (fstat(fd, &st) < 0 ||
             (st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) ||              (st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) ||
Line 518 
Line 495 
                 error("Bad ownership or mode(0%3.3o) for '%s'.",                  error("Bad ownership or mode(0%3.3o) for '%s'.",
                     st.st_mode & 0777, filename);                      st.st_mode & 0777, filename);
                 error("It is recommended that your private key files are NOT accessible by others.");                  error("It is recommended that your private key files are NOT accessible by others.");
                   error("This private key will be ignored.");
                 return 0;                  return 0;
         }          }
         switch (key->type) {          return 1;
         case KEY_RSA1:  }
                 if (key->rsa->e != NULL) {  
                         BN_clear_free(key->rsa->e);  
                         key->rsa->e = NULL;  
                 }  
                 if (key->rsa->n != NULL) {  
                         BN_clear_free(key->rsa->n);  
                         key->rsa->n = NULL;  
                 }  
                 ret = load_private_key_rsa1(fd, filename, passphrase,  
                     key->rsa, comment_return);          /* closes fd */  
   
   Key *
   key_load_private_type(int type, const char *filename, const char *passphrase,
       char **commentp)
   {
           int fd;
   
           fd = open(filename, O_RDONLY);
           if (fd < 0)
                   return NULL;
           if (!key_perm_ok(fd, filename)) {
                   debug("bad permissions: ignore key: %s", filename);
                   close(fd);
                   return NULL;
           }
           switch (type) {
           case KEY_RSA1:
                   return key_load_private_rsa1(fd, filename, passphrase,
                       commentp);
                   /* closes fd */
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
         case KEY_RSA:          case KEY_RSA:
         case KEY_UNSPEC:          case KEY_UNSPEC:
                 ret = load_private_key_ssh2(fd, passphrase, key,                  return key_load_private_pem(fd, type, passphrase, commentp);
                     comment_return);                    /* closes fd */                  /* closes fd */
                 break;                  break;
         default:          default:
                 close(fd);                  close(fd);
                 break;                  break;
         }          }
         return ret;          return NULL;
 }  }
   
   Key *
   key_load_private(const char *filename, const char *passphrase,
       char **commentp)
   {
           Key *pub;
           int fd;
   
           fd = open(filename, O_RDONLY);
           if (fd < 0)
                   return NULL;
           if (!key_perm_ok(fd, filename)) {
                   debug("bad permissions: ignore key: %s", filename);
                   close(fd);
                   return NULL;
           }
           pub = key_load_public_rsa1(fd, filename, commentp);
           lseek(fd, (off_t) 0, SEEK_SET);         /* rewind */
           if (pub == NULL) {
                   /* closes fd */
                   return key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
           } else {
                   /* it's a SSH v1 key if the public key part is readable */
                   key_free(pub);
                   /* closes fd */
                   return key_load_private_rsa1(fd, filename, passphrase, NULL);
           }
   }
   
 int  int
 do_load_public_key(const char *filename, Key *k, char **commentp)  key_try_load_public(Key *k, const char *filename, char **commentp)
 {  {
         FILE *f;          FILE *f;
         char line[1024];          char line[4096];
         char *cp;          char *cp;
   
         f = fopen(filename, "r");          f = fopen(filename, "r");
Line 582 
Line 597 
         return 0;          return 0;
 }  }
   
 /* load public key from pubkey file */  /* load public key from ssh v1 private or any pubkey file */
 int  Key *
 try_load_public_key(const char *filename, Key *k, char **commentp)  key_load_public(const char *filename, char **commentp)
 {  {
         char pub[MAXPATHLEN];          Key *pub;
           char file[MAXPATHLEN];
   
         if (do_load_public_key(filename, k, commentp) == 1)          pub = key_load_public_type(KEY_RSA1, filename, commentp);
                 return 1;          if (pub != NULL)
         if (strlcpy(pub, filename, sizeof pub) >= MAXPATHLEN)                  return pub;
                 return 0;          pub = key_new(KEY_UNSPEC);
         if (strlcat(pub, ".pub", sizeof pub) >= MAXPATHLEN)          if (key_try_load_public(pub, filename, commentp) == 1)
                 return 0;                  return pub;
         if (do_load_public_key(pub, k, commentp) == 1)          if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
                 return 1;              (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
         return 0;              (key_try_load_public(pub, file, commentp) == 1))
                   return pub;
           key_free(pub);
           return NULL;
 }  }

Legend:
Removed from v.1.28  
changed lines
  Added in v.1.29