@@ -57,21 +57,6 @@ const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
57
57
const char * BIP71_MIMETYPE_PAYMENT = " application/bitcoin-payment" ;
58
58
const char * BIP71_MIMETYPE_PAYMENTACK = " application/bitcoin-paymentack" ;
59
59
const char * BIP71_MIMETYPE_PAYMENTREQUEST = " application/bitcoin-paymentrequest" ;
60
-
61
- struct X509StoreDeleter {
62
- void operator ()(X509_STORE* b) {
63
- X509_STORE_free (b);
64
- }
65
- };
66
-
67
- struct X509Deleter {
68
- void operator ()(X509* b) { X509_free (b); }
69
- };
70
-
71
- namespace // Anon namespace
72
- {
73
- std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
74
- }
75
60
#endif
76
61
77
62
//
@@ -99,96 +84,6 @@ static QString ipcServerName()
99
84
100
85
static QList<QString> savedPaymentRequests;
101
86
102
- #ifdef ENABLE_BIP70
103
- static void ReportInvalidCertificate (const QSslCertificate& cert)
104
- {
105
- qDebug () << QString (" %1: Payment server found an invalid certificate: " ).arg (__func__) << cert.serialNumber () << cert.subjectInfo (QSslCertificate::CommonName) << cert.subjectInfo (QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo (QSslCertificate::OrganizationalUnitName);
106
- }
107
-
108
- //
109
- // Load OpenSSL's list of root certificate authorities
110
- //
111
- void PaymentServer::LoadRootCAs (X509_STORE* _store)
112
- {
113
- // Unit tests mostly use this, to pass in fake root CAs:
114
- if (_store)
115
- {
116
- certStore.reset (_store);
117
- return ;
118
- }
119
-
120
- // Normal execution, use either -rootcertificates or system certs:
121
- certStore.reset (X509_STORE_new ());
122
-
123
- // Note: use "-system-" default here so that users can pass -rootcertificates=""
124
- // and get 'I don't like X.509 certificates, don't trust anybody' behavior:
125
- QString certFile = QString::fromStdString (gArgs .GetArg (" -rootcertificates" , " -system-" ));
126
-
127
- // Empty store
128
- if (certFile.isEmpty ()) {
129
- qDebug () << QString (" PaymentServer::%1: Payment request authentication via X.509 certificates disabled." ).arg (__func__);
130
- return ;
131
- }
132
-
133
- QList<QSslCertificate> certList;
134
-
135
- if (certFile != " -system-" ) {
136
- qDebug () << QString (" PaymentServer::%1: Using \" %2\" as trusted root certificate." ).arg (__func__).arg (certFile);
137
-
138
- certList = QSslCertificate::fromPath (certFile);
139
- // Use those certificates when fetching payment requests, too:
140
- QSslSocket::setDefaultCaCertificates (certList);
141
- } else
142
- certList = QSslSocket::systemCaCertificates ();
143
-
144
- int nRootCerts = 0 ;
145
- const QDateTime currentTime = QDateTime::currentDateTime ();
146
-
147
- for (const QSslCertificate& cert : certList) {
148
- // Don't log NULL certificates
149
- if (cert.isNull ())
150
- continue ;
151
-
152
- // Not yet active/valid, or expired certificate
153
- if (currentTime < cert.effectiveDate () || currentTime > cert.expiryDate ()) {
154
- ReportInvalidCertificate (cert);
155
- continue ;
156
- }
157
-
158
- // Blacklisted certificate
159
- if (cert.isBlacklisted ()) {
160
- ReportInvalidCertificate (cert);
161
- continue ;
162
- }
163
- QByteArray certData = cert.toDer ();
164
- const unsigned char *data = (const unsigned char *)certData.data ();
165
-
166
- std::unique_ptr<X509, X509Deleter> x509 (d2i_X509 (0 , &data, certData.size ()));
167
- if (x509 && X509_STORE_add_cert (certStore.get (), x509.get ()))
168
- {
169
- // Note: X509_STORE increases the reference count to the X509 object,
170
- // we still have to release our reference to it.
171
- ++nRootCerts;
172
- }
173
- else
174
- {
175
- ReportInvalidCertificate (cert);
176
- continue ;
177
- }
178
- }
179
- qWarning () << " PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates" ;
180
-
181
- // Project for another day:
182
- // Fetch certificate revocation lists, and add them to certStore.
183
- // Issues to consider:
184
- // performance (start a thread to fetch in background?)
185
- // privacy (fetch through tor/proxy so IP address isn't revealed)
186
- // would it be easier to just use a compiled-in blacklist?
187
- // or use Qt's blacklist?
188
- // "certificate stapling" with server-side caching is more efficient
189
- }
190
- #endif
191
-
192
87
//
193
88
// Sending to the server is done synchronously, at startup.
194
89
// If the server isn't already running, startup continues,
@@ -300,10 +195,10 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
300
195
QObject(parent),
301
196
saveURIs(true ),
302
197
uriServer(0 ),
198
+ optionsModel(0 )
303
199
#ifdef ENABLE_BIP70
304
- netManager (0 ),
200
+ , netManager(0 )
305
201
#endif
306
- optionsModel (0 )
307
202
{
308
203
#ifdef ENABLE_BIP70
309
204
// Verify that the version of the library that we linked against is
@@ -367,32 +262,6 @@ bool PaymentServer::eventFilter(QObject *object, QEvent *event)
367
262
return QObject::eventFilter (object, event);
368
263
}
369
264
370
- #ifdef ENABLE_BIP70
371
- void PaymentServer::initNetManager ()
372
- {
373
- if (!optionsModel)
374
- return ;
375
- delete netManager;
376
-
377
- // netManager is used to fetch paymentrequests given in bitcoin: URIs
378
- netManager = new QNetworkAccessManager (this );
379
-
380
- QNetworkProxy proxy;
381
-
382
- // Query active SOCKS5 proxy
383
- if (optionsModel->getProxySettings (proxy)) {
384
- netManager->setProxy (proxy);
385
-
386
- qDebug () << " PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName () << " :" << proxy.port ();
387
- }
388
- else
389
- qDebug () << " PaymentServer::initNetManager: No active proxy server found." ;
390
-
391
- connect (netManager, &QNetworkAccessManager::finished, this , &PaymentServer::netRequestFinished);
392
- connect (netManager, &QNetworkAccessManager::sslErrors, this , &PaymentServer::reportSslErrors);
393
- }
394
- #endif
395
-
396
265
void PaymentServer::uiReady ()
397
266
{
398
267
#ifdef ENABLE_BIP70
@@ -510,7 +379,140 @@ void PaymentServer::handleURIConnection()
510
379
handleURIOrFile (msg);
511
380
}
512
381
382
+ void PaymentServer::setOptionsModel (OptionsModel *_optionsModel)
383
+ {
384
+ this ->optionsModel = _optionsModel;
385
+ }
386
+
513
387
#ifdef ENABLE_BIP70
388
+ struct X509StoreDeleter {
389
+ void operator ()(X509_STORE* b) {
390
+ X509_STORE_free (b);
391
+ }
392
+ };
393
+
394
+ struct X509Deleter {
395
+ void operator ()(X509* b) { X509_free (b); }
396
+ };
397
+
398
+ namespace // Anon namespace
399
+ {
400
+ std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
401
+ }
402
+
403
+ static void ReportInvalidCertificate (const QSslCertificate& cert)
404
+ {
405
+ qDebug () << QString (" %1: Payment server found an invalid certificate: " ).arg (__func__) << cert.serialNumber () << cert.subjectInfo (QSslCertificate::CommonName) << cert.subjectInfo (QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo (QSslCertificate::OrganizationalUnitName);
406
+ }
407
+
408
+ //
409
+ // Load OpenSSL's list of root certificate authorities
410
+ //
411
+ void PaymentServer::LoadRootCAs (X509_STORE* _store)
412
+ {
413
+ // Unit tests mostly use this, to pass in fake root CAs:
414
+ if (_store)
415
+ {
416
+ certStore.reset (_store);
417
+ return ;
418
+ }
419
+
420
+ // Normal execution, use either -rootcertificates or system certs:
421
+ certStore.reset (X509_STORE_new ());
422
+
423
+ // Note: use "-system-" default here so that users can pass -rootcertificates=""
424
+ // and get 'I don't like X.509 certificates, don't trust anybody' behavior:
425
+ QString certFile = QString::fromStdString (gArgs .GetArg (" -rootcertificates" , " -system-" ));
426
+
427
+ // Empty store
428
+ if (certFile.isEmpty ()) {
429
+ qDebug () << QString (" PaymentServer::%1: Payment request authentication via X.509 certificates disabled." ).arg (__func__);
430
+ return ;
431
+ }
432
+
433
+ QList<QSslCertificate> certList;
434
+
435
+ if (certFile != " -system-" ) {
436
+ qDebug () << QString (" PaymentServer::%1: Using \" %2\" as trusted root certificate." ).arg (__func__).arg (certFile);
437
+
438
+ certList = QSslCertificate::fromPath (certFile);
439
+ // Use those certificates when fetching payment requests, too:
440
+ QSslSocket::setDefaultCaCertificates (certList);
441
+ } else
442
+ certList = QSslSocket::systemCaCertificates ();
443
+
444
+ int nRootCerts = 0 ;
445
+ const QDateTime currentTime = QDateTime::currentDateTime ();
446
+
447
+ for (const QSslCertificate& cert : certList) {
448
+ // Don't log NULL certificates
449
+ if (cert.isNull ())
450
+ continue ;
451
+
452
+ // Not yet active/valid, or expired certificate
453
+ if (currentTime < cert.effectiveDate () || currentTime > cert.expiryDate ()) {
454
+ ReportInvalidCertificate (cert);
455
+ continue ;
456
+ }
457
+
458
+ // Blacklisted certificate
459
+ if (cert.isBlacklisted ()) {
460
+ ReportInvalidCertificate (cert);
461
+ continue ;
462
+ }
463
+
464
+ QByteArray certData = cert.toDer ();
465
+ const unsigned char *data = (const unsigned char *)certData.data ();
466
+
467
+ std::unique_ptr<X509, X509Deleter> x509 (d2i_X509 (0 , &data, certData.size ()));
468
+ if (x509 && X509_STORE_add_cert (certStore.get (), x509.get ()))
469
+ {
470
+ // Note: X509_STORE increases the reference count to the X509 object,
471
+ // we still have to release our reference to it.
472
+ ++nRootCerts;
473
+ }
474
+ else
475
+ {
476
+ ReportInvalidCertificate (cert);
477
+ continue ;
478
+ }
479
+ }
480
+ qWarning () << " PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates" ;
481
+
482
+ // Project for another day:
483
+ // Fetch certificate revocation lists, and add them to certStore.
484
+ // Issues to consider:
485
+ // performance (start a thread to fetch in background?)
486
+ // privacy (fetch through tor/proxy so IP address isn't revealed)
487
+ // would it be easier to just use a compiled-in blacklist?
488
+ // or use Qt's blacklist?
489
+ // "certificate stapling" with server-side caching is more efficient
490
+ }
491
+
492
+ void PaymentServer::initNetManager ()
493
+ {
494
+ if (!optionsModel)
495
+ return ;
496
+ delete netManager;
497
+
498
+ // netManager is used to fetch paymentrequests given in bitcoin: URIs
499
+ netManager = new QNetworkAccessManager (this );
500
+
501
+ QNetworkProxy proxy;
502
+
503
+ // Query active SOCKS5 proxy
504
+ if (optionsModel->getProxySettings (proxy)) {
505
+ netManager->setProxy (proxy);
506
+
507
+ qDebug () << " PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName () << " :" << proxy.port ();
508
+ }
509
+ else
510
+ qDebug () << " PaymentServer::initNetManager: No active proxy server found." ;
511
+
512
+ connect (netManager, &QNetworkAccessManager::finished, this , &PaymentServer::netRequestFinished);
513
+ connect (netManager, &QNetworkAccessManager::sslErrors, this , &PaymentServer::reportSslErrors);
514
+ }
515
+
514
516
//
515
517
// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine()
516
518
// so don't use "Q_EMIT message()", but "QMessageBox::"!
@@ -760,14 +762,7 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
760
762
}
761
763
Q_EMIT message (tr (" Network request error" ), errString, CClientUIInterface::MSG_ERROR);
762
764
}
763
- #endif
764
-
765
- void PaymentServer::setOptionsModel (OptionsModel *_optionsModel)
766
- {
767
- this ->optionsModel = _optionsModel;
768
- }
769
765
770
- #ifdef ENABLE_BIP70
771
766
void PaymentServer::handlePaymentACK (const QString& paymentACKMsg)
772
767
{
773
768
// currently we don't further process or store the paymentACK message
0 commit comments