diff options
Diffstat (limited to 'cervisia/cvsservice/sshagent.cpp')
-rw-r--r-- | cervisia/cvsservice/sshagent.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/cervisia/cvsservice/sshagent.cpp b/cervisia/cvsservice/sshagent.cpp new file mode 100644 index 00000000..48bc5eef --- /dev/null +++ b/cervisia/cvsservice/sshagent.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2003 Christian Loose <christian.loose@hamburg.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "sshagent.h" + +#include <qregexp.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kprocess.h> + +#include <stdlib.h> + + +// initialize static member variables +bool SshAgent::m_isRunning = false; +bool SshAgent::m_isOurAgent = false; +QString SshAgent::m_authSock = QString::null; +QString SshAgent::m_pid = QString::null; + + +SshAgent::SshAgent(QObject* parent, const char* name) + : QObject(parent, name) +{ +} + + +SshAgent::~SshAgent() +{ +} + + +bool SshAgent::querySshAgent() +{ + kdDebug(8051) << "SshAgent::querySshAgent(): ENTER" << endl; + + if( m_isRunning ) + return true; + + // Did the user already start a ssh-agent process? + char* pid; + if( (pid = ::getenv("SSH_AGENT_PID")) != 0 ) + { + kdDebug(8051) << "SshAgent::querySshAgent(): ssh-agent already exists" + << endl; + + m_pid = QString::fromLocal8Bit(pid); + + char* sock = ::getenv("SSH_AUTH_SOCK"); + if( sock ) + m_authSock = QString::fromLocal8Bit(sock); + + m_isOurAgent = false; + m_isRunning = true; + } + // We have to start a new ssh-agent process + else + { + kdDebug(8051) << "SshAgent::querySshAgent(): start ssh-agent" << endl; + + m_isOurAgent = true; + m_isRunning = startSshAgent(); + } + + return m_isRunning; +} + + +bool SshAgent::addSshIdentities() +{ + kdDebug(8051) << "SshAgent::addSshIdentities(): ENTER" << endl; + + if( !m_isRunning || !m_isOurAgent ) + return false; + + // add identities to ssh-agent + KProcess proc; + + proc.setEnvironment("SSH_AGENT_PID", m_pid); + proc.setEnvironment("SSH_AUTH_SOCK", m_authSock); + proc.setEnvironment("SSH_ASKPASS", "cvsaskpass"); + + proc << "ssh-add"; + + connect(&proc, SIGNAL(receivedStdout(KProcess*, char*, int)), + SLOT(slotReceivedStdout(KProcess*, char*, int))); + connect(&proc, SIGNAL(receivedStderr(KProcess*, char*, int)), + SLOT(slotReceivedStderr(KProcess*, char*, int))); + + proc.start(KProcess::DontCare, KProcess::AllOutput); + + // wait for process to finish + // TODO CL use timeout? + proc.wait(); + + kdDebug(8051) << "SshAgent::slotProcessExited(): added identities" << endl; + + return (proc.normalExit() && proc.exitStatus() == 0); +} + + +void SshAgent::killSshAgent() +{ + kdDebug(8051) << "SshAgent::killSshAgent(): ENTER" << endl; + + if( !m_isRunning || !m_isOurAgent ) + return; + + KProcess proc; + + proc << "kill" << m_pid; + + proc.start(KProcess::DontCare, KProcess::NoCommunication); + + kdDebug(8051) << "SshAgent::killSshAgent(): killed pid = " << m_pid << endl; +} + + +void SshAgent::slotProcessExited(KProcess*) +{ + kdDebug(8051) << "SshAgent::slotProcessExited(): ENTER" << endl; + + QRegExp cshPidRx("setenv SSH_AGENT_PID (\\d*);"); + QRegExp cshSockRx("setenv SSH_AUTH_SOCK (.*);"); + + QRegExp bashPidRx("SSH_AGENT_PID=(\\d*).*"); + QRegExp bashSockRx("SSH_AUTH_SOCK=(.*\\.\\d*);.*"); + + QStringList::Iterator it = m_outputLines.begin(); + QStringList::Iterator end = m_outputLines.end(); + for( ; it != end; ++it ) + { + if( m_pid.isEmpty() ) + { + int pos = cshPidRx.search(*it); + if( pos > -1 ) + { + m_pid = cshPidRx.cap(1); + continue; + } + + pos = bashPidRx.search(*it); + if( pos > -1 ) + { + m_pid = bashPidRx.cap(1); + continue; + } + } + + if( m_authSock.isEmpty() ) + { + int pos = cshSockRx.search(*it); + if( pos > -1 ) + { + m_authSock = cshSockRx.cap(1); + continue; + } + + pos = bashSockRx.search(*it); + if( pos > -1 ) + { + m_authSock = bashSockRx.cap(1); + continue; + } + } + } + + kdDebug(8051) << "SshAgent::slotProcessExited(): pid = " << m_pid + << ", socket = " << m_authSock << endl; +} + + +void SshAgent::slotReceivedStdout(KProcess* proc, char* buffer, int buflen) +{ + Q_UNUSED(proc); + + QString output = QString::fromLocal8Bit(buffer, buflen); + m_outputLines += QStringList::split("\n", output); + + kdDebug(8051) << "SshAgent::slotReceivedStdout(): output = " << output << endl; +} + + +void SshAgent::slotReceivedStderr(KProcess* proc, char* buffer, int buflen) +{ + Q_UNUSED(proc); + + QString output = QString::fromLocal8Bit(buffer, buflen); + m_outputLines += QStringList::split("\n", output); + + kdDebug(8051) << "SshAgent::slotReceivedStderr(): output = " << output << endl; +} + + +bool SshAgent::startSshAgent() +{ + kdDebug(8051) << "SshAgent::startSshAgent(): ENTER" << endl; + + KProcess proc; + + proc << "ssh-agent"; + + connect(&proc, SIGNAL(processExited(KProcess*)), + SLOT(slotProcessExited(KProcess*))); + connect(&proc, SIGNAL(receivedStdout(KProcess*, char*, int)), + SLOT(slotReceivedStdout(KProcess*, char*, int))); + connect(&proc, SIGNAL(receivedStderr(KProcess*, char*, int)), + SLOT(slotReceivedStderr(KProcess*, char*, int)) ); + + proc.start(KProcess::NotifyOnExit, KProcess::All); + + // wait for process to finish + // TODO CL use timeout? + proc.wait(); + + return (proc.normalExit() && proc.exitStatus() == 0); +} + + +#include "sshagent.moc" |