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