• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDEsu

ssh.cpp

Go to the documentation of this file.
00001 /* vi: ts=8 sts=4 sw=4
00002 *
00003 * $Id: ssh.cpp 397696 2005-03-15 01:33:05Z dmacvicar $
00004 *
00005 * This file is part of the KDE project, module kdesu.
00006 * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
00007 *
00008 * This is free software; you can use this library under the GNU Library
00009 * General Public License, version 2. See the file "COPYING.LIB" for the
00010 * exact licensing terms.
00011 *
00012 * ssh.cpp: Execute a program on a remote machine using ssh.
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 * Create a port forwarding for DCOP. For the remote port, we take a pseudo
00142 * random number between 10k and 50k. This is not ok, of course, but I see
00143 * no other way. There is, afaik, no security issue involved here. If the port
00144 * happens to be occupied, ssh will refuse to start.
00145 *
00146 * 14/SEP/2000: DCOP forwarding is not used anymore.
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 * Conversation with ssh.
00181 * If check is 0, this waits for either a "Password: " prompt,
00182 * or the header of the stub. If a prompt is received, the password is
00183 * written back. Used for running a command.
00184 * If check is 1, operation is the same as 0 except that if a stub header is
00185 * received, the stub is stopped with the "stop" command. This is used for
00186 * checking a password.
00187 * If check is 2, operation is the same as 1, except that no password is
00188 * written. The prompt is saved to m_Prompt. Used for checking the need for
00189 * a password.
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             // Check for "kdesu_stub" header.
00209             if (line == "kdesu_stub")
00210             {
00211                 unreadLine(line);
00212                 return 0;
00213             }
00214     
00215             // Match "Password: " with the regex ^[^:]+:[\w]*$.
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             // Warning/error message.
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 // Display redirection is handled by ssh natively.
00260 QCString SshProcess::display()
00261 {
00262     return "no";
00263 }
00264 
00265 
00266 QCString SshProcess::displayAuth()
00267 {
00268     return "no";
00269 }
00270 
00271 
00272 // Return the remote end of the forwarded connection.
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 ); }

KDEsu

Skip menu "KDEsu"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal