1 /************************************************************************** 2 * Copyright (C) 2005-2020 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 <https://www.gnu.org/licenses/>. * 16 ***************************************************************************/ 17 18 #ifndef SSHMASTERCONNECTION_H 19 #define SSHMASTERCONNECTION_H 20 21 #include <libssh/libssh.h> 22 #include <QString> 23 #include <QList> 24 #include <QMutex> 25 #include <QThread> 26 #include <QStringList> 27 #include <QTcpSocket> 28 #include <QNetworkProxy> 29 30 31 #define PROPERTY(TYPE,NAME) private: TYPE NAME; \ 32 public: TYPE get_##NAME(){return NAME;} \ 33 void set_##NAME(TYPE VAL){NAME=VAL;} 34 35 36 class ONMainWindow; 37 class SshProcess; 38 struct ChannelConnection 39 { 40 ssh_channel channel; 41 int sock; 42 SshProcess* creator; 43 int forwardPort; 44 int localPort; 45 QString forwardHost; 46 QString localHost; 47 QString command; 48 QString uuid; 49 bool operator==(ChannelConnection& t) 50 { 51 return (channel==t.channel); 52 } 53 }; 54 55 struct ReverseTunnelRequest 56 { 57 uint localPort; 58 uint forwardPort; 59 QString localHost; 60 SshProcess* creator; 61 bool listen; 62 }; 63 64 struct CopyRequest 65 { 66 SshProcess* creator; 67 QString src; 68 QString dst; 69 }; 70 71 class SshMasterConnection: public QThread 72 { 73 Q_OBJECT 74 PROPERTY(bool, kerberosDelegation) 75 public: 76 enum ProxyType {PROXYSSH, PROXYHTTP}; 77 78 enum passphrase_types { 79 PASSPHRASE_PRIVKEY, 80 PASSPHRASE_CHALLENGE, 81 PASSPHRASE_PASSWORD, 82 PASSPHRASE_UNKNOWN 83 }; 84 85 void run(); 86 SshMasterConnection(QObject* parent, QString host, int port, bool acceptUnknownServers, QString user, 87 QString pass, QString key, bool autologin, bool krblogin=false, 88 bool useproxy=false, ProxyType type=PROXYSSH, QString proxyserver=QString::null, quint16 proxyport=0, 89 QString proxylogin=QString::null, QString proxypassword=QString::null, QString proxyKey=QString::null, 90 bool proxyAutologin=false, bool proxyKrbLogin=false); 91 ~SshMasterConnection(); 92 void addChannelConnection(SshProcess* creator, int sock, QString forwardHost, 93 int forwardPort, QString localHost, int localPort, void* channel=0l); 94 void addChannelConnection(SshProcess* creator, QString uuid, QString cmd); 95 void addCopyRequest(SshProcess* creator, QString src, QString dst); 96 void writeKnownHosts(bool); 97 void setKeyPhrase(QString); 98 99 int executeCommand(const QString& command, QObject* receiver=0, const char* slotFinished=0, bool overridePath=true); 100 int startTunnel(const QString& forwardHost, uint forwardPort, const QString& localHost, 101 uint localPort, bool reverse=false, QObject* receiver=0, const char* slotTunnelOk=0, const char* slotFinished=0); 102 int copyFile(const QString& src, const QString dst, QObject* receiver=0, const char* slotFinished=0); 103 QString getSourceFile(int pid); 104 setAcceptUnknownServers(bool accept)105 void setAcceptUnknownServers(bool accept) 106 { 107 acceptUnknownServers=accept; 108 } getHost()109 QString getHost() 110 { 111 return host; 112 } getUser()113 QString getUser() 114 { 115 return user; 116 } getPort()117 int getPort() 118 { 119 return port; 120 } useKerberos()121 bool useKerberos() 122 { 123 return kerberos; 124 }; 125 126 private: 127 bool sshConnect(); 128 bool userAuthWithPass(); 129 bool userAuthAuto(); 130 bool userAuthWithKey(); 131 bool userChallengeAuth(); 132 bool checkLogin(); 133 bool userAuth(); 134 bool userAuthKrb(); 135 bool userAuthKeyboardInteractive(QString prompt); 136 void channelLoop(); 137 void finalize(int arg1); 138 void copy(); 139 int serverAuth(QString& errorMsg); 140 void setVerficationCode(QString code); 141 void checkReverseTunnelConnections(); 142 void addReverseTunnelConnections(); 143 #ifdef Q_OS_WIN 144 void parseKnownHosts(); 145 #endif 146 147 private slots: 148 149 void slotSshProxyServerAuthError ( int,QString, SshMasterConnection* ); 150 void slotSshProxyServerAuthAborted (); 151 void slotSshProxyUserAuthError ( QString ); 152 void slotSshProxyConnectionError ( QString,QString ); 153 154 155 void slotSshProxyConnectionOk(); 156 void slotSshProxyTunnelOk(int); 157 void slotSshProxyTunnelFailed(bool result, QString output, 158 int); 159 void slotSshProxyInteractionStart ( SshMasterConnection* connection, QString prompt ); 160 void slotSshProxyInteractionUpdate ( SshMasterConnection* connection, QString output ); 161 void slotSshProxyInteractionFinish ( SshMasterConnection* connection); 162 163 public slots: 164 void interactionTextEnter(QString text); 165 void interactionInterruptSlot(); 166 167 private: 168 ssh_session my_ssh_session; 169 QList<ChannelConnection> channelConnections; 170 QList<CopyRequest> copyRequests; 171 QList<ReverseTunnelRequest> reverseTunnelRequest; 172 QMutex channelConnectionsMutex; 173 QMutex copyRequestMutex; 174 QMutex disconnectFlagMutex; 175 QMutex writeHostKeyMutex; 176 QMutex reverseTunnelRequestMutex; 177 QMutex interactionInputMutex; 178 QString interactionInputText; 179 bool interactionInterrupt; 180 bool writeHostKey; 181 bool writeHostKeyReady; 182 int nextPid; 183 QList<SshProcess*> processes; 184 185 QString keyPhrase; 186 bool keyPhraseReady; 187 QMutex keyPhraseMutex; 188 189 QString host; 190 int port; 191 QString user; 192 QString pass; 193 QString key; 194 bool useproxy; 195 QString proxyserver; 196 quint16 proxyport; 197 QString proxylogin; 198 QString proxypassword; 199 ProxyType proxytype; 200 bool proxyautologin; 201 bool proxyKrbLogin; 202 QString proxykey; 203 QStringList authErrors; 204 bool autologin; 205 bool disconnectSessionFlag; 206 int localProxyPort; 207 bool acceptUnknownServers; 208 ONMainWindow* mainWnd; 209 bool kerberos; 210 QString sshProcErrString; 211 QTcpSocket *tcpProxySocket; 212 QNetworkProxy *tcpNetworkProxy; 213 SshMasterConnection* sshProxy; 214 bool sshProxyReady; 215 bool breakLoop; 216 bool loginCheck; 217 218 bool challengeAuthPasswordAccepted; 219 QString challengeAuthVerificationCode; 220 221 static const QString challenge_auth_code_prompts_[]; 222 223 signals: 224 void stdErr(SshProcess* caller, QByteArray data); 225 void stdOut(SshProcess* caller, QByteArray data); 226 void ioErr(SshProcess* caller, QString error, QString lastSessionError); 227 void copyErr(SshProcess* caller, QString error, QString lastSessionError); 228 void copyOk(SshProcess* caller); 229 void channelClosed(SshProcess* caller, QString uuid); 230 void reverseTunnelOk(SshProcess* caller); 231 void reverseTunnelFailed(SshProcess* caller, QString error); 232 233 void connectionError(QString message, QString lastSessionError); 234 void serverAuthError(int errCode, QString lastSessionError, SshMasterConnection*); 235 void serverAuthAborted(); 236 void userAuthError(QString error); 237 238 void connectionOk( QString host); 239 240 void needPassPhrase(SshMasterConnection*, SshMasterConnection::passphrase_types); 241 void needChallengeResponse(SshMasterConnection*, QString Challenge); 242 void startInteraction(SshMasterConnection*, QString prompt); 243 void finishInteraction(SshMasterConnection*); 244 void updateInteraction(SshMasterConnection*, QString output); 245 }; 246 247 Q_DECLARE_METATYPE (SshMasterConnection::passphrase_types) 248 249 #endif // SSHMASTERCONNECTION_H 250 251