comparison svr-kex.c @ 1329:185c14fa504d

Use atomic key generation in all cases
author Matt Johnston <matt@ucc.asn.au>
date Sat, 19 Nov 2016 00:31:21 +0800
parents 750ec4ec4cbe
children bbc0a0ee3843
comparison
equal deleted inserted replaced
1328:c13aa2cd8d51 1329:185c14fa504d
91 } 91 }
92 92
93 93
94 #if DROPBEAR_DELAY_HOSTKEY 94 #if DROPBEAR_DELAY_HOSTKEY
95 95
96 static void fsync_parent_dir(const char* fn) {
97 #ifdef HAVE_LIBGEN_H
98 char *fn_dir = m_strdup(fn);
99 char *dir = dirname(fn_dir);
100 int dirfd = open(dir, O_RDONLY);
101
102 if (dirfd != -1) {
103 if (fsync(dirfd) != 0) {
104 TRACE(("fsync of directory %s failed: %s", dir, strerror(errno)))
105 }
106 m_close(dirfd);
107 } else {
108 TRACE(("error opening directory %s for fsync: %s", dir, strerror(errno)))
109 }
110
111 free(fn_dir);
112 #endif
113 }
114
115 static void svr_ensure_hostkey() { 96 static void svr_ensure_hostkey() {
116 97
117 const char* fn = NULL; 98 const char* fn = NULL;
118 char *fn_temp = NULL;
119 enum signkey_type type = ses.newkeys->algo_hostkey; 99 enum signkey_type type = ses.newkeys->algo_hostkey;
120 void **hostkey = signkey_key_ptr(svr_opts.hostkey, type); 100 void **hostkey = signkey_key_ptr(svr_opts.hostkey, type);
121 int ret = DROPBEAR_FAILURE; 101 int ret = DROPBEAR_FAILURE;
122 102
123 if (hostkey && *hostkey) { 103 if (hostkey && *hostkey) {
149 129
150 if (readhostkey(fn, svr_opts.hostkey, &type) == DROPBEAR_SUCCESS) { 130 if (readhostkey(fn, svr_opts.hostkey, &type) == DROPBEAR_SUCCESS) {
151 return; 131 return;
152 } 132 }
153 133
154 fn_temp = m_malloc(strlen(fn) + 20); 134 if (signkey_generate(type, 0, fn, 1) == DROPBEAR_FAILURE) {
155 snprintf(fn_temp, strlen(fn)+20, "%s.tmp%d", fn, getpid());
156
157 if (signkey_generate(type, 0, fn_temp) == DROPBEAR_FAILURE) {
158 goto out; 135 goto out;
159 } 136 }
160 137
161 if (link(fn_temp, fn) < 0) {
162 /* It's OK to get EEXIST - we probably just lost a race
163 with another connection to generate the key */
164 if (errno != EEXIST) {
165 dropbear_log(LOG_ERR, "Failed moving key file to %s: %s", fn,
166 strerror(errno));
167 /* XXX fallback to non-atomic copy for some filesystems? */
168 goto out;
169 }
170 }
171
172 /* ensure directory update is flushed to disk, otherwise we can end up
173 with zero-byte hostkey files if the power goes off */
174 fsync_parent_dir(fn);
175
176 ret = readhostkey(fn, svr_opts.hostkey, &type); 138 ret = readhostkey(fn, svr_opts.hostkey, &type);
177 139
178 if (ret == DROPBEAR_SUCCESS) { 140 if (ret == DROPBEAR_SUCCESS) {
179 char *fp = NULL; 141 char *fp = NULL;
180 unsigned int len; 142 unsigned int len;
188 m_free(fp); 150 m_free(fp);
189 buf_free(key_buf); 151 buf_free(key_buf);
190 } 152 }
191 153
192 out: 154 out:
193 if (fn_temp) {
194 unlink(fn_temp);
195 m_free(fn_temp);
196 }
197
198 if (ret == DROPBEAR_FAILURE) 155 if (ret == DROPBEAR_FAILURE)
199 { 156 {
200 dropbear_exit("Couldn't read or generate hostkey %s", fn); 157 dropbear_exit("Couldn't read or generate hostkey %s", fn);
201 } 158 }
202 } 159 }