Mercurial > dropbear
comparison gensignkey.c @ 1663:c795520269f9
Fallback for key gen without hard link support (#89)
Add a non-atomic fallback for key generation on platforms where link()
is not permitted (such as most stock Android installs) or on filesystems
without hard link support (such as FAT).
author | Matt Robinson <git@nerdoftheherd.com> |
---|---|
date | Sat, 14 Mar 2020 14:37:35 +0000 |
parents | d32bcb5c557d |
children | 8b4274d34fe8 |
comparison
equal
deleted
inserted
replaced
1660:26e07f7f682a | 1663:c795520269f9 |
---|---|
7 #include "gened25519.h" | 7 #include "gened25519.h" |
8 #include "signkey.h" | 8 #include "signkey.h" |
9 #include "dbrandom.h" | 9 #include "dbrandom.h" |
10 | 10 |
11 /* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ | 11 /* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
12 static int buf_writefile(buffer * buf, const char * filename) { | 12 static int buf_writefile(buffer * buf, const char * filename, int skip_exist) { |
13 int ret = DROPBEAR_FAILURE; | 13 int ret = DROPBEAR_FAILURE; |
14 int fd = -1; | 14 int fd = -1; |
15 | 15 |
16 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); | 16 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); |
17 if (fd < 0) { | 17 if (fd < 0) { |
18 dropbear_log(LOG_ERR, "Couldn't create new file %s: %s", | 18 /* If generating keys on connection (skip_exist) it's OK to get EEXIST |
19 filename, strerror(errno)); | 19 - we probably just lost a race with another connection to generate the key */ |
20 if (skip_exist && errno == EEXIST) { | |
21 ret = DROPBEAR_SUCCESS; | |
22 } else { | |
23 dropbear_log(LOG_ERR, "Couldn't create new file %s: %s", | |
24 filename, strerror(errno)); | |
25 } | |
26 | |
20 goto out; | 27 goto out; |
21 } | 28 } |
22 | 29 |
23 /* write the file now */ | 30 /* write the file now */ |
24 while (buf->pos != buf->len) { | 31 while (buf->pos != buf->len) { |
142 key = NULL; | 149 key = NULL; |
143 buf_setpos(buf, 0); | 150 buf_setpos(buf, 0); |
144 | 151 |
145 fn_temp = m_malloc(strlen(filename) + 30); | 152 fn_temp = m_malloc(strlen(filename) + 30); |
146 snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid()); | 153 snprintf(fn_temp, strlen(filename)+30, "%s.tmp%d", filename, getpid()); |
147 ret = buf_writefile(buf, fn_temp); | 154 ret = buf_writefile(buf, fn_temp, 0); |
148 | 155 |
149 if (ret == DROPBEAR_FAILURE) { | 156 if (ret == DROPBEAR_FAILURE) { |
150 goto out; | 157 goto out; |
151 } | 158 } |
152 | 159 |
153 if (link(fn_temp, filename) < 0) { | 160 if (link(fn_temp, filename) < 0) { |
154 /* If generating keys on connection (skipexist) it's OK to get EEXIST | 161 /* If generating keys on connection (skipexist) it's OK to get EEXIST |
155 - we probably just lost a race with another connection to generate the key */ | 162 - we probably just lost a race with another connection to generate the key */ |
156 if (!(skip_exist && errno == EEXIST)) { | 163 if (!(skip_exist && errno == EEXIST)) { |
157 dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename, | 164 if (errno == EPERM || errno == EACCES) { |
158 strerror(errno)); | 165 /* Non-atomic fallback when hard-links not allowed or unsupported */ |
159 /* XXX fallback to non-atomic copy for some filesystems? */ | 166 buf_setpos(buf, 0); |
160 ret = DROPBEAR_FAILURE; | 167 ret = buf_writefile(buf, filename, skip_exist); |
168 } else { | |
169 dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", filename, | |
170 strerror(errno)); | |
171 ret = DROPBEAR_FAILURE; | |
172 } | |
173 | |
161 goto out; | 174 goto out; |
162 } | 175 } |
163 } | 176 } |
164 | 177 |
165 /* ensure directory update is flushed to disk, otherwise we can end up | 178 /* ensure directory update is flushed to disk, otherwise we can end up |