=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/authfile.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- src/usr.bin/ssh/authfile.c 1999/10/11 20:00:35 1.7 +++ src/usr.bin/ssh/authfile.c 1999/11/23 22:25:52 1.8 @@ -15,7 +15,7 @@ */ #include "includes.h" -RCSID("$Id: authfile.c,v 1.7 1999/10/11 20:00:35 markus Exp $"); +RCSID("$Id: authfile.c,v 1.8 1999/11/23 22:25:52 markus Exp $"); #include #include "xmalloc.h" @@ -36,93 +36,93 @@ save_private_key(const char *filename, const char *passphrase, RSA *key, const char *comment) { - Buffer buffer, encrypted; - char buf[100], *cp; - int f, i; - CipherContext cipher; - int cipher_type; - u_int32_t rand; + Buffer buffer, encrypted; + char buf[100], *cp; + int f, i; + CipherContext cipher; + int cipher_type; + u_int32_t rand; - /* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to - another cipher; otherwise use SSH_AUTHFILE_CIPHER. */ - if (strcmp(passphrase, "") == 0) - cipher_type = SSH_CIPHER_NONE; - else - cipher_type = SSH_AUTHFILE_CIPHER; + /* If the passphrase is empty, use SSH_CIPHER_NONE to ease + converting to another cipher; otherwise use + SSH_AUTHFILE_CIPHER. */ + if (strcmp(passphrase, "") == 0) + cipher_type = SSH_CIPHER_NONE; + else + cipher_type = SSH_AUTHFILE_CIPHER; - /* This buffer is used to built the secret part of the private key. */ - buffer_init(&buffer); - - /* Put checkbytes for checking passphrase validity. */ - rand = arc4random(); - buf[0] = rand & 0xff; - buf[1] = (rand >> 8) & 0xff; - buf[2] = buf[0]; - buf[3] = buf[1]; - buffer_append(&buffer, buf, 4); + /* This buffer is used to built the secret part of the private key. */ + buffer_init(&buffer); - /* Store the private key (n and e will not be stored because they will - be stored in plain text, and storing them also in encrypted format - would just give known plaintext). */ - buffer_put_bignum(&buffer, key->d); - buffer_put_bignum(&buffer, key->iqmp); - buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */ - buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */ + /* Put checkbytes for checking passphrase validity. */ + rand = arc4random(); + buf[0] = rand & 0xff; + buf[1] = (rand >> 8) & 0xff; + buf[2] = buf[0]; + buf[3] = buf[1]; + buffer_append(&buffer, buf, 4); - /* Pad the part to be encrypted until its size is a multiple of 8. */ - while (buffer_len(&buffer) % 8 != 0) - buffer_put_char(&buffer, 0); + /* Store the private key (n and e will not be stored because they + will be stored in plain text, and storing them also in + encrypted format would just give known plaintext). */ + buffer_put_bignum(&buffer, key->d); + buffer_put_bignum(&buffer, key->iqmp); + buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */ + buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */ - /* This buffer will be used to contain the data in the file. */ - buffer_init(&encrypted); + /* Pad the part to be encrypted until its size is a multiple of 8. */ + while (buffer_len(&buffer) % 8 != 0) + buffer_put_char(&buffer, 0); - /* First store keyfile id string. */ - cp = AUTHFILE_ID_STRING; - for (i = 0; cp[i]; i++) - buffer_put_char(&encrypted, cp[i]); - buffer_put_char(&encrypted, 0); + /* This buffer will be used to contain the data in the file. */ + buffer_init(&encrypted); - /* Store cipher type. */ - buffer_put_char(&encrypted, cipher_type); - buffer_put_int(&encrypted, 0); /* For future extension */ + /* First store keyfile id string. */ + cp = AUTHFILE_ID_STRING; + for (i = 0; cp[i]; i++) + buffer_put_char(&encrypted, cp[i]); + buffer_put_char(&encrypted, 0); - /* Store public key. This will be in plain text. */ - buffer_put_int(&encrypted, BN_num_bits(key->n)); - buffer_put_bignum(&encrypted, key->n); - buffer_put_bignum(&encrypted, key->e); - buffer_put_string(&encrypted, comment, strlen(comment)); + /* Store cipher type. */ + buffer_put_char(&encrypted, cipher_type); + buffer_put_int(&encrypted, 0); /* For future extension */ - /* Allocate space for the private part of the key in the buffer. */ - buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); + /* Store public key. This will be in plain text. */ + buffer_put_int(&encrypted, BN_num_bits(key->n)); + buffer_put_bignum(&encrypted, key->n); + buffer_put_bignum(&encrypted, key->e); + buffer_put_string(&encrypted, comment, strlen(comment)); - cipher_set_key_string(&cipher, cipher_type, passphrase, 1); - cipher_encrypt(&cipher, (unsigned char *)cp, - (unsigned char *)buffer_ptr(&buffer), - buffer_len(&buffer)); - memset(&cipher, 0, sizeof(cipher)); + /* Allocate space for the private part of the key in the buffer. */ + buffer_append_space(&encrypted, &cp, buffer_len(&buffer)); - /* Destroy temporary data. */ - memset(buf, 0, sizeof(buf)); - buffer_free(&buffer); + cipher_set_key_string(&cipher, cipher_type, passphrase, 1); + cipher_encrypt(&cipher, (unsigned char *) cp, + (unsigned char *) buffer_ptr(&buffer), + buffer_len(&buffer)); + memset(&cipher, 0, sizeof(cipher)); - /* Write to a file. */ - f = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0600); - if (f < 0) - return 0; + /* Destroy temporary data. */ + memset(buf, 0, sizeof(buf)); + buffer_free(&buffer); - if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) != - buffer_len(&encrypted)) - { - debug("Write to key file %.200s failed: %.100s", filename, - strerror(errno)); - buffer_free(&encrypted); - close(f); - remove(filename); - return 0; - } - close(f); - buffer_free(&encrypted); - return 1; + /* Write to a file. */ + f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (f < 0) + return 0; + + if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) != + buffer_len(&encrypted)) { + debug("Write to key file %.200s failed: %.100s", filename, + strerror(errno)); + buffer_free(&encrypted); + close(f); + remove(filename); + return 0; + } + close(f); + buffer_free(&encrypted); + return 1; } /* Loads the public part of the key file. Returns 0 if an error @@ -130,70 +130,65 @@ non-zero otherwise. */ int -load_public_key(const char *filename, RSA *pub, +load_public_key(const char *filename, RSA * pub, char **comment_return) { - int f, i; - off_t len; - Buffer buffer; - char *cp; + int f, i; + off_t len; + Buffer buffer; + char *cp; - /* Read data from the file into the buffer. */ - f = open(filename, O_RDONLY); - if (f < 0) - return 0; + /* Read data from the file into the buffer. */ + f = open(filename, O_RDONLY); + if (f < 0) + return 0; - len = lseek(f, (off_t)0, SEEK_END); - lseek(f, (off_t)0, SEEK_SET); - - buffer_init(&buffer); - buffer_append_space(&buffer, &cp, len); + len = lseek(f, (off_t) 0, SEEK_END); + lseek(f, (off_t) 0, SEEK_SET); - if (read(f, cp, (size_t)len) != (size_t)len) - { - debug("Read from key file %.200s failed: %.100s", filename, - strerror(errno)); - buffer_free(&buffer); - close(f); - return 0; - } - close(f); + buffer_init(&buffer); + buffer_append_space(&buffer, &cp, len); - /* Check that it is at least big enought to contain the ID string. */ - if (len < strlen(AUTHFILE_ID_STRING) + 1) - { - debug("Bad key file %.200s.", filename); - buffer_free(&buffer); - return 0; - } + if (read(f, cp, (size_t) len) != (size_t) len) { + debug("Read from key file %.200s failed: %.100s", filename, + strerror(errno)); + buffer_free(&buffer); + close(f); + return 0; + } + close(f); - /* Make sure it begins with the id string. Consume the id string from - the buffer. */ - for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++) - if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i]) - { - debug("Bad key file %.200s.", filename); - buffer_free(&buffer); - return 0; - } + /* Check that it is at least big enought to contain the ID string. */ + if (len < strlen(AUTHFILE_ID_STRING) + 1) { + debug("Bad key file %.200s.", filename); + buffer_free(&buffer); + return 0; + } + /* Make sure it begins with the id string. Consume the id string + from the buffer. */ + for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) + if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) { + debug("Bad key file %.200s.", filename); + buffer_free(&buffer); + return 0; + } + /* Skip cipher type and reserved data. */ + (void) buffer_get_char(&buffer); /* cipher type */ + (void) buffer_get_int(&buffer); /* reserved */ - /* 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. */ + buffer_get_int(&buffer); + pub->n = BN_new(); + buffer_get_bignum(&buffer, pub->n); + 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. */ - /* Read the public key from the buffer. */ - buffer_get_int(&buffer); - pub->n = BN_new(); - buffer_get_bignum(&buffer, pub->n); - 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. */ + buffer_free(&buffer); - buffer_free(&buffer); - - return 1; + return 1; } /* Loads the private key from the file. Returns 0 if an error is encountered @@ -202,149 +197,139 @@ int load_private_key(const char *filename, const char *passphrase, - RSA *prv, char **comment_return) + RSA * prv, char **comment_return) { - int f, i, check1, check2, cipher_type; - off_t len; - Buffer buffer, decrypted; - char *cp; - CipherContext cipher; - BN_CTX *ctx; - BIGNUM *aux; - struct stat st; + int f, i, check1, check2, cipher_type; + off_t len; + Buffer buffer, decrypted; + char *cp; + CipherContext cipher; + BN_CTX *ctx; + BIGNUM *aux; + struct stat st; - /* Read the file into the buffer. */ - f = open(filename, O_RDONLY); - if (f < 0) - return 0; + /* Read the file into the buffer. */ + f = open(filename, O_RDONLY); + if (f < 0) + return 0; - /* We assume we are called under uid of the owner of the file */ - if (fstat(f, &st) < 0 || - (st.st_uid != 0 && st.st_uid != getuid()) || - (st.st_mode & 077) != 0) { - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("Bad ownership or mode(0%3.3o) for '%s'.", - st.st_mode & 0777, filename); - error("It is recommended that your private key files are NOT accessible by others."); - return 0; - } + /* We assume we are called under uid of the owner of the file */ + if (fstat(f, &st) < 0 || + (st.st_uid != 0 && st.st_uid != getuid()) || + (st.st_mode & 077) != 0) { + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + error("Bad ownership or mode(0%3.3o) for '%s'.", + st.st_mode & 0777, filename); + error("It is recommended that your private key files are NOT accessible by others."); + return 0; + } + len = lseek(f, (off_t) 0, SEEK_END); + lseek(f, (off_t) 0, SEEK_SET); - len = lseek(f, (off_t)0, SEEK_END); - lseek(f, (off_t)0, SEEK_SET); - - buffer_init(&buffer); - buffer_append_space(&buffer, &cp, len); + buffer_init(&buffer); + buffer_append_space(&buffer, &cp, len); - if (read(f, cp, (size_t)len) != (size_t)len) - { - debug("Read from key file %.200s failed: %.100s", filename, - strerror(errno)); - buffer_free(&buffer); - close(f); - return 0; - } - close(f); + if (read(f, cp, (size_t) len) != (size_t) len) { + debug("Read from key file %.200s failed: %.100s", filename, + strerror(errno)); + buffer_free(&buffer); + close(f); + return 0; + } + close(f); - /* Check that it is at least big enought to contain the ID string. */ - if (len < strlen(AUTHFILE_ID_STRING) + 1) - { - debug("Bad key file %.200s.", filename); - buffer_free(&buffer); - return 0; - } + /* Check that it is at least big enought to contain the ID string. */ + if (len < strlen(AUTHFILE_ID_STRING) + 1) { + debug("Bad key file %.200s.", filename); + buffer_free(&buffer); + return 0; + } + /* Make sure it begins with the id string. Consume the id string + from the buffer. */ + for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++) + if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) { + debug("Bad key file %.200s.", filename); + buffer_free(&buffer); + return 0; + } + /* Read cipher type. */ + cipher_type = buffer_get_char(&buffer); + (void) buffer_get_int(&buffer); /* Reserved data. */ - /* Make sure it begins with the id string. Consume the id string from - the buffer. */ - for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++) - if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i]) - { - debug("Bad key file %.200s.", filename); - buffer_free(&buffer); - return 0; - } + /* Read the public key from the buffer. */ + buffer_get_int(&buffer); + prv->n = BN_new(); + buffer_get_bignum(&buffer, prv->n); + prv->e = BN_new(); + buffer_get_bignum(&buffer, prv->e); + if (comment_return) + *comment_return = buffer_get_string(&buffer, NULL); + else + xfree(buffer_get_string(&buffer, NULL)); - /* Read cipher type. */ - cipher_type = buffer_get_char(&buffer); - (void)buffer_get_int(&buffer); /* Reserved data. */ + /* Check that it is a supported cipher. */ + if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & + (1 << cipher_type)) == 0) { + debug("Unsupported cipher %.100s used in key file %.200s.", + cipher_name(cipher_type), filename); + buffer_free(&buffer); + goto fail; + } + /* Initialize space for decrypted data. */ + buffer_init(&decrypted); + buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); - /* Read the public key from the buffer. */ - buffer_get_int(&buffer); - prv->n = BN_new(); - buffer_get_bignum(&buffer, prv->n); - prv->e = BN_new(); - buffer_get_bignum(&buffer, prv->e); - if (comment_return) - *comment_return = buffer_get_string(&buffer, NULL); - else - xfree(buffer_get_string(&buffer, NULL)); + /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ + cipher_set_key_string(&cipher, cipher_type, passphrase, 0); + cipher_decrypt(&cipher, (unsigned char *) cp, + (unsigned char *) buffer_ptr(&buffer), + buffer_len(&buffer)); - /* Check that it is a supported cipher. */ - if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) & - (1 << cipher_type)) == 0) - { - debug("Unsupported cipher %.100s used in key file %.200s.", - cipher_name(cipher_type), filename); - buffer_free(&buffer); - goto fail; - } + buffer_free(&buffer); - /* Initialize space for decrypted data. */ - buffer_init(&decrypted); - buffer_append_space(&decrypted, &cp, buffer_len(&buffer)); - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ - cipher_set_key_string(&cipher, cipher_type, passphrase, 0); - cipher_decrypt(&cipher, (unsigned char *)cp, - (unsigned char *)buffer_ptr(&buffer), - buffer_len(&buffer)); + check1 = buffer_get_char(&decrypted); + check2 = buffer_get_char(&decrypted); + if (check1 != buffer_get_char(&decrypted) || + check2 != buffer_get_char(&decrypted)) { + if (strcmp(passphrase, "") != 0) + debug("Bad passphrase supplied for key file %.200s.", filename); + /* Bad passphrase. */ + buffer_free(&decrypted); +fail: + BN_clear_free(prv->n); + BN_clear_free(prv->e); + if (comment_return) + xfree(*comment_return); + return 0; + } + /* Read the rest of the private key. */ + prv->d = BN_new(); + buffer_get_bignum(&decrypted, prv->d); + prv->iqmp = BN_new(); + buffer_get_bignum(&decrypted, prv->iqmp); /* u */ + /* in SSL and SSH p and q are exchanged */ + prv->q = BN_new(); + buffer_get_bignum(&decrypted, prv->q); /* p */ + prv->p = BN_new(); + buffer_get_bignum(&decrypted, prv->p); /* q */ - buffer_free(&buffer); + ctx = BN_CTX_new(); + aux = BN_new(); - check1 = buffer_get_char(&decrypted); - check2 = buffer_get_char(&decrypted); - if (check1 != buffer_get_char(&decrypted) || - check2 != buffer_get_char(&decrypted)) - { - if (strcmp(passphrase, "") != 0) - debug("Bad passphrase supplied for key file %.200s.", filename); - /* Bad passphrase. */ - buffer_free(&decrypted); - fail: - BN_clear_free(prv->n); - BN_clear_free(prv->e); - if (comment_return) - xfree(*comment_return); - return 0; - } + BN_sub(aux, prv->q, BN_value_one()); + prv->dmq1 = BN_new(); + BN_mod(prv->dmq1, prv->d, aux, ctx); - /* Read the rest of the private key. */ - prv->d = BN_new(); - buffer_get_bignum(&decrypted, prv->d); - prv->iqmp = BN_new(); - buffer_get_bignum(&decrypted, prv->iqmp); /* u */ - /* in SSL and SSH p and q are exchanged */ - prv->q = BN_new(); - buffer_get_bignum(&decrypted, prv->q); /* p */ - prv->p = BN_new(); - buffer_get_bignum(&decrypted, prv->p); /* q */ + BN_sub(aux, prv->p, BN_value_one()); + prv->dmp1 = BN_new(); + BN_mod(prv->dmp1, prv->d, aux, ctx); - ctx = BN_CTX_new(); - aux = BN_new(); + BN_clear_free(aux); + BN_CTX_free(ctx); - BN_sub(aux, prv->q, BN_value_one()); - prv->dmq1 = BN_new(); - BN_mod(prv->dmq1, prv->d, aux, ctx); + buffer_free(&decrypted); - BN_sub(aux, prv->p, BN_value_one()); - prv->dmp1 = BN_new(); - BN_mod(prv->dmp1, prv->d, aux, ctx); - - BN_clear_free(aux); - BN_CTX_free(ctx); - - buffer_free(&decrypted); - - return 1; + return 1; }