]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream commit
authordjm@openbsd.org <djm@openbsd.org>
Fri, 10 Feb 2017 04:34:50 +0000 (04:34 +0000)
committerDamien Miller <djm@mindrot.org>
Fri, 10 Feb 2017 04:35:28 +0000 (15:35 +1100)
bring back r1.34 that was backed out for problems loading
public keys:

translate OpenSSL error codes to something more
meaninful; bz#2522 reported by Jakub Jelen, ok dtucker@

with additional fix from Jakub Jelen to solve the backout.
bz#2525 bz#2523 re-ok dtucker@

Upstream-ID: a9d5bc0306f4473d9b4f4484f880e95f3c1cc031

sshkey.c

index c01da6c39b2e9950e81caa16de7bab8e9458abb4..05675920f2484ae272d3bcd80669306c933894a0 100644 (file)
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.41 2016/10/24 01:09:17 dtucker Exp $ */
+/* $OpenBSD: sshkey.c,v 1.42 2017/02/10 04:34:50 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -3786,7 +3786,44 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
 
        if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
            (char *)passphrase)) == NULL) {
-               r = SSH_ERR_KEY_WRONG_PASSPHRASE;
+               unsigned long pem_err = ERR_peek_last_error();
+               int pem_reason = ERR_GET_REASON(pem_err);
+
+               /*
+                * Translate OpenSSL error codes to determine whether
+                * passphrase is required/incorrect.
+                */
+               switch (ERR_GET_LIB(pem_err)) {
+               case ERR_LIB_PEM:
+                       switch (pem_reason) {
+                       case PEM_R_BAD_PASSWORD_READ:
+                       case PEM_R_PROBLEMS_GETTING_PASSWORD:
+                       case PEM_R_BAD_DECRYPT:
+                               r = SSH_ERR_KEY_WRONG_PASSPHRASE;
+                               goto out;
+                       default:
+                               r = SSH_ERR_INVALID_FORMAT;
+                               goto out;
+                       }
+               case ERR_LIB_EVP:
+                       switch (pem_reason) {
+                       case EVP_R_BAD_DECRYPT:
+                               r = SSH_ERR_KEY_WRONG_PASSPHRASE;
+                               goto out;
+                       case EVP_R_BN_DECODE_ERROR:
+                       case EVP_R_DECODE_ERROR:
+                       case EVP_R_PRIVATE_KEY_DECODE_ERROR:
+                               r = SSH_ERR_INVALID_FORMAT;
+                               goto out;
+                       default:
+                               r = SSH_ERR_LIBCRYPTO_ERROR;
+                               goto out;
+                       }
+               case ERR_LIB_ASN1:
+                       r = SSH_ERR_INVALID_FORMAT;
+                       goto out;
+               }
+               r = SSH_ERR_LIBCRYPTO_ERROR;
                goto out;
        }
        if (pk->type == EVP_PKEY_RSA &&
@@ -3860,6 +3897,8 @@ int
 sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
     const char *passphrase, struct sshkey **keyp, char **commentp)
 {
+       int r = SSH_ERR_INTERNAL_ERROR;
+
        if (keyp != NULL)
                *keyp = NULL;
        if (commentp != NULL)
@@ -3882,9 +3921,11 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
                return sshkey_parse_private2(blob, type, passphrase,
                    keyp, commentp);
        case KEY_UNSPEC:
-               if (sshkey_parse_private2(blob, type, passphrase, keyp,
-                   commentp) == 0)
-                       return 0;
+               r = sshkey_parse_private2(blob, type, passphrase, keyp,
+                   commentp);
+               /* Do not fallback to PEM parser if only passphrase is wrong. */
+               if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE)
+                       return r;
 #ifdef WITH_OPENSSL
                return sshkey_parse_private_pem_fileblob(blob, type,
                    passphrase, keyp);