~x2go/x2go/x2goclient_master

« back to all changes in this revision

Viewing changes to httpbrokerclient.cpp

  • Committer: Mihai Moldovan
  • Date: 2015-03-04 20:15:47 UTC
  • Revision ID: git-v1:b7398771a7abd84ddcff407063edb95dd0a205d3
general: move *.cpp and *.h files to src/ and *.ts files to src/i18n/.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************
2
 
*   Copyright (C) 2005-2015 by Oleksandr Shneyder                         *
3
 
*   o.shneyder@phoca-gmbh.de                                              *
4
 
*                                                                         *
5
 
*   This program is free software; you can redistribute it and/or modify  *
6
 
*   it under the terms of the GNU General Public License as published by  *
7
 
*   the Free Software Foundation; either version 2 of the License, or     *
8
 
*   (at your option) any later version.                                   *
9
 
*   This program is distributed in the hope that it will be useful,       *
10
 
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
 
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
 
*   GNU General Public License for more details.                          *
13
 
*                                                                         *
14
 
*   You should have received a copy of the GNU General Public License     *
15
 
*   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
16
 
***************************************************************************/
17
 
 
18
 
#include "httpbrokerclient.h"
19
 
#include <QNetworkAccessManager>
20
 
#include <QUrl>
21
 
#include <QNetworkRequest>
22
 
#include <QNetworkReply>
23
 
#include <QUuid>
24
 
#include <QTextStream>
25
 
#include <QFile>
26
 
#include <QDir>
27
 
#include <QSslSocket>
28
 
#include "x2gologdebug.h"
29
 
#include <QMessageBox>
30
 
#include <QDateTime>
31
 
#include "onmainwindow.h"
32
 
#include "x2gosettings.h"
33
 
#include <QDesktopWidget>
34
 
#include <QTimer>
35
 
#include "SVGFrame.h"
36
 
#include "onmainwindow.h"
37
 
#include <QTemporaryFile>
38
 
#include <QInputDialog>
39
 
 
40
 
 
41
 
HttpBrokerClient::HttpBrokerClient ( ONMainWindow* wnd, ConfigFile* cfg )
42
 
{
43
 
    config=cfg;
44
 
    mainWindow=wnd;
45
 
    sshConnection=0;
46
 
    QUrl lurl ( config->brokerurl );
47
 
    if(lurl.userName().length()>0)
48
 
        config->brokerUser=lurl.userName();
49
 
    nextAuthId=config->brokerUserId;
50
 
 
51
 
    if(config->brokerurl.indexOf("ssh://")==0)
52
 
    {
53
 
        sshBroker=true;
54
 
        x2goDebug<<"host:"<<lurl.host();
55
 
        x2goDebug<<"port:"<<lurl.port(22);
56
 
        x2goDebug<<"uname:"<<lurl.userName();
57
 
        x2goDebug<<"path:"<<lurl.path();
58
 
        config->sshBrokerBin=lurl.path();
59
 
    }
60
 
    else
61
 
    {
62
 
        sshBroker=false;
63
 
 
64
 
        if ((config->brokerCaCertFile.length() >0) && (QFile::exists(config->brokerCaCertFile))) {
65
 
            QSslSocket::addDefaultCaCertificates(config->brokerCaCertFile, QSsl::Pem);
66
 
            x2goDebug<<"Custom CA certificate file loaded into HTTPS broker client: "<<config->brokerCaCertFile;
67
 
        }
68
 
 
69
 
        http=new QNetworkAccessManager ( this );
70
 
        x2goDebug<<"Setting up connection to broker: "<<config->brokerurl;
71
 
 
72
 
        connect ( http, SIGNAL ( sslErrors ( QNetworkReply*, const QList<QSslError>& ) ),this,
73
 
                  SLOT ( slotSslErrors ( QNetworkReply*, const QList<QSslError>& ) ) );
74
 
 
75
 
        connect ( http,SIGNAL ( finished (QNetworkReply*) ),this,
76
 
                  SLOT ( slotRequestFinished (QNetworkReply*) ) );
77
 
    }
78
 
}
79
 
 
80
 
 
81
 
