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