Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

sshkeys.cpp

Go to the documentation of this file.
00001 /*
00002  *  ssh-agent key manipulation utility
00003  *
00004  *  (C) 2002 David Woodhouse <dwmw2@infradead.org>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 #include "sshkeys.h"
00022 
00023 #include <qpe/qpeapplication.h>
00024 #include <qdir.h>
00025 #include <qfile.h>
00026 #include <qmultilineedit.h>
00027 #include <qpushbutton.h>
00028 #include <qlistview.h>
00029 #include <qcombobox.h>
00030 
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <fcntl.h>
00034 #include <sys/ioctl.h>
00035 #include <stdlib.h>
00036 #include <unistd.h>
00037 #include <stdio.h>
00038 #include <ctype.h>
00039 
00040 using namespace Opie::Core;
00041 static const char *keynames[] = { "identity", "id_rsa", "id_dsa" };
00042 
00043 
00044 static void detachTerminal() {
00045     /* If we had a controlling TTY, detach from it.
00046        This is to ensure that SSH uses ssh-askpass */
00047     int fd = open("/dev/tty", O_RDONLY);
00048     if (fd != -1) {
00049         ioctl(fd, TIOCNOTTY, NULL);
00050         close(fd);
00051     }
00052 }
00053 
00054 
00055 SSHKeysApp::SSHKeysApp( QWidget* parent,  const char* name, WFlags fl )
00056     : SSHKeysBase( parent, name, fl )
00057 {
00058     detachTerminal();
00059 
00060 
00061     QCString home = QFile::encodeName( QDir::homeDirPath() );
00062     unsigned i;
00063 
00064     connect(AddButton, SIGNAL(clicked()), this, SLOT(doAddButton()));
00065     connect(RefreshListButton, SIGNAL(clicked()), this, SLOT(doRefreshListButton()));
00066     connect(RemoveAllButton, SIGNAL(clicked()), this, SLOT(doRemoveAllButton()));
00067 
00068     connect(&addprocess, SIGNAL(receivedStdout(Opie::Core::OProcess*,char*,int)),
00069             this, SLOT(log_sshadd_output(Opie::Core::OProcess*,char*,int)));
00070     connect(&addprocess, SIGNAL(receivedStderr(Opie::Core::OProcess*,char*,int)),
00071             this, SLOT(log_sshadd_stderr(Opie::Core::OProcess*,char*,int)));
00072     connect(&addprocess, SIGNAL(processExited(Opie::Core::OProcess*)),
00073             this, SLOT(ssh_add_exited(Opie::Core::OProcess*)));
00074 
00075     connect(KeyFileName, SIGNAL(textChanged(const QString&)),
00076         this, SLOT(add_text_changed(const QString&)));
00077 
00078     if (home) {
00079         for (i = 0; i < sizeof(keynames)/sizeof(keynames[0]); i++) {
00080             char thiskeyname[32];
00081 
00082             thiskeyname[31] = 0;
00083             snprintf(thiskeyname, 31, "%s/.ssh/%s", home.data(), keynames[i]);
00084             if (!access(thiskeyname, R_OK)) {
00085                 KeyFileName->insertItem(thiskeyname);
00086             }
00087         }
00088     }
00089 
00090     doRefreshListButton();
00091 }
00092 
00093 SSHKeysApp::~SSHKeysApp()
00094 {
00095 }
00096 
00097 void SSHKeysApp::doRefreshListButton()
00098 {
00099     OProcess sshadd_process;
00100     QListViewItem *t = KeyList->firstChild();
00101 
00102     while(t) {
00103         QListViewItem *next = t->nextSibling();
00104         KeyList->takeItem(t);
00105         delete(t);
00106         t = next;
00107     }
00108 
00109     connect(&sshadd_process, SIGNAL(receivedStdout(Opie::Core::OProcess*,char*,int)),
00110             this, SLOT(get_list_keys_output(Opie::Core::OProcess*,char*,int)));
00111     connect(&sshadd_process, SIGNAL(receivedStderr(Opie::Core::OProcess*,char*,int)),
00112             this, SLOT(log_sshadd_stderr(Opie::Core::OProcess*,char*,int)));
00113 
00114     keystate = KeySize;
00115     incoming_keyname="";
00116     incoming_keysize="";
00117     incoming_keyfingerprint="";
00118 
00119 //    log_text("Running ssh-add -l");
00120     sshadd_process << "ssh-add" << "-l";
00121     bool ret = sshadd_process.start(OProcess::Block, OProcess::AllOutput);
00122     if (!ret) {
00123         log_text(tr("Error running ssh-add"));
00124         return;
00125     }
00126     flush_sshadd_output();
00127     if (sshadd_process.exitStatus() == 2) {
00128         setEnabled(FALSE);
00129     }
00130 }
00131 
00132 void SSHKeysApp::get_list_keys_output(OProcess *proc, char *buffer, int buflen)
00133 {
00134     int i;
00135     (void) proc;
00136 
00137     for (i=0; i<buflen; i++) {
00138         switch(keystate) {
00139         case Noise:
00140         noise:
00141             if (buffer[i] == '\n') {
00142                 log_text(incoming_noise.local8Bit());
00143                 incoming_noise = "";
00144                 keystate = KeySize;
00145             } else {
00146                 incoming_noise += buffer[i];
00147             }
00148             break;
00149 
00150         case KeySize:
00151             if (isdigit(buffer[i])) {
00152                 incoming_keysize += buffer[i];
00153             } else if (buffer[i] == ' ') {
00154                 keystate = KeyFingerprint;
00155             } else {
00156                 incoming_keysize = "";
00157                 incoming_noise = "";
00158                 keystate = Noise;
00159                 goto noise;
00160             }
00161             break;
00162 
00163         case KeyFingerprint:
00164             if (isxdigit(buffer[i]) || buffer[i] == ':') {
00165                 incoming_keyfingerprint += buffer[i];
00166             } else if (buffer[i] == ' ') {
00167                 keystate = KeyName;
00168             } else {
00169                 incoming_keysize = "";
00170                 incoming_keyfingerprint = "";
00171                 incoming_noise = "";
00172                 keystate = Noise;
00173                 goto noise;
00174             }
00175             break;
00176 
00177         case KeyName:
00178             if (buffer[i] == '\n') {
00179                 /* Wheee. Got one. */
00180                 KeyList->insertItem(new
00181                     QListViewItem(KeyList, incoming_keyname, incoming_keysize, incoming_keyfingerprint));
00182                 incoming_keysize = "";
00183                 incoming_keyfingerprint = "";
00184                 incoming_keyname = "";
00185                 keystate = KeySize;
00186             } else if (isprint(buffer[i])) {
00187                 incoming_keyname += buffer[i];
00188             } else {
00189                 incoming_keysize = "";
00190                 incoming_keyfingerprint = "";
00191                 incoming_noise = "";
00192                 keystate = Noise;
00193                 goto noise;
00194             }
00195             break;
00196         }
00197     }
00198 }
00199 
00200 void SSHKeysApp::flush_sshadd_output(void)
00201 {
00202     if (pending_stdout.length()) {
00203         log_text(pending_stdout.ascii());
00204     }
00205     pending_stdout = "";
00206 
00207     if (pending_stderr.length()) {
00208         log_text(pending_stderr.ascii());
00209     }
00210     pending_stderr = "";
00211 }
00212 
00213 void SSHKeysApp::log_sshadd_output(OProcess *proc, char *buffer, int buflen)
00214 {
00215     (void) proc;
00216 
00217     while (buflen) {
00218         if (*buffer == '\n') {
00219             log_text(pending_stdout);
00220             pending_stdout = "";
00221         } else {
00222             pending_stdout += *buffer;
00223         }
00224         buffer++;
00225         buflen--;
00226     }
00227 }
00228 
00229 void SSHKeysApp::log_sshadd_stderr(OProcess *proc, char *buffer, int buflen)
00230 {
00231     (void) proc;
00232 
00233     while (buflen) {
00234         if (*buffer == '\n') {
00235             log_text(pending_stderr);
00236             pending_stderr = "";
00237         } else {
00238             pending_stderr += *buffer;
00239         }
00240         buffer++;
00241         buflen--;
00242     }
00243 }
00244 
00245 void SSHKeysApp::ssh_add_exited(OProcess *proc)
00246 {
00247     (void)proc;
00248 
00249     doRefreshListButton();
00250     setEnabled(TRUE);
00251     if (proc->exitStatus() == 2) {
00252         setEnabled(FALSE);
00253     }
00254 }
00255 
00256 void SSHKeysApp::add_text_changed(const QString &text)
00257 {
00258     struct stat sbuf;
00259 
00260     if (!text.length() || (!access(text.ascii(), R_OK) &&
00261                 !stat(text.ascii(), &sbuf) &&
00262                    S_ISREG(sbuf.st_mode)))
00263         AddButton->setEnabled(TRUE);
00264     else
00265         AddButton->setEnabled(FALSE);
00266 }
00267 
00268 void SSHKeysApp::doAddButton()
00269 {
00270     addprocess.clearArguments();
00271 
00272     setEnabled(FALSE);
00273 
00274     if (KeyFileName->currentText().length()) {
00275         addprocess << "ssh-add" << "--" << KeyFileName->currentText();
00276 //        log_text(QString(tr("Running ssh-add -- ")) + KeyFileName->currentText());
00277     } else {
00278         addprocess << "ssh-add";
00279 //        log_text(tr("Running ssh-add"));
00280     }
00281     bool ret = addprocess.start(OProcess::NotifyOnExit, OProcess::AllOutput);
00282     if (!ret) {
00283         log_text(tr("Error running ssh-add"));
00284         doRefreshListButton();
00285         setEnabled(TRUE);
00286     }
00287     flush_sshadd_output();
00288 }
00289 
00290 void SSHKeysApp::log_text(const char *text)
00291 {
00292     TextOutput->append(text);
00293     TextOutput->setCursorPosition(TextOutput->numLines()+1, 0, FALSE);
00294 }
00295 
00296 void SSHKeysApp::doRemoveAllButton()
00297 {
00298     OProcess sshadd_process;
00299 
00300     connect(&sshadd_process, SIGNAL(receivedStdout(Opie::Core::OProcess*,char*,int)),
00301             this, SLOT(log_sshadd_output(Opie::Core::OProcess*,char*,int)));
00302     connect(&sshadd_process, SIGNAL(receivedStderr(Opie::Core::OProcess*,char*,int)),
00303             this, SLOT(log_sshadd_stderr(Opie::Core::OProcess*,char*,int)));
00304 
00305 //    log_text(tr("Running ssh-add -D"));
00306     sshadd_process << "ssh-add" << "-D";
00307     bool ret = sshadd_process.start(OProcess::Block, OProcess::AllOutput);
00308     if (!ret) {
00309         log_text(tr("Error running ssh-add"));
00310     }
00311     flush_sshadd_output();
00312     doRefreshListButton();
00313 }

Generated on Sat Nov 5 16:17:57 2005 for OPIE by  doxygen 1.4.2