diff options
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 101 |
1 files changed, 46 insertions, 55 deletions
diff --git a/authfile.c b/authfile.c index 20b66d9bd..35ccf576c 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.137 2020/01/25 23:02:13 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.140 2020/04/17 07:15:11 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -141,6 +141,14 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, | |||
141 | } | 141 | } |
142 | 142 | ||
143 | int | 143 | int |
144 | sshkey_load_private(const char *filename, const char *passphrase, | ||
145 | struct sshkey **keyp, char **commentp) | ||
146 | { | ||
147 | return sshkey_load_private_type(KEY_UNSPEC, filename, passphrase, | ||
148 | keyp, commentp); | ||
149 | } | ||
150 | |||
151 | int | ||
144 | sshkey_load_private_type_fd(int fd, int type, const char *passphrase, | 152 | sshkey_load_private_type_fd(int fd, int type, const char *passphrase, |
145 | struct sshkey **keyp, char **commentp) | 153 | struct sshkey **keyp, char **commentp) |
146 | { | 154 | { |
@@ -161,51 +169,57 @@ sshkey_load_private_type_fd(int fd, int type, const char *passphrase, | |||
161 | return r; | 169 | return r; |
162 | } | 170 | } |
163 | 171 | ||
164 | /* XXX this is almost identical to sshkey_load_private_type() */ | 172 | /* Load a pubkey from the unencrypted envelope of a new-format private key */ |
165 | int | 173 | static int |
166 | sshkey_load_private(const char *filename, const char *passphrase, | 174 | sshkey_load_pubkey_from_private(const char *filename, struct sshkey **pubkeyp) |
167 | struct sshkey **keyp, char **commentp) | ||
168 | { | 175 | { |
169 | struct sshbuf *buffer = NULL; | 176 | struct sshbuf *buffer = NULL; |
177 | struct sshkey *pubkey = NULL; | ||
170 | int r, fd; | 178 | int r, fd; |
171 | 179 | ||
172 | if (keyp != NULL) | 180 | if (pubkeyp != NULL) |
173 | *keyp = NULL; | 181 | *pubkeyp = NULL; |
174 | if (commentp != NULL) | ||
175 | *commentp = NULL; | ||
176 | 182 | ||
177 | if ((fd = open(filename, O_RDONLY)) == -1) | 183 | if ((fd = open(filename, O_RDONLY)) == -1) |
178 | return SSH_ERR_SYSTEM_ERROR; | 184 | return SSH_ERR_SYSTEM_ERROR; |
179 | if (sshkey_perm_ok(fd, filename) != 0) { | ||
180 | r = SSH_ERR_KEY_BAD_PERMISSIONS; | ||
181 | goto out; | ||
182 | } | ||
183 | if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || | 185 | if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || |
184 | (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp, | 186 | (r = sshkey_parse_pubkey_from_private_fileblob_type(buffer, |
185 | commentp)) != 0) | 187 | KEY_UNSPEC, &pubkey)) != 0) |
186 | goto out; | 188 | goto out; |
187 | if (keyp && *keyp && | 189 | if ((r = sshkey_set_filename(pubkey, filename)) != 0) |
188 | (r = sshkey_set_filename(*keyp, filename)) != 0) | ||
189 | goto out; | 190 | goto out; |
191 | /* success */ | ||
192 | if (pubkeyp != NULL) { | ||
193 | *pubkeyp = pubkey; | ||
194 | pubkey = NULL; | ||
195 | } | ||
190 | r = 0; | 196 | r = 0; |
191 | out: | 197 | out: |
192 | close(fd); | 198 | close(fd); |
193 | sshbuf_free(buffer); | 199 | sshbuf_free(buffer); |
200 | sshkey_free(pubkey); | ||
194 | return r; | 201 | return r; |
195 | } | 202 | } |
196 | 203 | ||
197 | static int | 204 | static int |
198 | sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) | 205 | sshkey_try_load_public(struct sshkey **kp, const char *filename, |
206 | char **commentp) | ||
199 | { | 207 | { |
200 | FILE *f; | 208 | FILE *f; |
201 | char *line = NULL, *cp; | 209 | char *line = NULL, *cp; |
202 | size_t linesize = 0; | 210 | size_t linesize = 0; |
203 | int r; | 211 | int r; |
212 | struct sshkey *k = NULL; | ||
204 | 213 | ||
214 | *kp = NULL; | ||
205 | if (commentp != NULL) | 215 | if (commentp != NULL) |
206 | *commentp = NULL; | 216 | *commentp = NULL; |
207 | if ((f = fopen(filename, "r")) == NULL) | 217 | if ((f = fopen(filename, "r")) == NULL) |
208 | return SSH_ERR_SYSTEM_ERROR; | 218 | return SSH_ERR_SYSTEM_ERROR; |
219 | if ((k = sshkey_new(KEY_UNSPEC)) == NULL) { | ||
220 | fclose(f); | ||
221 | return SSH_ERR_ALLOC_FAIL; | ||
222 | } | ||
209 | while (getline(&line, &linesize, f) != -1) { | 223 | while (getline(&line, &linesize, f) != -1) { |
210 | cp = line; | 224 | cp = line; |
211 | switch (*cp) { | 225 | switch (*cp) { |
@@ -230,12 +244,15 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) | |||
230 | if (*commentp == NULL) | 244 | if (*commentp == NULL) |
231 | r = SSH_ERR_ALLOC_FAIL; | 245 | r = SSH_ERR_ALLOC_FAIL; |
232 | } | 246 | } |
247 | /* success */ | ||
248 | *kp = k; | ||
233 | free(line); | 249 | free(line); |
234 | fclose(f); | 250 | fclose(f); |
235 | return r; | 251 | return r; |
236 | } | 252 | } |
237 | } | 253 | } |
238 | } | 254 | } |
255 | free(k); | ||
239 | free(line); | 256 | free(line); |
240 | fclose(f); | 257 | fclose(f); |
241 | return SSH_ERR_INVALID_FORMAT; | 258 | return SSH_ERR_INVALID_FORMAT; |
@@ -245,8 +262,7 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) | |||
245 | int | 262 | int |
246 | sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) | 263 | sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) |
247 | { | 264 | { |
248 | struct sshkey *pub = NULL; | 265 | char *pubfile = NULL; |
249 | char *file = NULL; | ||
250 | int r; | 266 | int r; |
251 | 267 | ||
252 | if (keyp != NULL) | 268 | if (keyp != NULL) |
@@ -254,35 +270,21 @@ sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) | |||
254 | if (commentp != NULL) | 270 | if (commentp != NULL) |
255 | *commentp = NULL; | 271 | *commentp = NULL; |
256 | 272 | ||
257 | if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) | 273 | if ((r = sshkey_try_load_public(keyp, filename, commentp)) == 0) |
258 | return SSH_ERR_ALLOC_FAIL; | ||
259 | if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { | ||
260 | if (keyp != NULL) { | ||
261 | *keyp = pub; | ||
262 | pub = NULL; | ||
263 | } | ||
264 | r = 0; | ||
265 | goto out; | 274 | goto out; |
266 | } | ||
267 | sshkey_free(pub); | ||
268 | 275 | ||
269 | /* try .pub suffix */ | 276 | /* try .pub suffix */ |
270 | if (asprintf(&file, "%s.pub", filename) == -1) | 277 | if (asprintf(&pubfile, "%s.pub", filename) == -1) |
271 | return SSH_ERR_ALLOC_FAIL; | 278 | return SSH_ERR_ALLOC_FAIL; |
272 | if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { | 279 | if ((r = sshkey_try_load_public(keyp, pubfile, commentp)) == 0) |
273 | r = SSH_ERR_ALLOC_FAIL; | ||
274 | goto out; | 280 | goto out; |
275 | } | 281 | |
276 | if ((r = sshkey_try_load_public(pub, file, commentp)) == 0) { | 282 | /* finally, try to extract public key from private key file */ |
277 | if (keyp != NULL) { | 283 | if ((r = sshkey_load_pubkey_from_private(filename, keyp)) == 0) |
278 | *keyp = pub; | 284 | goto out; |
279 | pub = NULL; | 285 | |
280 | } | ||
281 | r = 0; | ||
282 | } | ||
283 | out: | 286 | out: |
284 | free(file); | 287 | free(pubfile); |
285 | sshkey_free(pub); | ||
286 | return r; | 288 | return r; |
287 | } | 289 | } |
288 | 290 | ||
@@ -300,18 +302,7 @@ sshkey_load_cert(const char *filename, struct sshkey **keyp) | |||
300 | if (asprintf(&file, "%s-cert.pub", filename) == -1) | 302 | if (asprintf(&file, "%s-cert.pub", filename) == -1) |
301 | return SSH_ERR_ALLOC_FAIL; | 303 | return SSH_ERR_ALLOC_FAIL; |
302 | 304 | ||
303 | if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { | 305 | r = sshkey_try_load_public(keyp, file, NULL); |
304 | goto out; | ||
305 | } | ||
306 | if ((r = sshkey_try_load_public(pub, file, NULL)) != 0) | ||
307 | goto out; | ||
308 | /* success */ | ||
309 | if (keyp != NULL) { | ||
310 | *keyp = pub; | ||
311 | pub = NULL; | ||
312 | } | ||
313 | r = 0; | ||
314 | out: | ||
315 | free(file); | 306 | free(file); |
316 | sshkey_free(pub); | 307 | sshkey_free(pub); |
317 | return r; | 308 | return r; |