Mercurial > dropbear
diff gensignkey.c @ 1344:b90da477ab63 coverity
merge coverity
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 18 May 2017 23:02:39 +0800 |
parents | bbc0a0ee3843 |
children | 4f8eb331174f |
line wrap: on
line diff
--- a/gensignkey.c Fri Jul 22 00:08:02 2016 +0800 +++ b/gensignkey.c Thu May 18 23:02:39 2017 +0800 @@ -76,10 +76,12 @@ } } -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) { @@ -126,10 +128,37 @@ sign_key_free(key); key = NULL; buf_setpos(buf, 0); - ret = buf_writefile(buf, 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); + + if (ret == DROPBEAR_FAILURE) { + goto out; + } - buf_burn(buf); - buf_free(buf); - buf = NULL; + 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; }