diff options
author | Matt Johnston <matt@ucc.asn.au> | 2020-10-15 19:55:15 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2020-10-15 19:55:15 +0800 |
commit | 0e3e8db5bfca0c579be55e7580a46c593c1384be (patch) | |
tree | 2b1a718f633fb95c1f2d689a591cf9e8642697f3 /gensignkey.c | |
parent | 78e17f6ee9a944430da3e517ee1fe384fd6b275b (diff) | |
parent | 17873e8c922eded2cec86184673a6d110df6403f (diff) |
merge from main
--HG--
branch : fuzz
Diffstat (limited to 'gensignkey.c')
-rw-r--r-- | gensignkey.c | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/gensignkey.c b/gensignkey.c index 8317fea..4be3d7d 100644 --- a/gensignkey.c +++ b/gensignkey.c @@ -4,18 +4,26 @@ #include "ecdsa.h" #include "genrsa.h" #include "gendss.h" +#include "gened25519.h" #include "signkey.h" #include "dbrandom.h" /* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ -static int buf_writefile(buffer * buf, const char * filename) { +static int buf_writefile(buffer * buf, const char * filename, int skip_exist) { int ret = DROPBEAR_FAILURE; int fd = -1; fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd < 0) { - dropbear_log(LOG_ERR, "Couldn't create new file %s: %s", - filename, strerror(errno)); + /* If generating keys on connection (skip_exist) it's OK to get EEXIST + - we probably just lost a race with another connection to generate the key */ + if (skip_exist && errno == EEXIST) { + ret = DROPBEAR_SUCCESS; + } else { + dropbear_log(LOG_ERR, "Couldn't create new file %s: %s", + filename, strerror(errno)); + } + goto out; } @@ -69,6 +77,10 @@ static int get_default_bits(enum signkey_type keytype) case DROPBEAR_SIGNKEY_ECDSA_NISTP256: return 256; #endif +#if DROPBEAR_ED25519 + case DROPBEAR_SIGNKEY_ED25519: + return 256; +#endif default: return 0; } @@ -119,6 +131,11 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename, } break; #endif +#if DROPBEAR_ED25519 + case DROPBEAR_SIGNKEY_ED25519: + key->ed25519key = gen_ed25519_priv_key(bits); + break; +#endif default: dropbear_exit("Internal error"); } @@ -134,7 +151,7 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename, fn_temp = m_malloc(strlen(filename) + 30); snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid()); - ret = buf_writefile(buf, fn_temp); + ret = buf_writefile(buf, fn_temp, 0); if (ret == DROPBEAR_FAILURE) { goto out; @@ -144,14 +161,24 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename, /* If generating keys on connection (skipexist) it's OK to get EEXIST - we probably just lost a race with another connection to generate the key */ if (!(skip_exist && errno == EEXIST)) { - dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename, - strerror(errno)); - /* XXX fallback to non-atomic copy for some filesystems? */ - ret = DROPBEAR_FAILURE; + if (errno == EPERM || errno == EACCES) { + /* Non-atomic fallback when hard-links not allowed or unsupported */ + buf_setpos(buf, 0); + ret = buf_writefile(buf, filename, skip_exist); + } else { + dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename, + strerror(errno)); + ret = DROPBEAR_FAILURE; + } + goto out; } } + /* ensure directory update is flushed to disk, otherwise we can end up + with zero-byte hostkey files if the power goes off */ + fsync_parent_dir(filename); + out: if (buf) { buf_burn(buf); |