@@ -57,21 +57,6 @@ const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
5757const char * BIP71_MIMETYPE_PAYMENT = " application/bitcoin-payment" ;
5858const char * BIP71_MIMETYPE_PAYMENTACK = " application/bitcoin-paymentack" ;
5959const 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- }
7560#endif
7661
7762//
@@ -99,96 +84,6 @@ static QString ipcServerName()
9984
10085static QList<QString> savedPaymentRequests;
10186
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-
19287//
19388// Sending to the server is done synchronously, at startup.
19489// If the server isn't already running, startup continues,
@@ -300,10 +195,10 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
300195 QObject(parent),
301196 saveURIs(true ),
302197 uriServer(0 ),
198+ optionsModel(0 )
303199#ifdef ENABLE_BIP70
304- netManager (0 ),
200+ , netManager(0 )
305201#endif
306- optionsModel (0 )
307202{
308203#ifdef ENABLE_BIP70
309204 // Verify that the version of the library that we linked against is
@@ -367,32 +262,6 @@ bool PaymentServer::eventFilter(QObject *object, QEvent *event)
367262 return QObject::eventFilter (object, event);
368263}
369264
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-
396265void PaymentServer::uiReady ()
397266{
398267#ifdef ENABLE_BIP70
@@ -510,7 +379,140 @@ void PaymentServer::handleURIConnection()
510379 handleURIOrFile (msg);
511380}
512381
382+ void PaymentServer::setOptionsModel (OptionsModel *_optionsModel)
383+ {
384+ this ->optionsModel = _optionsModel;
385+ }
386+
513387#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+
514516//
515517// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine()
516518// so don't use "Q_EMIT message()", but "QMessageBox::"!
@@ -760,14 +762,7 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
760762 }
761763 Q_EMIT message (tr (" Network request error" ), errString, CClientUIInterface::MSG_ERROR);
762764}
763- #endif
764-
765- void PaymentServer::setOptionsModel (OptionsModel *_optionsModel)
766- {
767- this ->optionsModel = _optionsModel;
768- }
769765
770- #ifdef ENABLE_BIP70
771766void PaymentServer::handlePaymentACK (const QString& paymentACKMsg)
772767{
773768 // currently we don't further process or store the paymentACK message
0 commit comments