Mercurial > dropbear
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 } |