HttpBrokerClient::~HttpBrokerClient()
82
 
{
83
 
}
84
 
 
85
 
void HttpBrokerClient::createSshConnection()
86
 
{
87
 
    QUrl lurl ( config->brokerurl );
88
 
    sshConnection=new SshMasterConnection (this, lurl.host(), lurl.port(22),false,
89
 
                                           config->brokerUser, config->brokerPass,config->brokerSshKey,config->brokerAutologin,
90
 
                                           config->brokerKrbLogin, false);
91
 
 
92
 
    connect ( sshConnection, SIGNAL ( connectionOk(QString)), this, SLOT ( slotSshConnectionOk() ) );
93
 
    connect ( sshConnection, SIGNAL ( serverAuthError ( int,QString, SshMasterConnection* ) ),this,
94
 
              SLOT ( slotSshServerAuthError ( int,QString, SshMasterConnection* ) ) );
95
 
    connect ( sshConnection, SIGNAL ( needPassPhrase(SshMasterConnection*, bool)),this,
96
 
              SLOT ( slotSshServerAuthPassphrase(SshMasterConnection*, bool)) );
97
 
    connect ( sshConnection, SIGNAL ( userAuthError ( QString ) ),this,SLOT ( slotSshUserAuthError ( QString ) ) );
98
 
    connect ( sshConnection, SIGNAL ( connectionError(QString,QString)), this,
99
 
              SLOT ( slotSshConnectionError ( QString,QString ) ) );
100
 
    sshConnection->start();
101
 
}
102
 
 
103
 
void HttpBrokerClient::slotSshConnectionError(QString message, QString lastSessionError)
104
 
{
105
 
    if ( sshConnection )
106
 
    {
107
 
        sshConnection->wait();
108
 
        delete sshConnection;
109
 
        sshConnection=0l;
110
 
    }
111
 
 
112
 
    QMessageBox::critical ( 0l,message,lastSessionError,
113
 
                            QMessageBox::Ok,
114
 
                            QMessageBox::NoButton );
115
 
}
116
 
 
117
 
void HttpBrokerClient::slotSshConnectionOk()
118
 
{
119
 
    getUserSessions();
120
 
}
121
 
 
122
 
void HttpBrokerClient::slotSshServerAuthError(int error, QString sshMessage, SshMasterConnection* connection)
123
 
