source: ntrip/trunk/BNC/src/bncnetqueryv2.cpp@ 9851

Last change on this file since 9851 was 9795, checked in by stuerze, 21 months ago

consideration of client SSL certificates, if they are available

File size: 8.1 KB
Line 
1/* -------------------------------------------------------------------------
2 * BKG NTRIP Client
3 * -------------------------------------------------------------------------
4 *
5 * Class: bncNetQueryV2
6 *
7 * Purpose: Blocking Network Requests (NTRIP Version 2)
8 *
9 * Author: L. Mervart
10 *
11 * Created: 27-Dec-2008
12 *
13 * Changes:
14 *
15 * -----------------------------------------------------------------------*/
16
17#include <iostream>
18
19#include "bncnetqueryv2.h"
20#include "bncsettings.h"
21#include "bncversion.h"
22#include "bncsslconfig.h"
23#include "bncsettings.h"
24
25// Constructor
26////////////////////////////////////////////////////////////////////////////
27bncNetQueryV2::bncNetQueryV2(bool secure) {
28 _secure = secure;
29 _manager = new QNetworkAccessManager(this);
30 connect(_manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
31 this, SLOT(slotProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
32 _reply = 0;
33 _eventLoop = new QEventLoop(this);
34 _firstData = true;
35 _status = init;
36
37 bncSettings settings;
38 _sslIgnoreErrors = (Qt::CheckState(settings.value("sslIgnoreErrors").toInt()) == Qt::Checked);
39
40 if (_secure ) {
41 if (!QSslSocket::supportsSsl()) {
42 BNC_CORE->slotMessage("No SSL support, install OpenSSL run-time libraries", true);
43 stop();
44 }
45 // Generate filenames to consider a potential client certificate
46 _crtFileName = settings.value("sslClientCertPath").toString() + _url.host() + QString(".%1.crt").arg(_url.port());
47 _keyFileName = settings.value("sslClientCertPath").toString() + _url.host() + QString(".%1.key").arg(_url.port());
48 }
49
50
51}
52
53// Destructor
54////////////////////////////////////////////////////////////////////////////
55bncNetQueryV2::~bncNetQueryV2() {
56 delete _eventLoop;
57 if (_reply) {
58 _reply->abort();
59 delete _reply;
60 }
61 delete _manager;
62}
63
64// Stop (quit event loop)
65////////////////////////////////////////////////////////////////////////////
66void bncNetQueryV2::stop() {
67 if (_reply) {
68 _reply->abort();
69 delete _reply;
70 _reply = 0;
71 }
72 _eventLoop->quit();
73 _status = finished;
74}
75
76// End of Request
77////////////////////////////////////////////////////////////////////////////
78void bncNetQueryV2::slotFinished() {
79 _eventLoop->quit();
80 if (_reply && _reply->error() != QNetworkReply::NoError) {
81 _status = error;
82 if (!_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().isEmpty()) {
83 emit newMessage(_url.path().toLatin1().replace(0,1,"") +
84 ": NetQueryV2: server replied: " +
85 _reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray(),
86 true);
87 } else {
88 emit newMessage(_url.path().toLatin1().replace(0,1,"") +
89 ": NetQueryV2: server replied: " +
90 _reply->errorString().toLatin1(),
91 true);
92 }
93 }
94 else {
95 _status = finished;
96 }
97}
98
99//
100////////////////////////////////////////////////////////////////////////////
101void bncNetQueryV2::slotProxyAuthenticationRequired(const QNetworkProxy&,
102 QAuthenticator*) {
103 emit newMessage("slotProxyAuthenticationRequired", true);
104}
105
106// Start request, block till the next read
107////////////////////////////////////////////////////////////////////////////
108void bncNetQueryV2::startRequest(const QUrl& url, const QByteArray& gga) {
109 startRequestPrivate(url, gga, false);
110}
111
112// Start request, block till the next read
113////////////////////////////////////////////////////////////////////////////
114void bncNetQueryV2::keepAliveRequest(const QUrl& url, const QByteArray& gga) {
115 startRequestPrivate(url, gga, false);
116}
117
118// Start Request (Private Method)
119////////////////////////////////////////////////////////////////////////////
120void bncNetQueryV2::startRequestPrivate(const QUrl& url, const QByteArray& gga,
121 bool full) {
122
123 _status = running;
124
125 // Default scheme and path
126 // -----------------------
127 _url = url;
128 if (_url.scheme().isEmpty()) {
129 if (_secure) {
130 _url.setPort(443);
131 _url.setScheme("https");
132 }
133 else {
134 _url.setScheme("http");
135 }
136 }
137 if (_url.path().isEmpty()) {
138 _url.setPath("/");
139 }
140
141 // Network Request
142 // ---------------
143 bncSslConfig sslConfig = BNC_SSL_CONFIG;
144
145 if (_secure) {
146 QFile clientCrtFile(_crtFileName);
147 QFile privateKeyFile(_keyFileName);
148 if ( clientCrtFile.exists() && privateKeyFile.exists()) {
149 // set local certificate if available
150 clientCrtFile.open(QIODevice::ReadOnly);
151 QSslCertificate clientCrt(&clientCrtFile);
152 sslConfig.setLocalCertificate(clientCrt);
153 // set private key if available
154 privateKeyFile.open(QIODevice::ReadOnly);
155 QSslKey privateKey(&privateKeyFile, QSsl::Rsa);
156 sslConfig.setPrivateKey(privateKey);
157 }
158 }
159
160 QNetworkRequest request;
161 request.setSslConfiguration(sslConfig);
162 request.setUrl(_url);
163 request.setRawHeader("Host" , _url.host().toLatin1());
164 request.setRawHeader("Ntrip-Version", "Ntrip/2.0");
165 request.setRawHeader("User-Agent" , "NTRIP BNC/" BNCVERSION " (" BNC_OS ")");
166 if (!_url.userName().isEmpty()) {
167 QString uName = QUrl::fromPercentEncoding(_url.userName().toLatin1());
168 QString passW = QUrl::fromPercentEncoding(_url.password().toLatin1());
169 request.setRawHeader("Authorization", "Basic " +
170 (uName + ":" + passW).toLatin1().toBase64());
171 }
172 if (!gga.isEmpty()) {
173 request.setRawHeader("Ntrip-GGA", gga);
174 }
175 request.setRawHeader("Connection" , "close");
176
177 if (_reply) {
178 delete _reply;
179 _reply = 0;
180 }
181 _reply = _manager->get(request);
182
183 // Connect Signals
184 // ---------------
185 connect(_reply, SIGNAL(finished()), this, SLOT(slotFinished()));
186 connect(_reply, SIGNAL(finished()), _eventLoop, SLOT(quit()));
187 connect(_reply, SIGNAL(sslErrors(QList<QSslError>)),this, SLOT(slotSslErrors(QList<QSslError>)));
188 if (!full) {
189 connect(_reply, SIGNAL(readyRead()), _eventLoop, SLOT(quit()));
190 }
191}
192
193// Start Request, wait for its completion
194////////////////////////////////////////////////////////////////////////////
195void bncNetQueryV2::waitForRequestResult(const QUrl& url, QByteArray& outData) {
196
197 // Send Request
198 // ------------
199 startRequestPrivate(url, "", true);
200
201 // Wait Loop
202 // ---------
203 _eventLoop->exec();
204
205 // Copy Data and Return
206 // --------------------
207 if (_reply) {
208 outData = _reply->readAll();
209 }
210}
211
212// Wait for next data
213////////////////////////////////////////////////////////////////////////////
214void bncNetQueryV2::waitForReadyRead(QByteArray& outData) {
215
216 // Wait Loop
217 // ---------
218 if (!_reply->bytesAvailable()) {
219 _eventLoop->exec();
220 }
221 if (!_reply) {
222 return;
223 }
224
225 // Check NTRIPv2 error code
226 // ------------------------
227 if (_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
228 _reply->abort();
229 }
230
231 // Append Data
232 // -----------
233 else {
234 outData.append(_reply->readAll());
235 }
236}
237
238// TSL/SSL
239////////////////////////////////////////////////////////////////////////////
240void bncNetQueryV2::slotSslErrors(QList<QSslError> errors) {
241
242 QString msg = "SSL Error: ";
243 QSslCertificate cert = _reply->sslConfiguration().peerCertificate();
244 if (!cert.isNull() &&
245 cert.issuerInfo(QSslCertificate::OrganizationalUnitName).count() &&
246 cert.issuerInfo(QSslCertificate::Organization).count()) {
247
248 msg += QString("Server Certificate Issued by:\n"
249 "%1\n%2\nCannot be verified\n")
250#if QT_VERSION >= 0x050000
251 .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName).at(0))
252 .arg(cert.issuerInfo(QSslCertificate::Organization).at(0));
253#else
254 .arg(cert.issuerInfo(QSslCertificate::OrganizationalUnitName))
255 .arg(cert.issuerInfo(QSslCertificate::Organization));
256#endif
257 }
258
259 QListIterator<QSslError> it(errors);
260 while (it.hasNext()) {
261 const QSslError& err = it.next();
262 msg += err.errorString();
263 }
264
265 if (_sslIgnoreErrors) {
266 _reply->ignoreSslErrors();
267 BNC_CORE->slotMessage("BNC ignores SSL errors as configured", true);
268 }
269 else {
270 BNC_CORE->slotMessage(msg.toLatin1(), true);
271 stop();
272 }
273 return;
274}
Note: See TracBrowser for help on using the repository browser.