summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2014-11-08 22:15:16 +0800
committerMatt Johnston <matt@ucc.asn.au>2014-11-08 22:15:16 +0800
commit4ba830fc31c056aaada774ce29bb7d4e136b5dcd (patch)
treeeb8b8b6710dbe183bad0ebc252f0278943049cf1
parent3022a460394c811fb3256c56db696b8ad1a0ad6e (diff)
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.c1
-rw-r--r--svr-kex.c22
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;
diff --git a/svr-kex.c b/svr-kex.c
index 337c377..01c76e6 100644
--- a/svr-kex.c
+++ b/svr-kex.c
@@ -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) {