{
124
 
    QString errMsg;
125
 
    switch ( error )
126
 
    {
127
 
    case SSH_SERVER_KNOWN_CHANGED:
128
 
        errMsg=tr ( "Host key for server changed.\nIt is now: " ) +sshMessage+"\n"+
129
 
               tr ( "For security reasons, connection will be stopped" );
130
 
        connection->writeKnownHosts(false);
131
 
        connection->wait();
132
 
        if(sshConnection && sshConnection !=connection)
133
 
        {
134
 
            sshConnection->wait();
135
 
            delete sshConnection;
136
 
        }
137
 
        sshConnection=0;
138
 
        slotSshUserAuthError ( errMsg );
139
 
        return;
140
 
 
141
 
    case SSH_SERVER_FOUND_OTHER:
142
 
        errMsg=tr ( "The host key for this server was not found but an other"
143
 
                    "type of key exists.An attacker might change the default server key to"
144
 
                    "confuse your client into thinking the key does not exist" );
145
 
        connection->writeKnownHosts(false);
146
 
        connection->wait();
147
 
        if(sshConnection && sshConnection !=connection)
148
 
        {
149
 
            sshConnection->wait();
150
 
            delete sshConnection;
151
 
        }
152
 
        sshConnection=0;
153
 
        slotSshUserAuthError ( errMsg );
154
 
        return ;
155
 
 
156
 
    case SSH_SERVER_ERROR:
157
 
        connection->writeKnownHosts(false);
158
 
        connection->wait();
159
 
        if(sshConnection && sshConnection !=connection)
160
 
        {
161
 
            sshConnection->wait();
162
 
            delete sshConnection;
163
 
        }
164
 
        sshConnection=0;
165
 
        slotSshUserAuthError ( sshMessage );
166
 
        return ;
167
 
    case SSH_SERVER_FILE_NOT_FOUND:
168
 
        errMsg=tr ( "Could not find known host file."
169
 
                    "If you accept the host key here, the file will be automatically created" );
170
 
        break;
171
 
 
172
 
    case SSH_SERVER_NOT_KNOWN:
173
 
        errMsg=tr ( "The server is unknown. Do you trust the host key?\nPublic key hash: " ) +sshMessage;
174
 
        break;
175
 
    }
176
 
 
177
 
    if ( QMessageBox::warning ( 0, tr ( "Host key verification failed" ),errMsg,tr ( "Yes" ), tr ( "No" ) ) !=0 )
178
 
    {
179
 
        connection->writeKnownHosts(false);
180
 
        connection->wait();
181
 
        if(sshConnection && sshConnection !=connection)
182
 
        {
183
 
            sshConnection->wait();
184
 
            delete sshConnection;
185
 
        }
186
 
        sshConnection=0;
187
 
        slotSshUserAuthError ( tr ( "Host key verification failed" ) );
188
 
        return;
189
 
    }
190
 
    connection->writeKnownHosts(true);
191
 
    connection->wait();
192
 
    connection->start();
193
 
 
194
 
}
195
 
 
196
 
void HttpBrokerClient::slotSshServerAuthPassphrase(SshMasterConnection* connection, bool verificationCode)
197
 
{
198
 
    bool ok;
199
 
    QString message;
200
 
 
201
 
    if(verificationCode)
202
 
    {
203
 
        message=tr("Verification code:");
204
 
    }
205
 
    else
206
 
    {
207
 
        message=tr("Enter passphrase to decrypt a key");
208
 
    }
209
 
 
210
 
 
211
 
    QString phrase=QInputDialog::getText(0,connection->getUser()+"@"+connection->getHost()+":"+QString::number(connection->getPort()),
212
 
                                         message, QLineEdit::Password,QString::null, &ok);
213
 
    if(!ok)
214
 
    {
215
 
        phrase=QString::null;
216
 
    }
217
 
    else
218
 
    {
219
 
        if(phrase==QString::null)
220
 
            phrase="";
221
 
    }
222
 
    connection->setKeyPhrase(phrase);
223
 
 
224
 
}
225
 
 
226
 
void HttpBrokerClient::slotSshUserAuthError(QString error)
227
 
{
228
 
    if ( sshConnection )
229
 
    {
230
 
        sshConnection->wait();
231
 
        delete sshConnection;
232
 
        sshConnection=0l;
233
 
    }
234
 
 
235
 
    QMessageBox::critical ( 0l,tr ( "Authentication failed" ),error,
236
 
                            QMessageBox::Ok,
237
 
                            QMessageBox::NoButton );
238
 
    emit authFailed();
239
 
    return;
240
 
}
241
 
 
242
 
void HttpBrokerClient::getUserSessions()
243
 
