comparison svr-kex.c @ 1336:efad433418c4

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