From eba71bab9bf01c0d688f829a8971f902732558df Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sat, 29 Apr 2000 23:57:08 +1000 Subject: - Merge big update to OpenSSH-2.0 from OpenBSD CVS [README.openssh2] - interop w/ F-secure windows client - sync documentation - ssh_host_dsa_key not ssh_dsa_key [auth-rsa.c] - missing fclose [auth.c authfile.c compat.c dsa.c dsa.h hostfile.c key.c key.h radix.c] [readconf.c readconf.h ssh-add.c ssh-keygen.c ssh.c ssh.h sshconnect.c] [sshd.c uuencode.c uuencode.h authfile.h] - add DSA pubkey auth and other SSH2 fixes. use ssh-keygen -[xX] for trading keys with the real and the original SSH, directly from the people who invented the SSH protocol. [auth.c auth.h authfile.c sshconnect.c auth1.c auth2.c sshconnect.h] [sshconnect1.c sshconnect2.c] - split auth/sshconnect in one file per protocol version [sshconnect2.c] - remove debug [uuencode.c] - add trailing = [version.h] - OpenSSH-2.0 [ssh-keygen.1 ssh-keygen.c] - add -R flag: exit code indicates if RSA is alive [sshd.c] - remove unused silent if -Q is specified [ssh.h] - host key becomes /etc/ssh_host_dsa_key [readconf.c servconf.c ] - ssh/sshd default to proto 1 and 2 [uuencode.c] - remove debug [auth2.c ssh-keygen.c sshconnect2.c sshd.c] - xfree DSA blobs [auth2.c serverloop.c session.c] - cleanup logging for sshd/2, respect PasswordAuth no [sshconnect2.c] - less debug, respect .ssh/config [README.openssh2 channels.c channels.h] - clientloop.c session.c ssh.c - support for x11-fwding, client+server --- authfile.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 177 insertions(+), 29 deletions(-) (limited to 'authfile.c') diff --git a/authfile.c b/authfile.c index e17c6038..f93c9d47 100644 --- a/authfile.c +++ b/authfile.c @@ -15,14 +15,20 @@ */ #include "includes.h" -RCSID("$Id: authfile.c,v 1.11 2000/04/16 02:31:49 damien Exp $"); +RCSID("$Id: authfile.c,v 1.12 2000/04/29 13:57:10 damien Exp $"); #include +#include +#include +#include +#include + #include "xmalloc.h" #include "buffer.h" #include "bufaux.h" #include "cipher.h" #include "ssh.h" +#include "key.h" /* Version identification string for identity files. */ #define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n" @@ -35,8 +41,8 @@ RCSID("$Id: authfile.c,v 1.11 2000/04/16 02:31:49 damien Exp $"); */ int -save_private_key(const char *filename, const char *passphrase, - RSA *key, const char *comment) +save_private_key_rsa(const char *filename, const char *passphrase, + RSA *key, const char *comment) { Buffer buffer, encrypted; char buf[100], *cp; @@ -128,6 +134,63 @@ save_private_key(const char *filename, const char *passphrase, return 1; } +/* save DSA key in OpenSSL PEM format */ + +int +save_private_key_dsa(const char *filename, const char *passphrase, + DSA *dsa, const char *comment) +{ + FILE *fp; + int fd; + int success = 1; + int len = strlen(passphrase); + + if (len > 0 && len <= 4) { + error("passphrase too short: %d bytes", len); + errno = 0; + return 0; + } + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) { + debug("open %s failed", filename); + return 0; + } + fp = fdopen(fd, "w"); + if (fp == NULL ) { + debug("fdopen %s failed", filename); + close(fd); + return 0; + } + if (len > 0) { + if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(), + (char *)passphrase, strlen(passphrase), NULL, NULL)) + success = 0; + } else { + if (!PEM_write_DSAPrivateKey(fp, dsa, NULL, + NULL, 0, NULL, NULL)) + success = 0; + } + fclose(fp); + return success; +} + +int +save_private_key(const char *filename, const char *passphrase, Key *key, + const char *comment) +{ + switch (key->type) { + case KEY_RSA: + return save_private_key_rsa(filename, passphrase, key->rsa, comment); + break; + case KEY_DSA: + return save_private_key_dsa(filename, passphrase, key->dsa, comment); + break; + default: + break; + } + return 0; +} + /* * Loads the public part of the key file. Returns 0 if an error was * encountered (the file does not exist or is not readable), and non-zero @@ -135,8 +198,7 @@ save_private_key(const char *filename, const char *passphrase, */ int -load_public_key(const char *filename, RSA * pub, - char **comment_return) +load_public_key_rsa(const char *filename, RSA * pub, char **comment_return) { int fd, i; off_t len; @@ -154,7 +216,7 @@ load_public_key(const char *filename, RSA * pub, if (read(fd, cp, (size_t) len) != (size_t) len) { debug("Read from key file %.200s failed: %.100s", filename, - strerror(errno)); + strerror(errno)); buffer_free(&buffer); close(fd); return 0; @@ -183,9 +245,13 @@ load_public_key(const char *filename, RSA * pub, /* Read the public key from the buffer. */ buffer_get_int(&buffer); - pub->n = BN_new(); + /* XXX alloc */ + if (pub->n == NULL) + pub->n = BN_new(); buffer_get_bignum(&buffer, pub->n); - pub->e = BN_new(); + /* XXX alloc */ + if (pub->e == NULL) + pub->e = BN_new(); buffer_get_bignum(&buffer, pub->e); if (comment_return) *comment_return = buffer_get_string(&buffer, NULL); @@ -196,6 +262,20 @@ load_public_key(const char *filename, RSA * pub, return 1; } +int +load_public_key(const char *filename, Key * key, char **comment_return) +{ + switch (key->type) { + case KEY_RSA: + return load_public_key_rsa(filename, key->rsa, comment_return); + break; + case KEY_DSA: + default: + break; + } + return 0; +} + /* * 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 @@ -204,35 +284,17 @@ load_public_key(const char *filename, RSA * pub, */ int -load_private_key(const char *filename, const char *passphrase, - RSA * prv, char **comment_return) +load_private_key_rsa(int fd, const char *filename, + const char *passphrase, RSA * prv, char **comment_return) { - int fd, i, check1, check2, cipher_type; + int i, check1, check2, cipher_type; off_t len; Buffer buffer, decrypted; char *cp; CipherContext cipher; BN_CTX *ctx; BIGNUM *aux; - struct stat st; - - fd = open(filename, O_RDONLY); - if (fd < 0) - return 0; - /* check owner and modes */ - if (fstat(fd, &st) < 0 || - (st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) || - (st.st_mode & 077) != 0) { - close(fd); - 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(fd, (off_t) 0, SEEK_END); lseek(fd, (off_t) 0, SEEK_SET); @@ -309,7 +371,9 @@ load_private_key(const char *filename, const char *passphrase, buffer_free(&decrypted); fail: BN_clear_free(prv->n); + prv->n = NULL; BN_clear_free(prv->e); + prv->e = NULL; if (comment_return) xfree(*comment_return); return 0; @@ -343,3 +407,87 @@ fail: return 1; } + +int +load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return) +{ + DSA *dsa; + BIO *in; + FILE *fp; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + error("BIO_new failed"); + return 0; + } + fp = fdopen(fd, "r"); + if (fp == NULL) { + error("fdopen failed"); + return 0; + } + BIO_set_fp(in, fp, BIO_NOCLOSE); + dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase); + if (dsa == NULL) { + debug("PEM_read_bio_DSAPrivateKey failed"); + } else { + /* replace k->dsa with loaded key */ + DSA_free(k->dsa); + k->dsa = dsa; + } + BIO_free(in); + fclose(fp); + if (comment_return) + *comment_return = xstrdup("dsa w/o comment"); + debug("read DSA private key done"); +#ifdef DEBUG_DSS + DSA_print_fp(stderr, dsa, 8); +#endif + return dsa != NULL ? 1 : 0; +} + +int +load_private_key(const char *filename, const char *passphrase, Key *key, + char **comment_return) +{ + int fd; + int ret = 0; + struct stat st; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return 0; + + /* check owner and modes */ + if (fstat(fd, &st) < 0 || + (st.st_uid != 0 && st.st_uid != getuid()) || + (st.st_mode & 077) != 0) { + close(fd); + 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; + } + switch (key->type) { + case KEY_RSA: + 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_rsa(fd, filename, passphrase, + key->rsa, comment_return); + break; + case KEY_DSA: + ret = load_private_key_dsa(fd, passphrase, key, comment_return); + default: + break; + } + close(fd); + return ret; +} -- cgit v1.2.3