{
244
 
    QString brokerUser=config->brokerUser;
245
 
    // Otherwise, after logout from the session, we will be connected by a previous user without a password by authid.
246
 
    if (config->brokerAutologoff) {
247
 
        nextAuthId=config->brokerUserId;
248
 
    }
249
 
    x2goDebug<<"called getUserSessions: brokeruser: "<<brokerUser<<" authid: "<<nextAuthId;
250
 
    if(mainWindow->getUsePGPCard())
251
 
        brokerUser=mainWindow->getCardLogin();
252
 
    config->sessiondata=QString::null;
253
 
    if(!sshBroker)
254
 
    {
255
 
        QString req;
256
 
        QTextStream ( &req ) <<
257
 
                             "task=listsessions&"<<
258
 
                             "user="<<QUrl::toPercentEncoding(brokerUser)<<"&"<<
259
 
                             "password="<<QUrl::toPercentEncoding(config->brokerPass)<<"&"<<
260
 
                             "authid="<<nextAuthId;
261
 
 
262
 
        x2goDebug << "sending request: "<< req.toUtf8();
263
 
        QNetworkRequest request(QUrl(config->brokerurl));
264
 
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
265
 
        sessionsRequest=http->post (request, req.toUtf8() );
266
 
    }
267
 
    else
268
 
    {
269
 
        if(!sshConnection)
270
 
        {
271
 
            createSshConnection();
272
 
            return;
273
 
        }
274
 
        if (nextAuthId.length() > 0) {
275
 
            sshConnection->executeCommand ( config->sshBrokerBin+" --user "+ brokerUser +" --authid "+nextAuthId+ " --task listsessions",
276
 
                                            this, SLOT ( slotListSessions ( bool, QString,int ) ));
277
 
        } else {
278
 
            sshConnection->executeCommand ( config->sshBrokerBin+" --user "+ brokerUser +" --task listsessions",
279
 
                                            this, SLOT ( slotListSessions ( bool, QString,int ) ));
280
 
        }
281
 
    }
282
 
}
283
 
 
284
 
void HttpBrokerClient::selectUserSession(const QString& session)
285
 
{
286
 
    x2goDebug<<"Called selectUserSession for session "<<session<<".";
287
 
    QString brokerUser=config->brokerUser;
288
 
    if(mainWindow->getUsePGPCard())
289
 
        brokerUser=mainWindow->getCardLogin();
290
 
 
291
 
    if(!sshBroker)
292
 
    {
293
 
        QString req;
294
 
        QTextStream ( &req ) <<
295
 
                             "task=selectsession&"<<
296
 
                             "sid="<<session<<"&"<<
297
 
                             "user="<<QUrl::toPercentEncoding(brokerUser)<<"&"<<
298
 
                             "password="<<QUrl::toPercentEncoding(config->brokerPass)<<"&"<<
299
 
                             "authid="<<nextAuthId;
300
 
        x2goDebug << "sending request: "<< req.toUtf8();
301
 
        QNetworkRequest request(QUrl(config->brokerurl));
302
 
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
303
 
        selSessRequest=http->post (request, req.toUtf8() );
304
 
 
305
 
    }
306
 
    else
307
 
    {
308
 
        if (nextAuthId.length() > 0) {
309
 
            sshConnection->executeCommand ( config->sshBrokerBin+" --user "+ brokerUser +" --authid "+nextAuthId+ " --task selectsession --sid \""+session+"\"",
310
 
                                            this,SLOT ( slotSelectSession(bool,QString,int)));
311
 
        } else {
312
 
            sshConnection->executeCommand ( config->sshBrokerBin+" --user "+ brokerUser +" --task selectsession --sid \""+session+"\"",
313
 
                                            this,SLOT ( slotSelectSession(bool,QString,int)));
314
 
        }
315
 
    }
316
 
 
317
 
}
318
 
 
319
 
void HttpBrokerClient::changePassword(QString newPass)
320
 
