diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index fe68d5c41..378b3200c 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.189 2012/06/22 12:30:26 dtucker Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.191 2013/02/15 00:21:01 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -40,7 +40,7 @@ | |||
40 | #include <stdio.h> | 40 | #include <stdio.h> |
41 | #include <string.h> | 41 | #include <string.h> |
42 | #include <unistd.h> | 42 | #include <unistd.h> |
43 | #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) | 43 | #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) |
44 | #include <vis.h> | 44 | #include <vis.h> |
45 | #endif | 45 | #endif |
46 | 46 | ||
@@ -304,6 +304,7 @@ struct identity { | |||
304 | char *filename; /* comment for agent-only keys */ | 304 | char *filename; /* comment for agent-only keys */ |
305 | int tried; | 305 | int tried; |
306 | int isprivate; /* key points to the private key */ | 306 | int isprivate; /* key points to the private key */ |
307 | int userprovided; | ||
307 | }; | 308 | }; |
308 | TAILQ_HEAD(idlist, identity); | 309 | TAILQ_HEAD(idlist, identity); |
309 | 310 | ||
@@ -369,7 +370,7 @@ void userauth(Authctxt *, char *); | |||
369 | static int sign_and_send_pubkey(Authctxt *, Identity *); | 370 | static int sign_and_send_pubkey(Authctxt *, Identity *); |
370 | static void pubkey_prepare(Authctxt *); | 371 | static void pubkey_prepare(Authctxt *); |
371 | static void pubkey_cleanup(Authctxt *); | 372 | static void pubkey_cleanup(Authctxt *); |
372 | static Key *load_identity_file(char *); | 373 | static Key *load_identity_file(char *, int); |
373 | 374 | ||
374 | static Authmethod *authmethod_get(char *authlist); | 375 | static Authmethod *authmethod_get(char *authlist); |
375 | static Authmethod *authmethod_lookup(const char *name); | 376 | static Authmethod *authmethod_lookup(const char *name); |
@@ -1302,7 +1303,7 @@ identity_sign(Identity *id, u_char **sigp, u_int *lenp, | |||
1302 | if (id->isprivate || (id->key->flags & KEY_FLAG_EXT)) | 1303 | if (id->isprivate || (id->key->flags & KEY_FLAG_EXT)) |
1303 | return (key_sign(id->key, sigp, lenp, data, datalen)); | 1304 | return (key_sign(id->key, sigp, lenp, data, datalen)); |
1304 | /* load the private key from the file */ | 1305 | /* load the private key from the file */ |
1305 | if ((prv = load_identity_file(id->filename)) == NULL) | 1306 | if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) |
1306 | return (-1); | 1307 | return (-1); |
1307 | ret = key_sign(prv, sigp, lenp, data, datalen); | 1308 | ret = key_sign(prv, sigp, lenp, data, datalen); |
1308 | key_free(prv); | 1309 | key_free(prv); |
@@ -1427,7 +1428,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id) | |||
1427 | } | 1428 | } |
1428 | 1429 | ||
1429 | static Key * | 1430 | static Key * |
1430 | load_identity_file(char *filename) | 1431 | load_identity_file(char *filename, int userprovided) |
1431 | { | 1432 | { |
1432 | Key *private; | 1433 | Key *private; |
1433 | char prompt[300], *passphrase; | 1434 | char prompt[300], *passphrase; |
@@ -1435,7 +1436,8 @@ load_identity_file(char *filename) | |||
1435 | struct stat st; | 1436 | struct stat st; |
1436 | 1437 | ||
1437 | if (stat(filename, &st) < 0) { | 1438 | if (stat(filename, &st) < 0) { |
1438 | debug3("no such identity: %s", filename); | 1439 | (userprovided ? logit : debug3)("no such identity: %s: %s", |
1440 | filename, strerror(errno)); | ||
1439 | return NULL; | 1441 | return NULL; |
1440 | } | 1442 | } |
1441 | private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok); | 1443 | private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok); |
@@ -1475,7 +1477,7 @@ load_identity_file(char *filename) | |||
1475 | static void | 1477 | static void |
1476 | pubkey_prepare(Authctxt *authctxt) | 1478 | pubkey_prepare(Authctxt *authctxt) |
1477 | { | 1479 | { |
1478 | Identity *id; | 1480 | Identity *id, *id2, *tmp; |
1479 | Idlist agent, files, *preferred; | 1481 | Idlist agent, files, *preferred; |
1480 | Key *key; | 1482 | Key *key; |
1481 | AuthenticationConnection *ac; | 1483 | AuthenticationConnection *ac; |
@@ -1487,7 +1489,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1487 | preferred = &authctxt->keys; | 1489 | preferred = &authctxt->keys; |
1488 | TAILQ_INIT(preferred); /* preferred order of keys */ | 1490 | TAILQ_INIT(preferred); /* preferred order of keys */ |
1489 | 1491 | ||
1490 | /* list of keys stored in the filesystem */ | 1492 | /* list of keys stored in the filesystem and PKCS#11 */ |
1491 | for (i = 0; i < options.num_identity_files; i++) { | 1493 | for (i = 0; i < options.num_identity_files; i++) { |
1492 | if (options.identity_files[i] == NULL) | 1494 | if (options.identity_files[i] == NULL) |
1493 | continue; | 1495 | continue; |
@@ -1500,8 +1502,32 @@ pubkey_prepare(Authctxt *authctxt) | |||
1500 | id = xcalloc(1, sizeof(*id)); | 1502 | id = xcalloc(1, sizeof(*id)); |
1501 | id->key = key; | 1503 | id->key = key; |
1502 | id->filename = xstrdup(options.identity_files[i]); | 1504 | id->filename = xstrdup(options.identity_files[i]); |
1505 | id->userprovided = 1; | ||
1503 | TAILQ_INSERT_TAIL(&files, id, next); | 1506 | TAILQ_INSERT_TAIL(&files, id, next); |
1504 | } | 1507 | } |
1508 | /* Prefer PKCS11 keys that are explicitly listed */ | ||
1509 | TAILQ_FOREACH_SAFE(id, &files, next, tmp) { | ||
1510 | if (id->key == NULL || (id->key->flags & KEY_FLAG_EXT) == 0) | ||
1511 | continue; | ||
1512 | found = 0; | ||
1513 | TAILQ_FOREACH(id2, &files, next) { | ||
1514 | if (id2->key == NULL || | ||
1515 | (id2->key->flags & KEY_FLAG_EXT) != 0) | ||
1516 | continue; | ||
1517 | if (key_equal(id->key, id2->key)) { | ||
1518 | TAILQ_REMOVE(&files, id, next); | ||
1519 | TAILQ_INSERT_TAIL(preferred, id, next); | ||
1520 | found = 1; | ||
1521 | break; | ||
1522 | } | ||
1523 | } | ||
1524 | /* If IdentitiesOnly set and key not found then don't use it */ | ||
1525 | if (!found && options.identities_only) { | ||
1526 | TAILQ_REMOVE(&files, id, next); | ||
1527 | bzero(id, sizeof(id)); | ||
1528 | free(id); | ||
1529 | } | ||
1530 | } | ||
1505 | /* list of keys supported by the agent */ | 1531 | /* list of keys supported by the agent */ |
1506 | if ((ac = ssh_get_authentication_connection())) { | 1532 | if ((ac = ssh_get_authentication_connection())) { |
1507 | for (key = ssh_get_first_identity(ac, &comment, 2); | 1533 | for (key = ssh_get_first_identity(ac, &comment, 2); |
@@ -1541,7 +1567,8 @@ pubkey_prepare(Authctxt *authctxt) | |||
1541 | TAILQ_INSERT_TAIL(preferred, id, next); | 1567 | TAILQ_INSERT_TAIL(preferred, id, next); |
1542 | } | 1568 | } |
1543 | TAILQ_FOREACH(id, preferred, next) { | 1569 | TAILQ_FOREACH(id, preferred, next) { |
1544 | debug2("key: %s (%p)", id->filename, id->key); | 1570 | debug2("key: %s (%p),%s", id->filename, id->key, |
1571 | id->userprovided ? " explicit" : ""); | ||
1545 | } | 1572 | } |
1546 | } | 1573 | } |
1547 | 1574 | ||
@@ -1586,7 +1613,8 @@ userauth_pubkey(Authctxt *authctxt) | |||
1586 | sent = send_pubkey_test(authctxt, id); | 1613 | sent = send_pubkey_test(authctxt, id); |
1587 | } else if (id->key == NULL && id->filename) { | 1614 | } else if (id->key == NULL && id->filename) { |
1588 | debug("Trying private key: %s", id->filename); | 1615 | debug("Trying private key: %s", id->filename); |
1589 | id->key = load_identity_file(id->filename); | 1616 | id->key = load_identity_file(id->filename, |
1617 | id->userprovided); | ||
1590 | if (id->key != NULL) { | 1618 | if (id->key != NULL) { |
1591 | id->isprivate = 1; | 1619 | id->isprivate = 1; |
1592 | sent = sign_and_send_pubkey(authctxt, id); | 1620 | sent = sign_and_send_pubkey(authctxt, id); |