00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00046
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
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
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
00277 } else {
00278 addprocess << "ssh-add";
00279
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
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 }