KDEsu
ssh.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <config.h>
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 #include <fcntl.h>
00021 #include <signal.h>
00022 #include <errno.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include <signal.h>
00026 #include <time.h>
00027
00028 #include <sys/types.h>
00029 #include <sys/stat.h>
00030
00031 #include <qglobal.h>
00032 #include <qcstring.h>
00033
00034 #include <kdebug.h>
00035 #include <klocale.h>
00036 #include <kstandarddirs.h>
00037
00038 #include "ssh.h"
00039 #include "kcookie.h"
00040
00041
00042 SshProcess::SshProcess(const QCString &host, const QCString &user, const QCString &command)
00043 {
00044 m_Host = host;
00045 m_User = user;
00046 m_Command = command;
00047 m_Stub = "kdesu_stub";
00048 srand(time(0L));
00049 }
00050
00051
00052 SshProcess::~SshProcess()
00053 {
00054 }
00055
00056
00057 void SshProcess::setStub(const QCString &stub)
00058 {
00059 m_Stub = stub;
00060 }
00061
00062
00063 int SshProcess::checkInstall(const char *password)
00064 {
00065 return exec(password, 1);
00066 }
00067
00068
00069 int SshProcess::checkNeedPassword()
00070 {
00071 return exec(0L, 2);
00072 }
00073
00074
00075 int SshProcess::exec(const char *password, int check)
00076 {
00077 if (check)
00078 setTerminal(true);
00079
00080 QCStringList args;
00081 args += "-l"; args += m_User;
00082 args += "-o"; args += "StrictHostKeyChecking=no";
00083 args += m_Host; args += m_Stub;
00084
00085 if (StubProcess::exec("ssh", args) < 0)
00086 {
00087 return check ? SshNotFound : -1;
00088 }
00089
00090 int ret = ConverseSsh(password, check);
00091 if (ret < 0)
00092 {
00093 if (!check)
00094 kdError(900) << k_lineinfo << "Conversation with ssh failed\n";
00095 return ret;
00096 }
00097 if (check == 2)
00098 {
00099 if (ret == 1)
00100 {
00101 kill(m_Pid, SIGTERM);
00102 waitForChild();
00103 }
00104 return ret;
00105 }
00106
00107 if (m_bErase && password)
00108 {
00109 char *ptr = const_cast<char *>(password);
00110 const uint plen = strlen(password);
00111 for (unsigned i=0; i < plen; i++)
00112 ptr[i] = '\000';
00113 }
00114
00115 ret = ConverseStub(check);
00116 if (ret < 0)
00117 {
00118 if (!check)
00119 kdError(900) << k_lineinfo << "Converstation with kdesu_stub failed\n";
00120 return ret;
00121 }
00122 else if (ret == 1)
00123 {
00124 kill(m_Pid, SIGTERM);
00125 waitForChild();
00126 ret = SshIncorrectPassword;
00127 }
00128
00129 if (check == 1)
00130 {
00131 waitForChild();
00132 return 0;
00133 }
00134
00135 setExitString("Waiting for forwarded connections to terminate");
00136 ret = waitForChild();
00137 return ret;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 QCString SshProcess::dcopForward()
00150 {
00151 QCString result;
00152
00153 setDcopTransport("tcp");
00154
00155 QCString srv = StubProcess::dcopServer();
00156 if (srv.isEmpty())
00157 return result;
00158
00159 int i = srv.find('/');
00160 if (i == -1)
00161 return result;
00162 if (srv.left(i) != "tcp")
00163 return result;
00164 int j = srv.find(':', ++i);
00165 if (j == -1)
00166 return result;
00167 QCString host = srv.mid(i, j-i);
00168 bool ok;
00169 int port = srv.mid(++j).toInt(&ok);
00170 if (!ok)
00171 return result;
00172
00173 m_dcopPort = 10000 + (int) ((40000.0 * rand()) / (1.0 + RAND_MAX));
00174 result.sprintf("%d:%s:%d", m_dcopPort, host.data(), port);
00175 return result;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 int SshProcess::ConverseSsh(const char *password, int check)
00193 {
00194 unsigned i, j, colon;
00195
00196 QCString line;
00197 int state = 0;
00198
00199 while (state < 2)
00200 {
00201 line = readLine();
00202 const uint len = line.length();
00203 if (line.isNull())
00204 return -1;
00205
00206 switch (state) {
00207 case 0:
00208
00209 if (line == "kdesu_stub")
00210 {
00211 unreadLine(line);
00212 return 0;
00213 }
00214
00215
00216 for (i=0,j=0,colon=0; i<len; i++)
00217 {
00218 if (line[i] == ':')
00219 {
00220 j = i; colon++;
00221 continue;
00222 }
00223 if (!isspace(line[i]))
00224 j++;
00225 }
00226 if ((colon == 1) && (line[j] == ':'))
00227 {
00228 if (check == 2)
00229 {
00230 m_Prompt = line;
00231 return SshNeedsPassword;
00232 }
00233 WaitSlave();
00234 write(m_Fd, password, strlen(password));
00235 write(m_Fd, "\n", 1);
00236 state++;
00237 break;
00238 }
00239
00240
00241 m_Error += line; m_Error += "\n";
00242 if (m_bTerminal)
00243 fprintf(stderr, "ssh: %s\n", line.data());
00244 break;
00245
00246 case 1:
00247 if (line.isEmpty())
00248 {
00249 state++;
00250 break;
00251 }
00252 return -1;
00253 }
00254 }
00255 return 0;
00256 }
00257
00258
00259
00260 QCString SshProcess::display()
00261 {
00262 return "no";
00263 }
00264
00265
00266 QCString SshProcess::displayAuth()
00267 {
00268 return "no";
00269 }
00270
00271
00272
00273 QCString SshProcess::dcopServer()
00274 {
00275 return QCString().sprintf("tcp/localhost:%d", m_dcopPort);
00276 }
00277
00278 void SshProcess::virtual_hook( int id, void* data )
00279 { StubProcess::virtual_hook( id, data ); }