Rabbit Remote Control 0.0.30
Loading...
Searching...
No Matches
ChannelSSHTunnel.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include "ChannelSSHTunnel.h"
4#include <QLoggingCategory>
5#include <QThread>
6#include <QDateTime>
7#include <QAbstractEventDispatcher>
8#include <QScopedArrayPointer>
9#include <QtGlobal>
10#if defined(Q_OS_LINUX)
11 #include <sys/eventfd.h>
12#endif
13#if defined(Q_OS_WIN)
14 #include <WinSock2.h>
15 //#pragma comment(lib,"ws2_32.lib")
16#endif
17
18static Q_LOGGING_CATEGORY(log, "Channel.SSH.Tunnel")
19static Q_LOGGING_CATEGORY(logSSH, "Channel.SSH.log")
20
22 QSharedPointer<CParameterChannelSSH> parameter,
23 bool bWakeUp,
24 QObject *parent)
25 : CChannel(parent),
26 m_Session(NULL),
27 m_Channel(NULL),
28 m_pcapFile(NULL),
29 m_Parameter(parameter),
30 m_pSocketRead(nullptr),
31 m_pSocketWrite(nullptr),
32 m_pSocketException(nullptr),
33 m_pEvent(nullptr)
34{
35 qDebug(log) << "CChannelSSHTunnel::CChannelSSHTunnel()";
36 qDebug(log) << "libssh version:" << ssh_version(0);
37 Q_ASSERT(m_Parameter);
38 if(bWakeUp)
39 m_pEvent = new Channel::CEvent(this);
40}
41
42CChannelSSHTunnel::~CChannelSSHTunnel()
43{
44 qDebug(log) << "CChannelSSHTunnel::~CChannelSSHTunnel()";
45 if(m_pEvent)
46 delete m_pEvent;
47}
48
49QString CChannelSSHTunnel::GetDetails()
50{
51 return tr("- libssh version: ") + ssh_version(0);
52}
53
54void CChannelSSHTunnel::cb_log(ssh_session session,
55 int priority,
56 const char *message,
57 void *userdata)
58{
59 switch (priority) {
60 case SSH_LOG_WARN:
61 qWarning(logSSH) << message;
62 break;
63 case SSH_LOG_INFO:
64 qInfo(logSSH) << message;
65 case SSH_LOG_DEBUG:
66 case SSH_LOG_TRACE:
67 qDebug(logSSH) << message;
68 default:
69 break;
70 }
71}
72
73int CChannelSSHTunnel::WakeUp()
74{
75 if(!m_pEvent) return 0;
76 return m_pEvent->WakeUp();
77}
78
79bool CChannelSSHTunnel::open(OpenMode mode)
80{
81 int nRet = 0;
82 QString szErr;
83
84 m_Session = ssh_new();
85 if(NULL == m_Session)
86 {
87 szErr = tr("SSH failed: ssh_new.");
88 qCritical(log) << szErr;
89 setErrorString(szErr);
90 return false;
91 }
92
93 do{
94 if(!m_Parameter) {
95 qCritical(log) << "The parameter is null";
96 }
97 Q_ASSERT(m_Parameter);
98
99 struct ssh_callbacks_struct cb;
100 memset(&cb, 0, sizeof(struct ssh_callbacks_struct));
101 cb.userdata = this,
102 cb.log_function = cb_log;;
103 ssh_callbacks_init(&cb);
104 ssh_set_callbacks(m_Session, &cb);
105
106 /*
107 int value = 1;
108 ssh_options_set(m_Session, SSH_OPTIONS_NODELAY, (const void*)&value);//*/
109
110 /*
111 See: [ssh_options_set()](https://api.libssh.org/stable/group__libssh__session.html#ga7a801b85800baa3f4e16f5b47db0a73d)
112 SSH_LOG_NOLOG: No logging
113 SSH_LOG_WARNING: Only warnings
114 SSH_LOG_PROTOCOL: High level protocol information
115 SSH_LOG_PACKET: Lower level protocol information, packet level
116 SSH_LOG_FUNCTIONS: Every function path The default is SSH_LOG_NOLOG.
117 */
118 int verbosity = SSH_LOG_NOLOG;
119 ssh_options_set(m_Session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
120
121 if(!m_Parameter->GetServer().isEmpty()){
122 nRet = ssh_options_set(m_Session, SSH_OPTIONS_HOST,
123 m_Parameter->GetServer().toStdString().c_str());
124 if(nRet) {
125 szErr = tr("SSH failed: Set host fail. host:")
126 + m_Parameter->GetServer() + ";"
127 + ssh_get_error(m_Session);
128 qCritical(log) << szErr;
129 setErrorString(szErr);
130 break;
131 }
132 }
133
134 uint nPort = m_Parameter->GetPort();
135 nRet = ssh_options_set(m_Session, SSH_OPTIONS_PORT, &nPort);
136 if(nRet) {
137 szErr = tr("SSH failed: Set port fail. port:")
138 + QString::number(m_Parameter->GetPort()) + ";"
139 + ssh_get_error(m_Session);
140 qCritical(log) << szErr;
141 setErrorString(szErr);
142 break;
143 }
144
145 if(!m_Parameter->GetPcapFile().isEmpty())
146 {
147 m_pcapFile = ssh_pcap_file_new();
148 if(m_pcapFile) {
149 if (ssh_pcap_file_open(m_pcapFile,
150 m_Parameter->GetPcapFile().toStdString().c_str())
151 == SSH_ERROR) {
152 qCritical(log) << "SSH failed: Error opening pcap file: "
153 << m_Parameter->GetPcapFile();
154 ssh_pcap_file_free(m_pcapFile);
155 m_pcapFile = nullptr;
156 }
157 if(m_pcapFile)
158 ssh_set_pcap_file(m_Session, m_pcapFile);
159 } else {
160 szErr = tr("SSH failed: ssh_pcap_file_new: ")
161 + ssh_get_error(m_Session);
162 qCritical(log) << szErr;
163 }
164 }
165
166 nRet = ssh_connect(m_Session);
167 if(nRet) {
168 szErr = tr("SSH failed: ssh connect ")
169 + m_Parameter->GetServer()
170 + ":" + QString::number(m_Parameter->GetPort())
171 + " ("
172 + ssh_get_error(m_Session);
173 szErr += ")";
174 qCritical(log) << szErr;
175 setErrorString(szErr);
176 break;
177 }
178
179 nRet = verifyKnownhost(m_Session);
180 if(nRet) break;
181
182 if(((m_Parameter->GetPassword().isEmpty()
183 || m_Parameter->GetUser().isEmpty())
184 && m_Parameter->GetAuthenticationMethod() == SSH_AUTH_METHOD_PASSWORD)
185 || (m_Parameter->GetAuthenticationMethod() == SSH_AUTH_METHOD_PUBLICKEY
186 && m_Parameter->GetPassphrase().isEmpty())
187 ) {
188 emit sigBlockShowWidget("CDlgUserPassword", nRet, m_Parameter.data());
189 if(QDialog::Accepted != nRet)
190 {
191 setErrorString(tr("User cancel"));
192 return false;
193 }
194 }
195
196 nRet = authentication(m_Session,
197 m_Parameter->GetUser(),
198 m_Parameter->GetPassword(),
199 m_Parameter->GetPassphrase(),
200 m_Parameter->GetAuthenticationMethod());
201 if(nRet) break;
202
203 nRet = forward(m_Session);
204 if(nRet) break;
205
206 return QIODevice::open(mode);
207 } while(0);
208
209 ssh_disconnect(m_Session);
210 ssh_free(m_Session);
211 m_Session = NULL;
212 return false;
213}
214
215void CChannelSSHTunnel::close()
216{
217 qDebug(log) << "CChannelSSHTunnel::close()";
218
219 WakeUp();
220
221 /*
222 QAbstractEventDispatcher* pDispatcher = QAbstractEventDispatcher::instance();
223 if(m_pSocketRead) {
224 pDispatcher->unregisterSocketNotifier(m_pSocketRead);
225 m_pSocketRead->deleteLater();
226 m_pSocketRead = nullptr;
227 }
228 if(m_pSocketWrite) {
229 pDispatcher->unregisterSocketNotifier(m_pSocketWrite);
230 m_pSocketWrite->deleteLater();
231 m_pSocketWrite = nullptr;
232 }
233 if(m_pSocketException) {
234 pDispatcher->unregisterSocketNotifier(m_pSocketException);
235 m_pSocketException->deleteLater();
236 m_pSocketException = nullptr;
237 }//*/
238
239 if(m_pcapFile)
240 {
241 ssh_pcap_file_close(m_pcapFile);
242 ssh_pcap_file_free(m_pcapFile);
243 m_pcapFile = nullptr;
244 }
245
246 if(m_Channel) {
247 if(ssh_channel_is_open(m_Channel)) {
248 ssh_channel_close(m_Channel);
249 }
250 ssh_channel_free(m_Channel);
251 m_Channel = NULL;
252 }
253 if(m_Session) {
254 if(ssh_is_connected(m_Session))
255 ssh_disconnect(m_Session);
256 ssh_free(m_Session);
257 m_Session = NULL;
258 }
259
260 QIODevice::close();
261}
262
263int CChannelSSHTunnel::verifyKnownhost(ssh_session session)
264{
265 int nRet = -1;
266 QString szErr;
267 ssh_key srv_pubkey = NULL;
268 nRet = ssh_get_server_publickey(session, &srv_pubkey);
269 if (nRet < 0) {
270 szErr = tr("SSH failed: Get server public key.") + "(";
271 szErr += ssh_get_error(session);
272 szErr += ")";
273 qCritical(log) << szErr;
274 setErrorString(szErr);
275 return -1;
276 }
277 unsigned char *hash = NULL;
278 size_t nLen = 0;
279 nRet = ssh_get_publickey_hash(srv_pubkey,
280 SSH_PUBLICKEY_HASH_SHA1,
281 &hash,
282 &nLen);
283 ssh_key_free(srv_pubkey);
284 if(nRet) {
285 szErr = tr("SSH failed: Get public key hash value fail.");
286 qCritical(log) << szErr;
287 setErrorString(szErr);
288 return -2;
289 }
290 QByteArray baHash((const char*)hash, nLen);
291 QString szHash = baHash.toHex(':').toStdString().c_str();
292 ssh_clean_pubkey_hash(&hash);
293
294 QMessageBox::StandardButton btRet;
295 bool checkBox = false;
296 enum ssh_known_hosts_e state = ssh_session_is_known_server(session);
297 switch(state) {
298 case SSH_KNOWN_HOSTS_OK:
299 nRet = 0;
300 break;
301 case SSH_KNOWN_HOSTS_CHANGED:
302 nRet = -3;
303 szErr = tr("Host key for server changed. it is now:") + "\n";
304 szErr += szHash + "\n";
305 szErr += tr("For security reasons, connection will be stopped.") + "\n";
306 szErr += tr("Please look at the OpenSSL documentation on "
307 "how to add a private CA to the store.");
308 qCritical(log) << szErr;
309 setErrorString(szErr);
310 break;
311 case SSH_KNOWN_HOSTS_OTHER:
312 nRet = -4;
313 szErr = tr("The host key for this server was not found but an other type of key exists.") + "\n";
314 szErr += tr("An attacker might change the default server key to "
315 "confuse your client into thinking the key does not exist") + "\n";
316 szErr += tr("For security reasons, connection will be stopped.") + "\n";
317 szErr += tr("Please look at the OpenSSL documentation on "
318 "how to add a private CA to the store.");
319 qCritical(log) << szErr;
320 setErrorString(szErr);
321 break;
322 case SSH_KNOWN_HOSTS_NOT_FOUND:
323 nRet = -5;
324 szErr = tr("Could not find known host file.") + "\n";
325 szErr += tr("If you accept the host key here, the file will be "
326 "automatically created.") + "\n";
327 szErr += tr("Host key hash:") + "\n" + szHash;
328 qDebug(log) << szErr;
329 emit sigBlockShowMessageBox(tr("Error"), szErr,
330#ifndef Q_OS_ANDROID
331 QMessageBox::Yes |
332#endif
333 QMessageBox::No | QMessageBox::Ignore,
334 btRet, checkBox);
335 if(QMessageBox::Yes == btRet) {
336 nRet = ssh_session_update_known_hosts(session);
337 if(nRet)
338 {
339 qCritical(log) << "ssh_session_update_known_hosts fail."
340 << ssh_get_error(session);
341 }
342 } if(QMessageBox::Ignore == btRet)
343 nRet = 0;
344 else
345 setErrorString(tr("Reject the host key"));
346 break;
347 case SSH_KNOWN_HOSTS_UNKNOWN:
348 nRet = -6;
349 szErr = tr("The server is unknown. Do you trust the host key?") + "\n";
350 szErr += tr("Host key hash:") + "\n" + szHash;
351 qDebug(log) << szErr;
352 emit sigBlockShowMessageBox(tr("Error"), szErr,
353#ifndef Q_OS_ANDROID
354 QMessageBox::Yes |
355#endif
356 QMessageBox::No | QMessageBox::Ignore,
357 btRet, checkBox);
358 if(QMessageBox::Yes == btRet) {
359 nRet = ssh_session_update_known_hosts(session);
360 if (SSH_OK != nRet) {
361 qCritical(log) << "ssh_session_update_known_hosts fail."
362 << ssh_get_error(session);
363 }
364 } if(QMessageBox::Ignore == btRet)
365 nRet = 0;
366 else
367 setErrorString(tr("Reject the host key"));
368 break;
369 case SSH_KNOWN_HOSTS_ERROR:
370 nRet = -7;
371 szErr = tr("Error:") + ssh_get_error(session) + "\n";
372 szErr += tr("Host key hash:") + "\n" + szHash + "\n";
373 szErr += tr("Will be stopped.");
374 qCritical(log) << szErr;
375 setErrorString(szErr);
376 emit sigError(nRet, szErr);
377 break;
378 }
379
380 return nRet;
381}
382
385 ssh_session session,
386 const QString szUser,
387 const QString szPassword,
388 const QString szPassphrase,
389 const int nMethod)
390{
391 int nRet = 0;
392 int nServerMethod = nMethod;
393
394 qDebug(log) << "Authentication method:" << nMethod;
395 //* Get authentication list from ssh server
396 nRet = ssh_userauth_none(session,
397 szUser.toStdString().c_str());
398 qDebug(log) << "ssh_userauth_none:" << nRet;
399 if(SSH_AUTH_SUCCESS == nRet)
400 return 0;
401
402 char *banner = nullptr;
403 banner = ssh_get_issue_banner(session);
404 if (banner)
405 {
406 qDebug(log) << "banner:" << banner;
407 free(banner);
408 }
409
410 nServerMethod = ssh_userauth_list(session,
411 szUser.toStdString().c_str());
412 qDebug(log) << "ssh_userauth_list:" << nServerMethod;
413 //*/
414
415 if(nServerMethod & nMethod & SSH_AUTH_METHOD_PUBLICKEY) {
416 if(m_Parameter->GetUseSystemFile()) {
417 qDebug(log) << "User authentication with ssh_userauth_publickey_auto";
418 nRet = ssh_userauth_publickey_auto(session,
419 szUser.toStdString().c_str(),
420 szPassphrase.toStdString().c_str());
421 if(SSH_AUTH_SUCCESS == nRet)
422 return 0;
423 QString szErr = tr("SSH failed: Failed authenticating with publickey:")
424 + ssh_get_error(m_Session);
425 qCritical(log) << szErr;
426 setErrorString(szErr);
427 } else {
428 qDebug(log) << "User authentication with publickey";
429 nRet = authenticationPublicKey(
430 m_Session,
431 m_Parameter->GetUser(),
432 m_Parameter->GetPublicKeyFile(),
433 m_Parameter->GetPrivateKeyFile(),
434 m_Parameter->GetPassphrase());
435 if(SSH_AUTH_SUCCESS == nRet)
436 return 0;
437 }
438 }
439
440 if(nServerMethod & nMethod & SSH_AUTH_METHOD_PASSWORD) {
441 qDebug(log) << "User authentication with password";
442
443 nRet = ssh_userauth_password(session,
444 szUser.toStdString().c_str(),
445 szPassword.toStdString().c_str());
446 if(nRet) {
447 QString szErr = tr("Failed authenticating with password. User: ")
448 + szUser + "; "
449 + ssh_get_error(session);
450 qCritical(log) << szErr;
451 setErrorString(szErr);
452 return nRet;
453 }
454 }
455
456 return nRet;
457}
458
459int CChannelSSHTunnel::authenticationPublicKey(
460 ssh_session session,
461 const QString szUser,
462 const QString szPublicKeyFile,
463 const QString szPrivateKeyFile,
464 const QString szPassphrase)
465{
466 int nRet = 0;
467 QString szErr;
468 ssh_key publicKey = NULL;
469 ssh_key privateKey = NULL;
470
471 do{
472 if(szPublicKeyFile.isEmpty())
473 {
474 szErr = tr("SSH failed: There is not set public key file.");
475 qCritical(log) << szErr;
476 setErrorString(szErr);
477 break;
478 }
479 nRet = ssh_pki_import_pubkey_file(
480 szPublicKeyFile.toStdString().c_str(),
481 &publicKey);
482 if(SSH_OK != nRet) {
483 szErr = tr("SSH failed: Import public key fail.") + szPublicKeyFile;
484 if(SSH_EOF == nRet)
485 szErr += tr("The file doesn't exist or permission denied:");
486 qCritical(log) << szErr;
487 setErrorString(szErr);
488 break;
489 }
490
491 nRet = ssh_userauth_try_publickey(
492 session,
493 szUser.toStdString().c_str(),
494 publicKey);
495 if(SSH_AUTH_SUCCESS != nRet)
496 {
497 szErr = tr("SSH failed: Authentication failed. User:") + szUser + "\n";
498 szErr += ssh_get_error(session);
499 qCritical(log) << szErr;
500 setErrorString(szErr);
501 break;
502 }
503
504 if(szPrivateKeyFile.isEmpty())
505 {
506 szErr = tr("SSH failed: There is not set private key file.");
507 qCritical(log) << szErr;
508 setErrorString(szErr);
509 break;
510 }
511 nRet = ssh_pki_import_privkey_file(
512 szPrivateKeyFile.toStdString().c_str(),
513 szPassphrase.toStdString().c_str(),
514 NULL, NULL, &privateKey);
515 if(SSH_OK != nRet) {
516
517 szErr = tr("SSH failed: Import private key fail.") + szPrivateKeyFile;
518 if(SSH_EOF == nRet)
519 szErr += tr("The file doesn't exist or permission denied:");
520 qCritical(log) << szErr;
521 setErrorString(szErr);
522 break;
523 }
524
525 nRet = ssh_userauth_publickey(
526 session,
527 szUser.toStdString().c_str(),
528 privateKey);
529 if(SSH_AUTH_SUCCESS != nRet) {
530 szErr = tr("SSH failed: Authentication failed. User:") + szUser + "\n";
531 szErr += ssh_get_error(session);
532 qCritical(log) << szErr;
533 setErrorString(szErr);
534 }
535
536 }while(0);
537
538 if(publicKey)
539 ssh_key_free(publicKey);
540 if(privateKey)
541 ssh_key_free(privateKey);
542
543 return nRet;
544}
545
546int CChannelSSHTunnel::forward(ssh_session session)
547{
548 int nRet = 0;
549
550 Q_ASSERT(session);
551
552 m_Channel = ssh_channel_new(session);
553 if(NULL == m_Channel) {
554 qCritical(log) << "ssh_channel_new fail." << ssh_get_error(session);
555 return -1;
556 }
557
558 nRet = ssh_channel_open_forward(
559 m_Channel,
560 m_Parameter->GetRemoteHost().toStdString().c_str(),
561 m_Parameter->GetRemotePort(),
562 m_Parameter->GetSourceHost().toStdString().c_str(),
563 m_Parameter->GetSourcePort());
564 if(SSH_OK != nRet) {
565 ssh_channel_free(m_Channel);
566 m_Channel = NULL;
567
568 QString szErr;
569 szErr = tr("SSH failed: open forward.") + ssh_get_error(session);
570 szErr += "(" + m_Parameter->GetRemoteHost()
571 + ":" + QString::number(m_Parameter->GetRemotePort()) + ")";
572 qCritical(log) << szErr;
573 setErrorString(szErr);
574 return nRet;
575 }
576
577 qDebug(log) << "Connected:"
578 << m_Parameter->GetRemoteHost()
579 + ":" + QString::number(m_Parameter->GetRemotePort())
580 << "with ssh turnnel:"
581 << m_Parameter->GetServer()
582 + ":" + QString::number(m_Parameter->GetPort());
583
584 emit sigConnected();
585
586 //ssh_channel_set_blocking(m_Channel, 0);
587
588 return nRet;
589}
590
599{
600 int nRet = 0;
601
602 if(!m_Channel || !ssh_channel_is_open(m_Channel)
603 || ssh_channel_is_eof(m_Channel)) {
604 QString szErr = "The channel is not open";
605 qCritical(log) << szErr;
606 setErrorString(szErr);
607 return -1;
608 }
609
610 struct timeval timeout = {0, 50000};
611 ssh_channel channels[2], channel_out[2];
612 channels[0] = m_Channel;
613 channels[1] = nullptr;
614
615 fd_set set;
616 FD_ZERO(&set);
617 socket_t fd = SSH_INVALID_SOCKET;
618 if(m_pEvent)
619 fd = m_pEvent->GetFd();
620 if(SSH_INVALID_SOCKET != fd)
621 FD_SET(fd, &set);
622
623 //qDebug(log) << "ssh_select:" << fd;
624 nRet = ssh_select(channels, channel_out, fd + 1, &set, &timeout);
625 //qDebug(log) << "ssh_select end:" << nRet;
626 if(nRet < 0) {
627 QString szErr;
628 szErr = "ssh_channel_select failed: " + QString::number(nRet);
629 szErr += ssh_get_error(m_Session);
630 qCritical(log) << szErr;
631 setErrorString(szErr);
632 return -3;
633 }
634
635 /*
636 if(0 == nRet)
637 {
638 qDebug(log) << "Time out";
639 }//*/
640
641 if(SSH_INVALID_SOCKET != fd && FD_ISSET(fd, &set)) {
642 //qDebug(log) << "fires event";
643 if(m_pEvent) {
644 nRet = m_pEvent->Reset();
645 if(nRet) return -4;
646 }
647 }
648
649 if(!channels[0]) {
650 qDebug(log) << "There is not channel";
651 return 0;
652 }
653
654 if(ssh_channel_is_eof(m_Channel)) {
655 qWarning(log) << "Channel is eof";
656 setErrorString(tr("The channel is eof"));
657 return -1;
658 }
659
660 nRet = ssh_channel_poll(m_Channel, 0);
661 //qDebug(log) << "ssh_channel_poll:" << nRet;
662 if(nRet < 0) {
663 QString szErr;
664 szErr = "ssh_channel_poll failed. nRet:";
665 szErr += QString::number(nRet);
666 szErr += ssh_get_error(m_Session);
667 setErrorString(szErr);
668 qCritical(log) << szErr;
669 return -6;
670 }
671 if(nRet == 0) {
672 //qDebug(log) << "There is not data in channel";
673 return 0;
674 }
675
676 emit readyRead();
677
678 return 0;
679}
680
681// Because is same thread
682qint64 CChannelSSHTunnel::readData(char *data, qint64 maxlen)
683{
684 qint64 nRet = 0;
685
686 /*
687 qDebug(log) << "CChannel::readData:"
688 << maxlen << "nLen:" << m_readData.size();//*/
689
690 Q_ASSERT(data && maxlen >= 0);
691 if(!(data && maxlen >= 0))
692 return 0;
693
694 if(!m_Channel || !ssh_channel_is_open(m_Channel))
695 {
696 QString szErr;
697 szErr = "The channel is not opened";
698 qCritical(log) << szErr;
699 setErrorString(szErr);
700 return -1;
701 }
702 /*
703 if(ssh_channel_is_eof(m_Channel))
704 {
705 QString szErr;
706 szErr = "The channel is eof";
707 qCritical(log) << szErr;
708 setErrorString(szErr);
709 return -2;
710 }
711
712 nRet = ssh_channel_poll(m_Channel, 0);
713 //qDebug(log) << "ssh_channel_poll:" << nRet;
714 if(nRet < 0) {
715 QString szErr;
716 szErr = "ssh_channel_poll failed. nRet:";
717 szErr += QString::number(nRet);
718 szErr += ssh_get_error(m_Session);
719 qCritical(log) << szErr;
720 return nRet;
721 }
722 if(nRet == 0) {
723 //qDebug(log) << "There is not data in channel";
724 return 0;
725 }//*/
726
727 nRet = ssh_channel_read_nonblocking(m_Channel, data, maxlen, 0);
728 if(SSH_AGAIN == nRet) {
729 emit readyRead();
730 return 0;
731 } else if(0 > nRet) {
732 QString szErr;
733 szErr = "Read data from channel failed. nRet:";
734 szErr += QString::number(nRet);
735 szErr += ssh_get_error(m_Session);
736 qCritical(log) << szErr;
737 return nRet;
738 }
739
740 return nRet;
741}
742
743qint64 CChannelSSHTunnel::writeData(const char *data, qint64 len)
744{
745 qint64 nRet = 0;
746
747 Q_ASSERT(data && len >= 0);
748 if(!(data && len >= 0))
749 return 0;
750
751 if(!m_Channel || !ssh_channel_is_open(m_Channel) || ssh_channel_is_eof(m_Channel))
752 {
753 QString szErr;
754 szErr = "The channel is not opened";
755 qCritical(log) << szErr;
756 setErrorString(szErr);
757 return -1;
758 }
759
760 nRet = ssh_channel_write(m_Channel, data, len);
761 if(nRet < 0) {
762 if(SSH_AGAIN == nRet)
763 return 0;
764
765 QString szErr;
766 szErr = "Write data from channel failed:";
767 szErr += ssh_get_error(m_Session);
768 qCritical(log) << szErr;
769 setErrorString(szErr);
770 return -2;
771 }
772 return nRet;
773}
774
775/*
776int CChannelSSHTunnel::ProcessSocket()
777{
778 int nRet = 0;
779 bool check = false;
780 socket_t fd = ssh_get_fd(m_Session);
781 m_pSocketRead = new QSocketNotifier(fd, QSocketNotifier::Read, this);
782 if(m_pSocketRead) {
783 check = connect(
784 m_pSocketRead, &QSocketNotifier::activated,
785 this, [&](int fd) {
786 qDebug(log) << "QSocketNotifier::activated: read";
787 Q_UNUSED(fd)
788 emit this->readyRead();
789 });
790 Q_ASSERT(check);
791 }
792
793 // m_pSocketWrite = new QSocketNotifier(fd, QSocketNotifier::Write, this);
794 // if(m_pSocketWrite) {
795 // check = connect(
796 // m_pSocketWrite, &QSocketNotifier::activated,
797 // this, [&](int fd){
798 // Q_UNUSED(fd)
799 // qDebug(log) << "QSocketNotifier::activated: write";
800 // });
801 // Q_ASSERT(check);
802 // }
803
804 m_pSocketException = new QSocketNotifier(fd, QSocketNotifier::Exception, this);
805 if(m_pSocketException) {
806 check = connect(
807 m_pSocketException, &QSocketNotifier::activated,
808 this, [&](int) {
809 qDebug(log) << "QSocketNotifier::activated: Exception";
810 QString szErr;
811 szErr = "Channel exception:";
812 szErr += ssh_get_error(m_Session);
813 qCritical(log) << szErr;
814 emit sigError(-1, szErr);
815 });
816 Q_ASSERT(check);
817 }
818
819 return nRet;
820}
821//*/
ssh tunnel class
void sigBlockShowMessageBox(const QString &szTitle, const QString &szMessage, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton &nRet, bool &checkBox, QString checkBoxContext=QString())
Block background threads and display message dialogs in foreground threads (QMessageBox)
virtual bool open(OpenMode mode) override
int authentication(ssh_session session, const QString szUser, const QString szPassword, const QString szPassphrase, const int nMethod=SSH_AUTH_METHOD_PASSWORD)
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
Blocks the background thread and displays the window in the foreground thread.
The channel interface class.
Definition Channel.h:25
void sigConnected()
emit when the channel is connected.
void sigError(int nErr, const QString &szErr)
emit when the channel is error