{
321
 
    newBrokerPass=newPass;
322
 
    QString brokerUser=config->brokerUser;
323
 
    if(mainWindow->getUsePGPCard())
324
 
        brokerUser=mainWindow->getCardLogin();
325
 
 
326
 
    if(!sshBroker)
327
 
    {
328
 
        QString req;
329
 
        QTextStream ( &req ) <<
330
 
                             "task=setpass&"<<
331
 
                             "newpass="<<QUrl::toPercentEncoding(newPass)<<"&"<<
332
 
                             "user="<<QUrl::toPercentEncoding(brokerUser)<<"&"<<
333
 
                             "password="<<QUrl::toPercentEncoding(config->brokerPass)<<"&"<<
334
 
                             "authid="<<nextAuthId;
335
 
        x2goDebug << "sending request: "<< req.toUtf8();
336
 
        QNetworkRequest request(QUrl(config->brokerurl));
337
 
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
338
 
        chPassRequest=http->post (request, req.toUtf8() );
339
 
    }
340
 
    else
341
 
    {
342
 
        if (nextAuthId.length() > 0) {
343
 
            sshConnection->executeCommand ( config->sshBrokerBin+" --user "+ brokerUser +" --authid "+nextAuthId+ " --task setpass --newpass "+newPass, this,
344
 
                                            SLOT ( slotPassChanged(bool,QString,int)));
345
 
        } else {
346
 
            sshConnection->executeCommand ( config->sshBrokerBin+" --user "+ brokerUser +" --task setpass --newpass "+newPass, this,
347
 
                                            SLOT ( slotPassChanged(bool,QString,int)));
348
 
        }
349
 
    }
350
 
}
351
 
 
352
 
void HttpBrokerClient::testConnection()
353
 
{
354
 
    x2goDebug<<"called testConnection";
355
 
    if(!sshBroker)
356
 
    {
357
 
        QString req;
358
 
        QTextStream ( &req ) <<
359
 
                             "task=testcon";
360
 
        x2goDebug << "sending request: "<< req.toUtf8();
361
 
        QNetworkRequest request(QUrl(config->brokerurl));
362
 
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
363
 
        testConRequest=http->post (request, req.toUtf8() );
364
 
    }
365
 
    else
366
 
    {
367
 
        if (nextAuthId.length() > 0) {
368
 
            sshConnection->executeCommand(config->sshBrokerBin+" --authid "+nextAuthId+ " --task testcon",
369
 
                                          this, SLOT ( slotSelectSession(bool,QString,int)));
370
 
        } else {
371
 
            sshConnection->executeCommand(config->sshBrokerBin+" --task testcon",
372
 
                                          this, SLOT ( slotSelectSession(bool,QString,int)));
373
 
        }
374
 
    }
375
 
}
376
 
 
377
 
 
378
 
void HttpBrokerClient::createIniFile(const QString& raw_content)
379
 
{
380
 
    QString content;
381
 
    content = raw_content;
382
 
    content.replace("<br>","\n");
383
 
    x2goDebug<<"inifile content: "<<content<<"\n";
384
 
    QString cont;
385
 
    QStringList lines=content.split("START_USER_SESSIONS\n");
386
 
    if (lines.count()>1)
387
 
    {
388
 
        cont=lines[1];
389
 
        cont=cont.split("END_USER_SESSIONS\n")[0];
390
 
    }
391
 
    mainWindow->config.iniFile=cont;
392
 
}
393
 
 
394
 
 
395
 
bool HttpBrokerClient::checkAccess(QString answer )
396
 
{
397
 
    x2goDebug<<"called checkAccess - answer was: "<<answer;
398
 
    if (answer.indexOf("Access granted")==-1)
399
 
    {
400
 
        QMessageBox::critical (
401
 
            0,tr ( "Error" ),
402
 
            tr ( "Login failed!<br>"
403
 
                 "Please try again" ) );
404
 
        emit authFailed();
405
 
        return false;
406
 
    }
407
 
    config->brokerAuthenticated=true;
408
 
    int authBegin=answer.indexOf("AUTHID:");
409
 
    if (authBegin!=-1)
410
 
    {
411
 
        nextAuthId=answer.mid(authBegin+7, answer.indexOf("\n",authBegin)-authBegin-7);
412
 
    }
413
 
    return true;
414
 
}
415
 
 
416
 
 
417
 
void HttpBrokerClient::slotConnectionTest(bool success, QString answer, int)
418
 
