~ubuntu-branches/debian/sid/bitcoin/sid

« back to all changes in this revision

Viewing changes to src/qt/paymentrequestplus.cpp

  • Committer: Package Import Robot
  • Author(s): Scott Howard
  • Date: 2015-07-29 15:45:52 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20150729154552-p5t8q38o0ekh1f09
Tags: 0.11.0-1
* New upstream release (Closes: #793622)
  - build on all archs, big endian is now supported
* Updated symbols file
* Added bitcoin-cli.1 manpage from contrib/debian/manpages
* Updated debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright (c) 2011-2014 The Bitcoin developers
 
1
// Copyright (c) 2011-2014 The Bitcoin Core developers
2
2
// Distributed under the MIT software license, see the accompanying
3
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
4
 
9
9
 
10
10
#include "paymentrequestplus.h"
11
11
 
 
12
#include "util.h"
 
13
 
12
14
#include <stdexcept>
13
15
 
14
 
#include <openssl/x509.h>
15
16
#include <openssl/x509_vfy.h>
16
17
 
17
18
#include <QDateTime>
30
31
{
31
32
    bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size());
32
33
    if (!parseOK) {
33
 
        qWarning() << "PaymentRequestPlus::parse : Error parsing payment request";
 
34
        qWarning() << "PaymentRequestPlus::parse: Error parsing payment request";
34
35
        return false;
35
36
    }
36
37
    if (paymentRequest.payment_details_version() > 1) {
37
 
        qWarning() << "PaymentRequestPlus::parse : Received up-version payment details, version=" << paymentRequest.payment_details_version();
 
38
        qWarning() << "PaymentRequestPlus::parse: Received up-version payment details, version=" << paymentRequest.payment_details_version();
38
39
        return false;
39
40
    }
40
41
 
41
42
    parseOK = details.ParseFromString(paymentRequest.serialized_payment_details());
42
43
    if (!parseOK)
43
44
    {
44
 
        qWarning() << "PaymentRequestPlus::parse : Error parsing payment details";
 
45
        qWarning() << "PaymentRequestPlus::parse: Error parsing payment details";
45
46
        paymentRequest.Clear();
46
47
        return false;
47
48
    }
58
59
    return paymentRequest.IsInitialized();
59
60
}
60
61
 
61
 
QString PaymentRequestPlus::getPKIType() const
62
 
{
63
 
    if (!IsInitialized()) return QString("none");
64
 
    return QString::fromStdString(paymentRequest.pki_type());
65
 
}
66
 
 
67
62
bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const
68
63
{
69
64
    merchant.clear();
81
76
        digestAlgorithm = EVP_sha1();
82
77
    }
83
78
    else if (paymentRequest.pki_type() == "none") {
84
 
        qWarning() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none";
 
79
        qWarning() << "PaymentRequestPlus::getMerchant: Payment request: pki_type == none";
85
80
        return false;
86
81
    }
87
82
    else {
88
 
        qWarning() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
 
83
        qWarning() << "PaymentRequestPlus::getMerchant: Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
89
84
        return false;
90
85
    }
91
86
 
92
87
    payments::X509Certificates certChain;
93
88
    if (!certChain.ParseFromString(paymentRequest.pki_data())) {
94
 
        qWarning() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data";
 
89
        qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error parsing pki_data";
95
90
        return false;
96
91
    }
97
92
 
101
96
        QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
102
97
        QSslCertificate qCert(certData, QSsl::Der);
103
98
        if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
104
 
            qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert;
 
99
            qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
105
100
            return false;
106
101
        }
107
102
#if QT_VERSION >= 0x050000
108
103
        if (qCert.isBlacklisted()) {
109
 
            qWarning() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert;
 
104
            qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
110
105
            return false;
111
106
        }
112
107
#endif
116
111
            certs.push_back(cert);
117
112
    }
118
113
    if (certs.empty()) {
119
 
        qWarning() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain";
 
114
        qWarning() << "PaymentRequestPlus::getMerchant: Payment request: empty certificate chain";
120
115
        return false;
121
116
    }
122
117
 
123
118
    // The first cert is the signing cert, the rest are untrusted certs that chain
124
119
    // to a valid root authority. OpenSSL needs them separately.
125
120
    STACK_OF(X509) *chain = sk_X509_new_null();
126
 
    for (int i = certs.size()-1; i > 0; i--) {
 
121
    for (int i = certs.size() - 1; i > 0; i--) {
127
122
        sk_X509_push(chain, certs[i]);
128
123
    }
129
124
    X509 *signing_cert = certs[0];
132
127
    // load the signing cert into it and verify.
133
128
    X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
134
129
    if (!store_ctx) {
135
 
        qWarning() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX";
 
130
        qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error creating X509_STORE_CTX";
136
131
        return false;
137
132
    }
138
133
 
150
145
        int result = X509_verify_cert(store_ctx);
151
146
        if (result != 1) {
152
147
            int error = X509_STORE_CTX_get_error(store_ctx);
153
 
            throw SSLVerifyError(X509_verify_cert_error_string(error));
 
148
            // For testing payment requests, we allow self signed root certs!
 
149
            // This option is just shown in the UI options, if -help-debug is enabled.
 
150
            if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && GetBoolArg("-allowselfsignedrootcertificates", false))) {
 
151
                throw SSLVerifyError(X509_verify_cert_error_string(error));
 
152
            } else {
 
153
               qDebug() << "PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true.";
 
154
            }
154
155
        }
155
156
        X509_NAME *certname = X509_get_subject_name(signing_cert);
156
157
 
165
166
        EVP_MD_CTX_init(&ctx);
166
167
        if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) ||
167
168
            !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) ||
168
 
            !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) {
169
 
 
170
 
            throw SSLVerifyError("Bad signature, invalid PaymentRequest.");
 
169
            !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) {
 
170
            throw SSLVerifyError("Bad signature, invalid payment request.");
171
171
        }
172
172
 
173
173
        // OpenSSL API for getting human printable strings from certs is baroque.
181
181
        }
182
182
        // TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
183
183
    }
184
 
    catch (SSLVerifyError& err)
185
 
    {
 
184
    catch (const SSLVerifyError& err) {
186
185
        fResult = false;
187
 
        qWarning() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what();
 
186
        qWarning() << "PaymentRequestPlus::getMerchant: SSL error: " << err.what();
188
187
    }
189
188
 
190
189
    if (website)