summaryrefslogtreecommitdiffstats
path: root/src/helpers/sshagent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/helpers/sshagent.cpp')
-rw-r--r--src/helpers/sshagent.cpp257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/helpers/sshagent.cpp b/src/helpers/sshagent.cpp
new file mode 100644
index 0000000..ccde212
--- /dev/null
+++ b/src/helpers/sshagent.cpp
@@ -0,0 +1,257 @@
+/*
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sshagent.h"
+#include "kdesvn-config.h"
+
+#include <qregexp.h>
+#include <kapplication.h>
+#include <kdeversion.h>
+#include <kprocess.h>
+#include <kdebug.h>
+
+#include <stdlib.h>
+
+
+// initialize static member variables
+bool SshAgent::m_isRunning = false;
+bool SshAgent::m_isOurAgent = false;
+bool SshAgent::m_addIdentitiesDone = 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()
+{
+ if( m_isRunning )
+ return true;
+
+ // Did the user already start a ssh-agent process?
+ char* pid;
+ if( (pid = ::getenv("SSH_AGENT_PID")) != 0 )
+ {
+ m_pid = QString::fromLocal8Bit(pid);
+
+ char* sock = ::getenv("SSH_AUTH_SOCK");
+ if( sock )
+ m_authSock = QString::fromLocal8Bit(sock);
+ /* make sure that we have a askpass program.
+ * on some systems something like that isn't installed.*/
+#ifdef FORCE_ASKPASS
+ kdDebug()<<"Using test askpass"<<endl;
+#ifdef HAS_SETENV
+ ::setenv("SSH_ASKPASS",FORCE_ASKPASS,1);
+#else
+ ::putenv("SSH_ASKPASS="FORCE_ASKPASS);
+#endif
+#else
+/*
+ char*agent = ::getenv("SSH_ASKPASS");
+ if (!agent) {
+*/
+#ifdef HAS_SETENV
+ ::setenv("SSH_ASKPASS", "kdesvnaskpass",1);
+#else
+ ::putenv("SSH_ASKPASS=kdesvnaskpass");
+#endif
+/*
+ }
+*/
+#endif
+ m_isOurAgent = false;
+ m_isRunning = true;
+ }
+ // We have to start a new ssh-agent process
+ else
+ {
+ m_isOurAgent = true;
+ m_isRunning = startSshAgent();
+ }
+
+ return m_isRunning;
+}
+
+
+bool SshAgent::addSshIdentities(bool force)
+{
+ if (m_addIdentitiesDone && !force) {
+ return true;
+ }
+
+
+ if( !m_isRunning || (!m_isOurAgent&&!force)) {
+ return false;
+ }
+
+ // add identities to ssh-agent
+ KProcess proc;
+
+ proc.setEnvironment("SSH_AGENT_PID", m_pid);
+ proc.setEnvironment("SSH_AUTH_SOCK", m_authSock);
+
+#ifdef FORCE_ASKPASS
+ kdDebug()<<"Using test askpass"<<endl;
+ proc.setEnvironment("SSH_ASKPASS",FORCE_ASKPASS);
+#else
+ char*agent = 0;
+/*
+ if (force) {
+ agent = ::getenv("SSH_ASKPASS");
+ }
+*/
+ if (!agent) {
+ proc.setEnvironment("SSH_ASKPASS", "kdesvnaskpass");
+ }
+#endif
+
+ 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();
+
+ m_addIdentitiesDone = proc.normalExit() && proc.exitStatus() == 0;
+ return m_addIdentitiesDone;
+}
+
+
+void SshAgent::killSshAgent()
+{
+ if( !m_isRunning || !m_isOurAgent )
+ return;
+
+ KProcess proc;
+
+ proc << "kill" << m_pid;
+
+ proc.start(KProcess::DontCare, KProcess::NoCommunication);
+}
+
+
+void SshAgent::slotProcessExited(KProcess*)
+{
+ 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 m_outputLines = QStringList::split("\n",m_Output);
+
+ 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;
+ }
+ }
+ }
+
+}
+
+
+void SshAgent::slotReceivedStdout(KProcess* proc, char* buffer, int buflen)
+{
+ Q_UNUSED(proc);
+
+ QString output = QString::fromLocal8Bit(buffer, buflen);
+ m_Output+=output;
+}
+
+
+void SshAgent::slotReceivedStderr(KProcess* proc, char* buffer, int buflen)
+{
+ Q_UNUSED(proc);
+
+ QString output = QString::fromLocal8Bit(buffer, buflen);
+ m_Output+=output;
+}
+
+
+bool SshAgent::startSshAgent()
+{
+ 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"