diff options
author | Matt Johnston <matt@ucc.asn.au> | 2014-11-08 22:15:16 +0800 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2014-11-08 22:15:16 +0800 |
commit | f79737b53fe3c79bbe3b15c09dfe34731da8c256 (patch) | |
tree | ebeb3534e392cda26a3320195a2996eaceec20fb | |
parent | ca58e0c26653326add65112f2c88345cdce133f0 (diff) | |
download | dropbear-f79737b53fe3c79bbe3b15c09dfe34731da8c256.tar.gz |
Make sure hostkeys are flushed to disk to avoid empty files if the power
fails. Based on patch from Peter Korsgaard
-rw-r--r-- | gensignkey.c | 1 | ||||
-rw-r--r-- | svr-kex.c | 22 |
2 files changed, 23 insertions, 0 deletions
diff --git a/gensignkey.c b/gensignkey.c index 338bbef..06fdfd3 100644 --- a/gensignkey.c +++ b/gensignkey.c @@ -41,6 +41,7 @@ static int buf_writefile(buffer * buf, const char * filename) { out: if (fd >= 0) { + fsync(fd); m_close(fd); } return ret; @@ -84,7 +84,25 @@ void recv_msg_kexdh_init() { TRACE(("leave recv_msg_kexdh_init")) } + #ifdef DROPBEAR_DELAY_HOSTKEY + +static void fsync_parent_dir(const char* fn) { +#ifdef HAVE_LIBGEN_H + char *fn_dir = m_strdup(fn); + char *dir = dirname(fn_dir); + /* some OSes need the fd to be writable for fsync */ + int dirfd = open(dir, O_RDWR); + + if (dirfd != -1) { + fsync(dirfd); + m_close(dirfd); + } + + free(fn_dir); +#endif +} + static void svr_ensure_hostkey() { const char* fn = NULL; @@ -142,6 +160,10 @@ static void svr_ensure_hostkey() { } } + /* 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(fn); + ret = readhostkey(fn, svr_opts.hostkey, &type); if (ret == DROPBEAR_SUCCESS) { |