SSH: Print more helpful error message on key decoding error.

The botan exception string doesn't help anybody.

Change-Id: I81b8b837b0cf3406a8293cbf85b8fd1bff9bfa74
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Christian Kandeler
2011-12-07 17:08:08 +01:00
committed by hjk
parent c2cfceb6b2
commit 16ad21be9d
3 changed files with 101 additions and 94 deletions

View File

@@ -640,11 +640,6 @@ void SshConnectionPrivate::connectToHost()
m_errorString = ex.errorString; m_errorString = ex.errorString;
emit error(m_error); emit error(m_error);
return; return;
} catch (const Botan::Exception &ex) {
m_error = SshKeyFileError;
m_errorString = QString::fromAscii(ex.what());
emit error(m_error);
return;
} }
connect(m_socket, SIGNAL(connected()), this, SLOT(handleSocketConnected())); connect(m_socket, SIGNAL(connected()), this, SLOT(handleSocketConnected()));

View File

@@ -200,18 +200,22 @@ void SshEncryptionFacility::createAuthenticationKey(const QByteArray &privKeyFil
#endif #endif
QList<BigInt> pubKeyParams; QList<BigInt> pubKeyParams;
QList<BigInt> allKeyParams; QList<BigInt> allKeyParams;
try { QString error1;
createAuthenticationKeyFromPKCS8(privKeyFileContents, pubKeyParams, QString error2;
allKeyParams); if (!createAuthenticationKeyFromPKCS8(privKeyFileContents, pubKeyParams, allKeyParams, error1)
} catch (Botan::Exception &) { && !createAuthenticationKeyFromOpenSSL(privKeyFileContents, pubKeyParams, allKeyParams,
createAuthenticationKeyFromOpenSSL(privKeyFileContents, pubKeyParams, error2)) {
allKeyParams); #ifdef CREATOR_SSH_DEBUG
qDebug("%s: %s\n\t%s\n", Q_FUNC_INFO, qPrintable(error1), qPrintable(error2));
#endif
throw SshClientException(SshKeyFileError, SSH_TR("Decoding of private key file failed: "
"Format not understood."));
} }
foreach (const BigInt &b, allKeyParams) { foreach (const BigInt &b, allKeyParams) {
if (b.is_zero()) { if (b.is_zero()) {
throw SshClientException(SshKeyFileError, throw SshClientException(SshKeyFileError,
SSH_TR("Decoding of private key file failed.")); SSH_TR("Decoding of private key file failed: Invalid zero parameter."));
} }
} }
@@ -221,93 +225,101 @@ void SshEncryptionFacility::createAuthenticationKey(const QByteArray &privKeyFil
m_cachedPrivKeyContents = privKeyFileContents; m_cachedPrivKeyContents = privKeyFileContents;
} }
void SshEncryptionFacility::createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents, bool SshEncryptionFacility::createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents,
QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams) QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams, QString &error)
{ {
Pipe pipe; try {
pipe.process_msg(convertByteArray(privKeyFileContents), Pipe pipe;
privKeyFileContents.size()); pipe.process_msg(convertByteArray(privKeyFileContents), privKeyFileContents.size());
Private_Key * const key = PKCS8::load_key(pipe, m_rng, SshKeyPasswordRetriever()); Private_Key * const key = PKCS8::load_key(pipe, m_rng, SshKeyPasswordRetriever());
if (DSA_PrivateKey * const dsaKey = dynamic_cast<DSA_PrivateKey *>(key)) { if (DSA_PrivateKey * const dsaKey = dynamic_cast<DSA_PrivateKey *>(key)) {
m_authKeyAlgoName = SshCapabilities::PubKeyDss; m_authKeyAlgoName = SshCapabilities::PubKeyDss;
m_authKey.reset(dsaKey); m_authKey.reset(dsaKey);
pubKeyParams << dsaKey->group_p() << dsaKey->group_q() pubKeyParams << dsaKey->group_p() << dsaKey->group_q()
<< dsaKey->group_g() << dsaKey->get_y(); << dsaKey->group_g() << dsaKey->get_y();
allKeyParams << pubKeyParams << dsaKey->get_x(); allKeyParams << pubKeyParams << dsaKey->get_x();
} else if (RSA_PrivateKey * const rsaKey = dynamic_cast<RSA_PrivateKey *>(key)) { } else if (RSA_PrivateKey * const rsaKey = dynamic_cast<RSA_PrivateKey *>(key)) {
m_authKeyAlgoName = SshCapabilities::PubKeyRsa; m_authKeyAlgoName = SshCapabilities::PubKeyRsa;
m_authKey.reset(rsaKey); m_authKey.reset(rsaKey);
pubKeyParams << rsaKey->get_e() << rsaKey->get_n(); pubKeyParams << rsaKey->get_e() << rsaKey->get_n();
allKeyParams << pubKeyParams << rsaKey->get_p() << rsaKey->get_q() allKeyParams << pubKeyParams << rsaKey->get_p() << rsaKey->get_q()
<< rsaKey->get_d(); << rsaKey->get_d();
} else { } else {
throw Botan::Exception(); qWarning("%s: Unexpected code flow, expected success or exception.", Q_FUNC_INFO);
return false;
}
} catch (const Botan::Exception &ex) {
error = QLatin1String(ex.what());
return false;
} }
return true;
} }
void SshEncryptionFacility::createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents, bool SshEncryptionFacility::createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents,
QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams) QList<BigInt> &pubKeyParams, QList<BigInt> &allKeyParams, QString &error)
{ {
bool syntaxOk = true; try {
QList<QByteArray> lines = privKeyFileContents.split('\n'); bool syntaxOk = true;
while (lines.last().isEmpty()) QList<QByteArray> lines = privKeyFileContents.split('\n');
lines.removeLast(); while (lines.last().isEmpty())
if (lines.count() < 3) { lines.removeLast();
syntaxOk = false; if (lines.count() < 3) {
} else if (lines.first() == PrivKeyFileStartLineRsa) {
if (lines.last() != PrivKeyFileEndLineRsa)
syntaxOk =false;
else
m_authKeyAlgoName = SshCapabilities::PubKeyRsa;
} else if (lines.first() == PrivKeyFileStartLineDsa) {
if (lines.last() != PrivKeyFileEndLineDsa)
syntaxOk = false; syntaxOk = false;
else } else if (lines.first() == PrivKeyFileStartLineRsa) {
m_authKeyAlgoName = SshCapabilities::PubKeyDss; if (lines.last() != PrivKeyFileEndLineRsa)
} else { syntaxOk = false;
syntaxOk = false; else
} m_authKeyAlgoName = SshCapabilities::PubKeyRsa;
if (!syntaxOk) { } else if (lines.first() == PrivKeyFileStartLineDsa) {
throw SshClientException(SshKeyFileError, if (lines.last() != PrivKeyFileEndLineDsa)
SSH_TR("Private key file has unexpected format.")); syntaxOk = false;
} else
m_authKeyAlgoName = SshCapabilities::PubKeyDss;
} else {
syntaxOk = false;
}
if (!syntaxOk) {
error = SSH_TR("Unexpected format.");
return false;
}
QByteArray privateKeyBlob; QByteArray privateKeyBlob;
for (int i = 1; i < lines.size() - 1; ++i) for (int i = 1; i < lines.size() - 1; ++i)
privateKeyBlob += lines.at(i); privateKeyBlob += lines.at(i);
privateKeyBlob = QByteArray::fromBase64(privateKeyBlob); privateKeyBlob = QByteArray::fromBase64(privateKeyBlob);
BER_Decoder decoder(convertByteArray(privateKeyBlob), BER_Decoder decoder(convertByteArray(privateKeyBlob), privateKeyBlob.size());
privateKeyBlob.size()); BER_Decoder sequence = decoder.start_cons(SEQUENCE);
BER_Decoder sequence = decoder.start_cons(SEQUENCE); quint32 version;
quint32 version; sequence.decode (version);
sequence.decode (version); if (version != 0) {
if (version != 0) { error = SSH_TR("Key encoding has version %1, expected 0.").arg(version);
throw SshClientException(SshKeyFileError, return false;
SSH_TR("Private key encoding has version %1, expected 0.") }
.arg(version));
if (m_authKeyAlgoName == SshCapabilities::PubKeyDss) {
BigInt p, q, g, y, x;
sequence.decode (p).decode (q).decode (g).decode (y).decode (x);
DSA_PrivateKey * const dsaKey = new DSA_PrivateKey(m_rng, DL_Group(p, q, g), x);
m_authKey.reset(dsaKey);
pubKeyParams << p << q << g << y;
allKeyParams << pubKeyParams << x;
} else {
BigInt p, q, e, d, n;
sequence.decode(n).decode(e).decode(d).decode(p).decode(q);
RSA_PrivateKey * const rsaKey = new RSA_PrivateKey(m_rng, p, q, e, d, n);
m_authKey.reset(rsaKey);
pubKeyParams << e << n;
allKeyParams << pubKeyParams << p << q << d;
}
sequence.discard_remaining();
sequence.verify_end();
} catch (const Botan::Exception &ex) {
error = QLatin1String(ex.what());
return false;
} }
return true;
if (m_authKeyAlgoName == SshCapabilities::PubKeyDss) {
BigInt p, q, g, y, x;
sequence.decode (p).decode (q).decode (g).decode (y).decode (x);
DSA_PrivateKey * const dsaKey
= new DSA_PrivateKey(m_rng, DL_Group(p, q, g), x);
m_authKey.reset(dsaKey);
pubKeyParams << p << q << g << y;
allKeyParams << pubKeyParams << x;
} else {
BigInt p, q, e, d, n;
sequence.decode (n).decode (e).decode (d).decode (p).decode (q);
RSA_PrivateKey * const rsaKey
= new RSA_PrivateKey (m_rng, p, q, e, d, n);
m_authKey.reset(rsaKey);
pubKeyParams << e << n;
allKeyParams << pubKeyParams << p << q << d;
}
sequence.discard_remaining();
sequence.verify_end();
} }
QByteArray SshEncryptionFacility::authenticationAlgorithmName() const QByteArray SshEncryptionFacility::authenticationAlgorithmName() const

View File

@@ -118,10 +118,10 @@ private:
virtual char keyChar() const { return 'C'; } virtual char keyChar() const { return 'C'; }
virtual char macChar() const { return 'E'; } virtual char macChar() const { return 'E'; }
void createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents, bool createAuthenticationKeyFromPKCS8(const QByteArray &privKeyFileContents,
QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams); QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams, QString &error);
void createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents, bool createAuthenticationKeyFromOpenSSL(const QByteArray &privKeyFileContents,
QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams); QList<Botan::BigInt> &pubKeyParams, QList<Botan::BigInt> &allKeyParams, QString &error);
static const QByteArray PrivKeyFileStartLineRsa; static const QByteArray PrivKeyFileStartLineRsa;
static const QByteArray PrivKeyFileStartLineDsa; static const QByteArray PrivKeyFileStartLineDsa;