diff options
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 125 |
1 files changed, 74 insertions, 51 deletions
diff --git a/authfile.c b/authfile.c index e93d86738..3a81786c7 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.107 2014/06/24 01:13:21 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.111 2015/02/23 16:55:51 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 | * |
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
29 | #include <sys/stat.h> | 29 | #include <sys/stat.h> |
30 | #include <sys/param.h> | ||
31 | #include <sys/uio.h> | 30 | #include <sys/uio.h> |
32 | 31 | ||
33 | #include <errno.h> | 32 | #include <errno.h> |
@@ -37,6 +36,7 @@ | |||
37 | #include <stdlib.h> | 36 | #include <stdlib.h> |
38 | #include <string.h> | 37 | #include <string.h> |
39 | #include <unistd.h> | 38 | #include <unistd.h> |
39 | #include <limits.h> | ||
40 | 40 | ||
41 | #include "cipher.h" | 41 | #include "cipher.h" |
42 | #include "key.h" | 42 | #include "key.h" |
@@ -48,6 +48,7 @@ | |||
48 | #include "atomicio.h" | 48 | #include "atomicio.h" |
49 | #include "sshbuf.h" | 49 | #include "sshbuf.h" |
50 | #include "ssherr.h" | 50 | #include "ssherr.h" |
51 | #include "krl.h" | ||
51 | 52 | ||
52 | #define MAX_KEY_FILE_SIZE (1024 * 1024) | 53 | #define MAX_KEY_FILE_SIZE (1024 * 1024) |
53 | 54 | ||
@@ -94,7 +95,7 @@ sshkey_save_private(struct sshkey *key, const char *filename, | |||
94 | 95 | ||
95 | /* Load a key from a fd into a buffer */ | 96 | /* Load a key from a fd into a buffer */ |
96 | int | 97 | int |
97 | sshkey_load_file(int fd, const char *filename, struct sshbuf *blob) | 98 | sshkey_load_file(int fd, struct sshbuf *blob) |
98 | { | 99 | { |
99 | u_char buf[1024]; | 100 | u_char buf[1024]; |
100 | size_t len; | 101 | size_t len; |
@@ -141,8 +142,7 @@ sshkey_load_file(int fd, const char *filename, struct sshbuf *blob) | |||
141 | * otherwise. | 142 | * otherwise. |
142 | */ | 143 | */ |
143 | static int | 144 | static int |
144 | sshkey_load_public_rsa1(int fd, const char *filename, | 145 | sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp) |
145 | struct sshkey **keyp, char **commentp) | ||
146 | { | 146 | { |
147 | struct sshbuf *b = NULL; | 147 | struct sshbuf *b = NULL; |
148 | int r; | 148 | int r; |
@@ -153,7 +153,7 @@ sshkey_load_public_rsa1(int fd, const char *filename, | |||
153 | 153 | ||
154 | if ((b = sshbuf_new()) == NULL) | 154 | if ((b = sshbuf_new()) == NULL) |
155 | return SSH_ERR_ALLOC_FAIL; | 155 | return SSH_ERR_ALLOC_FAIL; |
156 | if ((r = sshkey_load_file(fd, filename, b)) != 0) | 156 | if ((r = sshkey_load_file(fd, b)) != 0) |
157 | goto out; | 157 | goto out; |
158 | if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0) | 158 | if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0) |
159 | goto out; | 159 | goto out; |
@@ -164,33 +164,6 @@ sshkey_load_public_rsa1(int fd, const char *filename, | |||
164 | } | 164 | } |
165 | #endif /* WITH_SSH1 */ | 165 | #endif /* WITH_SSH1 */ |
166 | 166 | ||
167 | #ifdef WITH_OPENSSL | ||
168 | /* XXX Deprecate? */ | ||
169 | int | ||
170 | sshkey_load_private_pem(int fd, int type, const char *passphrase, | ||
171 | struct sshkey **keyp, char **commentp) | ||
172 | { | ||
173 | struct sshbuf *buffer = NULL; | ||
174 | int r; | ||
175 | |||
176 | *keyp = NULL; | ||
177 | if (commentp != NULL) | ||
178 | *commentp = NULL; | ||
179 | |||
180 | if ((buffer = sshbuf_new()) == NULL) | ||
181 | return SSH_ERR_ALLOC_FAIL; | ||
182 | if ((r = sshkey_load_file(fd, NULL, buffer)) != 0) | ||
183 | goto out; | ||
184 | if ((r = sshkey_parse_private_pem_fileblob(buffer, type, passphrase, | ||
185 | keyp, commentp)) != 0) | ||
186 | goto out; | ||
187 | r = 0; | ||
188 | out: | ||
189 | sshbuf_free(buffer); | ||
190 | return r; | ||
191 | } | ||
192 | #endif /* WITH_OPENSSL */ | ||
193 | |||
194 | /* XXX remove error() calls from here? */ | 167 | /* XXX remove error() calls from here? */ |
195 | int | 168 | int |
196 | sshkey_perm_ok(int fd, const char *filename) | 169 | sshkey_perm_ok(int fd, const char *filename) |
@@ -226,7 +199,6 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, | |||
226 | struct sshkey **keyp, char **commentp, int *perm_ok) | 199 | struct sshkey **keyp, char **commentp, int *perm_ok) |
227 | { | 200 | { |
228 | int fd, r; | 201 | int fd, r; |
229 | struct sshbuf *buffer = NULL; | ||
230 | 202 | ||
231 | *keyp = NULL; | 203 | *keyp = NULL; |
232 | if (commentp != NULL) | 204 | if (commentp != NULL) |
@@ -246,18 +218,31 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, | |||
246 | if (perm_ok != NULL) | 218 | if (perm_ok != NULL) |
247 | *perm_ok = 1; | 219 | *perm_ok = 1; |
248 | 220 | ||
221 | r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp); | ||
222 | out: | ||
223 | close(fd); | ||
224 | return r; | ||
225 | } | ||
226 | |||
227 | int | ||
228 | sshkey_load_private_type_fd(int fd, int type, const char *passphrase, | ||
229 | struct sshkey **keyp, char **commentp) | ||
230 | { | ||
231 | struct sshbuf *buffer = NULL; | ||
232 | int r; | ||
233 | |||
249 | if ((buffer = sshbuf_new()) == NULL) { | 234 | if ((buffer = sshbuf_new()) == NULL) { |
250 | r = SSH_ERR_ALLOC_FAIL; | 235 | r = SSH_ERR_ALLOC_FAIL; |
251 | goto out; | 236 | goto out; |
252 | } | 237 | } |
253 | if ((r = sshkey_load_file(fd, filename, buffer)) != 0) | 238 | if ((r = sshkey_load_file(fd, buffer)) != 0 || |
254 | goto out; | 239 | (r = sshkey_parse_private_fileblob_type(buffer, type, |
255 | if ((r = sshkey_parse_private_fileblob_type(buffer, type, passphrase, | 240 | passphrase, keyp, commentp)) != 0) |
256 | keyp, commentp)) != 0) | ||
257 | goto out; | 241 | goto out; |
242 | |||
243 | /* success */ | ||
258 | r = 0; | 244 | r = 0; |
259 | out: | 245 | out: |
260 | close(fd); | ||
261 | if (buffer != NULL) | 246 | if (buffer != NULL) |
262 | sshbuf_free(buffer); | 247 | sshbuf_free(buffer); |
263 | return r; | 248 | return r; |
@@ -286,7 +271,7 @@ sshkey_load_private(const char *filename, const char *passphrase, | |||
286 | r = SSH_ERR_ALLOC_FAIL; | 271 | r = SSH_ERR_ALLOC_FAIL; |
287 | goto out; | 272 | goto out; |
288 | } | 273 | } |
289 | if ((r = sshkey_load_file(fd, filename, buffer)) != 0 || | 274 | if ((r = sshkey_load_file(fd, buffer)) != 0 || |
290 | (r = sshkey_parse_private_fileblob(buffer, passphrase, filename, | 275 | (r = sshkey_parse_private_fileblob(buffer, passphrase, filename, |
291 | keyp, commentp)) != 0) | 276 | keyp, commentp)) != 0) |
292 | goto out; | 277 | goto out; |
@@ -350,7 +335,7 @@ int | |||
350 | sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) | 335 | sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) |
351 | { | 336 | { |
352 | struct sshkey *pub = NULL; | 337 | struct sshkey *pub = NULL; |
353 | char file[MAXPATHLEN]; | 338 | char file[PATH_MAX]; |
354 | int r, fd; | 339 | int r, fd; |
355 | 340 | ||
356 | if (keyp != NULL) | 341 | if (keyp != NULL) |
@@ -358,11 +343,13 @@ sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) | |||
358 | if (commentp != NULL) | 343 | if (commentp != NULL) |
359 | *commentp = NULL; | 344 | *commentp = NULL; |
360 | 345 | ||
346 | /* XXX should load file once and attempt to parse each format */ | ||
347 | |||
361 | if ((fd = open(filename, O_RDONLY)) < 0) | 348 | if ((fd = open(filename, O_RDONLY)) < 0) |
362 | goto skip; | 349 | goto skip; |
363 | #ifdef WITH_SSH1 | 350 | #ifdef WITH_SSH1 |
364 | /* try rsa1 private key */ | 351 | /* try rsa1 private key */ |
365 | r = sshkey_load_public_rsa1(fd, filename, keyp, commentp); | 352 | r = sshkey_load_public_rsa1(fd, keyp, commentp); |
366 | close(fd); | 353 | close(fd); |
367 | switch (r) { | 354 | switch (r) { |
368 | case SSH_ERR_INTERNAL_ERROR: | 355 | case SSH_ERR_INTERNAL_ERROR: |
@@ -409,6 +396,7 @@ sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) | |||
409 | return 0; | 396 | return 0; |
410 | } | 397 | } |
411 | sshkey_free(pub); | 398 | sshkey_free(pub); |
399 | |||
412 | return r; | 400 | return r; |
413 | } | 401 | } |
414 | 402 | ||
@@ -494,11 +482,14 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, | |||
494 | /* | 482 | /* |
495 | * Returns success if the specified "key" is listed in the file "filename", | 483 | * Returns success if the specified "key" is listed in the file "filename", |
496 | * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. | 484 | * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error. |
497 | * If strict_type is set then the key type must match exactly, | 485 | * If "strict_type" is set then the key type must match exactly, |
498 | * otherwise a comparison that ignores certficiate data is performed. | 486 | * otherwise a comparison that ignores certficiate data is performed. |
487 | * If "check_ca" is set and "key" is a certificate, then its CA key is | ||
488 | * also checked and sshkey_in_file() will return success if either is found. | ||
499 | */ | 489 | */ |
500 | int | 490 | int |
501 | sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | 491 | sshkey_in_file(struct sshkey *key, const char *filename, int strict_type, |
492 | int check_ca) | ||
502 | { | 493 | { |
503 | FILE *f; | 494 | FILE *f; |
504 | char line[SSH_MAX_PUBKEY_BYTES]; | 495 | char line[SSH_MAX_PUBKEY_BYTES]; |
@@ -509,12 +500,8 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | |||
509 | int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) = | 500 | int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) = |
510 | strict_type ? sshkey_equal : sshkey_equal_public; | 501 | strict_type ? sshkey_equal : sshkey_equal_public; |
511 | 502 | ||
512 | if ((f = fopen(filename, "r")) == NULL) { | 503 | if ((f = fopen(filename, "r")) == NULL) |
513 | if (errno == ENOENT) | 504 | return SSH_ERR_SYSTEM_ERROR; |
514 | return SSH_ERR_KEY_NOT_FOUND; | ||
515 | else | ||
516 | return SSH_ERR_SYSTEM_ERROR; | ||
517 | } | ||
518 | 505 | ||
519 | while (read_keyfile_line(f, filename, line, sizeof(line), | 506 | while (read_keyfile_line(f, filename, line, sizeof(line), |
520 | &linenum) != -1) { | 507 | &linenum) != -1) { |
@@ -538,7 +525,9 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | |||
538 | } | 525 | } |
539 | if ((r = sshkey_read(pub, &cp)) != 0) | 526 | if ((r = sshkey_read(pub, &cp)) != 0) |
540 | goto out; | 527 | goto out; |
541 | if (sshkey_compare(key, pub)) { | 528 | if (sshkey_compare(key, pub) || |
529 | (check_ca && sshkey_is_cert(key) && | ||
530 | sshkey_compare(key->cert->signature_key, pub))) { | ||
542 | r = 0; | 531 | r = 0; |
543 | goto out; | 532 | goto out; |
544 | } | 533 | } |
@@ -553,3 +542,37 @@ sshkey_in_file(struct sshkey *key, const char *filename, int strict_type) | |||
553 | return r; | 542 | return r; |
554 | } | 543 | } |
555 | 544 | ||
545 | /* | ||
546 | * Checks whether the specified key is revoked, returning 0 if not, | ||
547 | * SSH_ERR_KEY_REVOKED if it is or another error code if something | ||
548 | * unexpected happened. | ||
549 | * This will check both the key and, if it is a certificate, its CA key too. | ||
550 | * "revoked_keys_file" may be a KRL or a one-per-line list of public keys. | ||
551 | */ | ||
552 | int | ||
553 | sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file) | ||
554 | { | ||
555 | int r; | ||
556 | |||
557 | r = ssh_krl_file_contains_key(revoked_keys_file, key); | ||
558 | /* If this was not a KRL to begin with then continue below */ | ||
559 | if (r != SSH_ERR_KRL_BAD_MAGIC) | ||
560 | return r; | ||
561 | |||
562 | /* | ||
563 | * If the file is not a KRL or we can't handle KRLs then attempt to | ||
564 | * parse the file as a flat list of keys. | ||
565 | */ | ||
566 | switch ((r = sshkey_in_file(key, revoked_keys_file, 0, 1))) { | ||
567 | case 0: | ||
568 | /* Key found => revoked */ | ||
569 | return SSH_ERR_KEY_REVOKED; | ||
570 | case SSH_ERR_KEY_NOT_FOUND: | ||
571 | /* Key not found => not revoked */ | ||
572 | return 0; | ||
573 | default: | ||
574 | /* Some other error occurred */ | ||
575 | return r; | ||
576 | } | ||
577 | } | ||
578 | |||