diff options
author | Matt Johnston <matt@ucc.asn.au> | 2017-05-18 23:45:10 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2017-05-18 23:45:10 +0800 |
commit | 4dae8edb76c3c252b681669c16f978477c633c16 (patch) | |
tree | 19c7eac9e1604f2bd75dcc34c266532ea98b0e41 /gensignkey.c | |
parent | a3e01b88841da97aae3d80b155034cc5f9f2c03e (diff) | |
parent | f7d38a1b9ccbe6225dcf5959d922b6d073638891 (diff) |
merge main to fuzz
--HG--
branch : fuzz
Diffstat (limited to 'gensignkey.c')
-rw-r--r-- | gensignkey.c | 51 |
1 files changed, 40 insertions, 11 deletions
diff --git a/gensignkey.c b/gensignkey.c index cdc16e6..4691de0 100644 --- a/gensignkey.c +++ b/gensignkey.c @@ -53,15 +53,15 @@ out: static int get_default_bits(enum signkey_type keytype) { switch (keytype) { -#ifdef DROPBEAR_RSA +#if DROPBEAR_RSA case DROPBEAR_SIGNKEY_RSA: return RSA_DEFAULT_SIZE; #endif -#ifdef DROPBEAR_DSS +#if DROPBEAR_DSS case DROPBEAR_SIGNKEY_DSS: return DSS_DEFAULT_SIZE; #endif -#ifdef DROPBEAR_ECDSA +#if DROPBEAR_ECDSA case DROPBEAR_SIGNKEY_ECDSA_KEYGEN: return ECDSA_DEFAULT_SIZE; case DROPBEAR_SIGNKEY_ECDSA_NISTP521: @@ -76,10 +76,12 @@ static int get_default_bits(enum signkey_type keytype) } } -int signkey_generate(enum signkey_type keytype, int bits, const char* filename) +/* if skip_exist is set it will silently return if the key file exists */ +int signkey_generate(enum signkey_type keytype, int bits, const char* filename, int skip_exist) { sign_key * key = NULL; buffer *buf = NULL; + char *fn_temp = NULL; int ret = DROPBEAR_FAILURE; if (bits == 0) { @@ -92,17 +94,17 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename) seedrandom(); switch(keytype) { -#ifdef DROPBEAR_RSA +#if DROPBEAR_RSA case DROPBEAR_SIGNKEY_RSA: key->rsakey = gen_rsa_priv_key(bits); break; #endif -#ifdef DROPBEAR_DSS +#if DROPBEAR_DSS case DROPBEAR_SIGNKEY_DSS: key->dsskey = gen_dss_priv_key(bits); break; #endif -#ifdef DROPBEAR_ECDSA +#if DROPBEAR_ECDSA case DROPBEAR_SIGNKEY_ECDSA_KEYGEN: case DROPBEAR_SIGNKEY_ECDSA_NISTP521: case DROPBEAR_SIGNKEY_ECDSA_NISTP384: @@ -126,10 +128,37 @@ int signkey_generate(enum signkey_type keytype, int bits, const char* filename) sign_key_free(key); key = NULL; buf_setpos(buf, 0); - ret = buf_writefile(buf, filename); - buf_burn(buf); - buf_free(buf); - buf = NULL; + fn_temp = m_malloc(strlen(filename) + 30); + snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid()); + ret = buf_writefile(buf, fn_temp); + + if (ret == DROPBEAR_FAILURE) { + goto out; + } + + if (link(fn_temp, filename) < 0) { + /* 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; + goto out; + } + } + +out: + if (buf) { + buf_burn(buf); + buf_free(buf); + } + + if (fn_temp) { + unlink(fn_temp); + m_free(fn_temp); + } + return ret; } |