{
419
 
    x2goDebug<<"called slotConnectionTest";
420
 
    if(!success)
421
 
    {
422
 
        x2goDebug<<answer;
423
 
        QMessageBox::critical(0,tr("Error"),answer);
424
 
        emit fatalHttpError();
425
 
        return;
426
 
    }
427
 
    if(!checkAccess(answer))
428
 
        return;
429
 
    if(!sshBroker)
430
 
    {
431
 
        x2goDebug<<"elapsed: "<<requestTime.elapsed()<<"received:"<<answer.size()<<endl;
432
 
        emit connectionTime(requestTime.elapsed(),answer.size());
433
 
    }
434
 
    return;
435
 
 
436
 
}
437
 
 
438
 
void HttpBrokerClient::slotListSessions(bool success, QString answer, int)
439
 
{
440
 
    if(!success)
441
 
    {
442
 
        x2goDebug<<answer;
443
 
        QMessageBox::critical(0,tr("Error"),answer);
444
 
        emit fatalHttpError();
445
 
        return;
446
 
    }
447
 
    if(!checkAccess(answer))
448
 
        return;
449
 
    createIniFile(answer);
450
 
    emit sessionsLoaded();
451
 
}
452
 
 
453
 
void HttpBrokerClient::slotPassChanged(bool success, QString answer, int)
454
 
{
455
 
    if(!success)
456
 
    {
457
 
        x2goDebug<<answer;
458
 
        QMessageBox::critical(0,tr("Error"),answer);
459
 
        emit fatalHttpError();
460
 
        return;
461
 
    }
462
 
    if(!checkAccess(answer))
463
 
        return;
464
 
 
465
 
}
466
 
 
467
 
void HttpBrokerClient::slotSelectSession(bool success, QString answer, int)
468
 
{
469
 
    if(!success)
470
 
    {
471
 
        x2goDebug<<answer;
472
 
        QMessageBox::critical(0,tr("Error"),answer);
473
 
        emit fatalHttpError();
474
 
        return;
475
 
    }
476
 
    if(!checkAccess(answer))
477
 
        return;
478
 
    x2goDebug<<"parsing "<<answer;
479
 
    parseSession(answer);
480
 
}
481
 
 
482
 
 
483
 
void HttpBrokerClient::slotRequestFinished ( QNetworkReply*  reply )
484
 
{
485
 
    if(reply->error() != QNetworkReply::NoError)
486
 
    {
487
 
        x2goDebug<<"Broker HTTP request failed with error: "<<reply->errorString();
488
 
        QMessageBox::critical(0,tr("Error"),reply->errorString());
489
 
        emit fatalHttpError();
490
 
        return;
491
 
    }
492
 
 
493
 
    QString answer ( reply->readAll() );
494
 
    x2goDebug<<"A http request returned.  Result was: "<<answer;
495
 
    if (reply == testConRequest)
496
 
    {
497
 
        slotConnectionTest(true,answer,0);
498
 
    }
499
 
    if (reply == sessionsRequest)
500
 
    {
501
 
        slotListSessions(true, answer,0);
502
 
    }
503
 
    if (reply == selSessRequest)
504
 
    {
505
 
        slotSelectSession(true,answer,0);
506
 
    }
507
 
    if (reply == chPassRequest)
508
 
    {
509
 
        slotPassChanged(true,answer,0);
510
 
    }
511
 
 
512
 
    // We receive ownership of the reply object
513
 
    // and therefore need to handle deletion.
514
 
    reply->deleteLater();
515
 
}
516
 
 
517
 
void HttpBrokerClient::parseSession(QString sinfo)
518
 
