summaryrefslogtreecommitdiffhomepage
path: root/gensignkey.c
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2017-05-18 23:45:10 +0800
committerMatt Johnston <matt@ucc.asn.au>2017-05-18 23:45:10 +0800
commit4dae8edb76c3c252b681669c16f978477c633c16 (patch)
tree19c7eac9e1604f2bd75dcc34c266532ea98b0e41 /gensignkey.c
parenta3e01b88841da97aae3d80b155034cc5f9f2c03e (diff)
parentf7d38a1b9ccbe6225dcf5959d922b6d073638891 (diff)
merge main to fuzz
--HG-- branch : fuzz
Diffstat (limited to 'gensignkey.c')
-rw-r--r--gensignkey.c51
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;
}