{
519
 
    x2goDebug<<"starting parser\n";
520
 
    QStringList lst=sinfo.split("SERVER:",QString::SkipEmptyParts);
521
 
    int keyStartPos=sinfo.indexOf("-----BEGIN DSA PRIVATE KEY-----");
522
 
    if(keyStartPos==-1)
523
 
        keyStartPos=sinfo.indexOf("-----BEGIN RSA PRIVATE KEY-----");
524
 
    QString endStr="-----END DSA PRIVATE KEY-----";
525
 
    int keyEndPos=sinfo.indexOf(endStr);
526
 
    if(keyEndPos==-1)
527
 
    {
528
 
        endStr="-----END RSA PRIVATE KEY-----";
529
 
        keyEndPos=sinfo.indexOf(endStr);
530
 
    }
531
 
    if (! (keyEndPos == -1 || keyStartPos == -1 || lst.size()==0))
532
 
        config->key=sinfo.mid(keyStartPos, keyEndPos+endStr.length()-keyStartPos);
533
 
    QString serverLine=(lst[1].split("\n"))[0];
534
 
    QStringList words=serverLine.split(":",QString::SkipEmptyParts);
535
 
    config->serverIp=words[0];
536
 
    if (words.count()>1)
537
 
        config->sshport=words[1];
538
 
    x2goDebug<<"server IP: "<<config->serverIp<<"\n";
539
 
    x2goDebug<<"server port: "<<config->sshport<<"\n";
540
 
    if (sinfo.indexOf("SESSION_INFO")!=-1)
541
 
    {
542
 
        QStringList lst=sinfo.split("SESSION_INFO:",QString::SkipEmptyParts);
543
 
        config->sessiondata=lst[1];
544
 
        x2goDebug<<"session data: "<<config->sessiondata<<"\n";
545
 
    }
546
 
    x2goDebug<<"parsing has finished\n";
547
 
    emit sessionSelected();
548
 
}
549
 
 
550
 
 
551
 
void HttpBrokerClient::slotSslErrors ( QNetworkReply* netReply, const QList<QSslError> & errors )
552
 
{
553
 
    QStringList err;
554
 
    QSslCertificate cert;
555
 
    for ( int i=0; i<errors.count(); ++i )
556
 
    {
557
 
        x2goDebug<<"sslError, code:"<<errors[i].error() <<":";
558
 
        err<<errors[i].errorString();
559
 
        if ( !errors[i].certificate().isNull() )
560
 
            cert=errors[i].certificate();
561
 
    }
562
 
 
563
 
 
564
 
    QString md5=getHexVal ( cert.digest() );
565
 
    QString fname=md5;
566
 
    fname=fname.replace(":","_");
567
 
    QUrl lurl ( config->brokerurl );
568
 
    QString homeDir=mainWindow->getHomeDirectory();
569
 
    if ( QFile::exists ( homeDir+"/.x2go/ssl/exceptions/"+
570
 
                         lurl.host() +"/"+fname ) )
571
 
    {
572
 
        QFile fl ( homeDir+"/.x2go/ssl/exceptions/"+
573
 
                   lurl.host() +"/"+fname );
574
 
        fl.open ( QIODevice::ReadOnly | QIODevice::Text );
575
 
        QSslCertificate mcert ( &fl );
576
 
        if ( mcert==cert )
577
 
        {
578
 
            netReply->ignoreSslErrors();
579
 
            requestTime.restart();
580
 
            return;
581
 
        }
582
 
    }
583
 
 
584
 
    QString text=tr ( "<br><b>Server uses an invalid "
585
 
                      "security certificate.</b><br><br>" );
586
 
    text+=err.join ( "<br>" );
587
 
    text+=tr ( "<p style='background:#FFFFDC;'>"
588
 
               "You should not add an exception "
589
 
               "if you are using an internet connection "
590
 
               "that you do not trust completely or if you are "
591
 
               "not used to seeing a warning for this server.</p>" );
592
 
    QMessageBox mb ( QMessageBox::Warning,tr ( "Secure connection failed" ),
593
 
                     text );
594
 
    text=QString::null;
595
 
    QTextStream ( &text ) <<err.join ( "\n" ) <<"\n"<<
596
 
                          "------------\n"<<
597
 
                          tr ( "Issued to:\n" ) <<
598
 
                          tr ( "Common Name(CN)\t" ) <<
599
 
                          cert.issuerInfo ( QSslCertificate::CommonName )
600
 
                          <<endl<<
601
 
                          tr ( "Organization(O)\t" ) <<
602
 
                          cert.issuerInfo ( QSslCertificate::Organization )
603
 
                          <<endl<<
604
 
                          tr ( "Organizational Unit(OU)\t" ) <<
605
 
                          cert.issuerInfo ( QSslCertificate::OrganizationalUnitName )
606
 
                          <<endl<<
607
 
                          tr ( "Serial Number\t" ) <<getHexVal ( cert.serialNumber() )
608
 
                          <<endl<<endl<<
609
 
                          tr ( "Issued by:\n" ) <<
610
 
                          tr ( "Common Name(CN)\t" ) <<
611
 
                          cert.subjectInfo ( QSslCertificate::CommonName )
612
 
                          <<endl<<
613
 
                          tr ( "Organization(O)\t" ) <<
614
 
                          cert.subjectInfo ( QSslCertificate::Organization )
615
 
                          <<endl<<
616
 
                          tr ( "Organizational Unit(OU)\t" ) <<
617
 
                          cert.subjectInfo ( QSslCertificate::OrganizationalUnitName )
618
 
                          <<endl<<endl<<
619
 
 
620
 
                          tr ( "Validity:\n" ) <<
621
 
                          tr ( "Issued on\t" ) <<cert.effectiveDate().toString() <<endl<<
622
 
                          tr ( "expires on\t" ) <<cert.expiryDate().toString() <<endl<<endl<<
623
 
                          tr ( "Fingerprints:\n" ) <<
624
 
                          tr ( "SHA1\t" ) <<
625
 
                          getHexVal ( cert.digest ( QCryptographicHash::Sha1 ) ) <<endl<<
626
 
                          tr ( "MD5\t" ) <<md5;
627
 
 
628
 
 
629
 
 
630
 
    mb.setDetailedText ( text );
631
 
    mb.setEscapeButton (
632
 
        ( QAbstractButton* ) mb.addButton ( tr ( "Exit X2Go Client" ),
633
 
                                            QMessageBox::RejectRole ) );
634
 
    QPushButton *okButton=mb.addButton ( tr ( "Add exception" ),
635
 
                                         QMessageBox::AcceptRole );
636
 
    mb.setDefaultButton ( okButton );
637
 
 
638
 
    mb.exec();
639
 
    if ( mb.clickedButton() == ( QAbstractButton* ) okButton )
640
 
    {
641
 
        x2goDebug<<"accept certificate";
642
 
        QDir dr;
643
 
        dr.mkpath ( homeDir+"/.x2go/ssl/exceptions/"+lurl.host() +"/" );
644
 
        QFile fl ( homeDir+"/.x2go/ssl/exceptions/"+
645
 
                   lurl.host() +"/"+fname );
646
 
        fl.open ( QIODevice::WriteOnly | QIODevice::Text );
647
 
        QTextStream ( &fl ) <<cert.toPem();
648
 
        fl.close();
649
 
        netReply->ignoreSslErrors();
650
 
        x2goDebug<<"store certificate in  "<<homeDir+"/.x2go/ssl/exceptions/"+
651
 
                 lurl.host() +"/"+fname;
652
 
        requestTime.restart();
653
 
    }
654
 
    else
655
 
        emit fatalHttpError();
656
 
}
657
 
 
658
 
 
659
 
QString HttpBrokerClient::getHexVal ( const QByteArray& ba )
660
 
{
661
 
    QStringList val;
662
 
    for ( int i=0; i<ba.size(); ++i )
663
 
    {
664
 
        QString bt;
665
 
        bt.sprintf ( "%02X", ( unsigned char ) ba[i] );
666
 
        val<<bt;
667
 
    }
668
 
    return val.join ( ":" );
669
 
}
670