ExecWrapper tweaks
authorManuel Nickschas <sputnick@quassel-irc.org>
Fri, 13 Mar 2009 18:05:54 +0000 (19:05 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Fri, 13 Mar 2009 19:03:06 +0000 (20:03 +0100)
We now handle params for scripts sanely, plus we refuse to execute ../ in script names
to avoid breaking out of our scripts jail.

src/client/clientuserinputhandler.cpp
src/client/execwrapper.cpp
src/client/execwrapper.h

index a02bc18..610a702 100644 (file)
@@ -67,15 +67,6 @@ void ClientUserInputHandler::handleUserInput(const BufferInfo &bufferInfo, const
 }
 
 void ClientUserInputHandler::handleExec(const BufferInfo &bufferInfo, const QString &execString) {
 }
 
 void ClientUserInputHandler::handleExec(const BufferInfo &bufferInfo, const QString &execString) {
-  QString script;
-  QStringList params;
-  if(execString.contains(' ')) {
-    script = execString.section(' ', 0, 0);
-    params = execString.section(' ', 1).trimmed().split(' '); // FIXME handle args properly, including quoted strings etc
-  } else
-    script = execString;
-
-  ExecWrapper *exec = new ExecWrapper(this);
-  exec->start(bufferInfo, script, params);
-
+  ExecWrapper *exec = new ExecWrapper(this); // gets suicidal when it's done
+  exec->start(bufferInfo, execString);
 }
 }
index b6dfc98..24b5c84 100644 (file)
@@ -36,18 +36,34 @@ ExecWrapper::ExecWrapper(QObject* parent) : QObject(parent) {
   connect(this, SIGNAL(stderr(QString)), SLOT(postStderr(QString)));
 }
 
   connect(this, SIGNAL(stderr(QString)), SLOT(postStderr(QString)));
 }
 
-void ExecWrapper::start(const BufferInfo &info, const QString &scriptName, const QStringList& params) {
+void ExecWrapper::start(const BufferInfo &info, const QString &command) {
   _bufferInfo = info;
   _bufferInfo = info;
-  _scriptName = scriptName;
-  foreach(QString scriptDir, Quassel::scriptDirPaths()) {
-    QString fileName = scriptDir + '/' + scriptName;
-    if(!QFile::exists(fileName))
-      continue;
-    _process.start(fileName, params);
-    return;
+  QString params;
+
+  QRegExp rx("^\\s*(\\S+)(\\s+(.*))?$");
+  if(!rx.exactMatch(command)) {
+    emit stderr(tr("Invalid command string for /exec: %1").arg(command));
+  } else {
+    _scriptName = rx.cap(1);
+    params = rx.cap(3);
   }
   }
-  emit stderr(tr("Could not find script \"%1\"").arg(scriptName));
-  deleteLater();
+
+  // Make sure we don't execute something outside a script dir
+  if(_scriptName.startsWith('/') || _scriptName.contains("../"))
+    emit stderr(tr("Name \"%1\" is invalid: / or ../ are not allowed!").arg(_scriptName));
+
+  else {
+    foreach(QString scriptDir, Quassel::scriptDirPaths()) {
+      QString fileName = scriptDir + _scriptName;
+      if(!QFile::exists(fileName))
+        continue;
+      _process.start(fileName + ' ' + params);
+      return;
+    }
+    emit stderr(tr("Could not find script \"%1\"").arg(_scriptName));
+  }
+
+  deleteLater(); // self-destruct
 }
 
 void ExecWrapper::postStdout(const QString &msg) {
 }
 
 void ExecWrapper::postStdout(const QString &msg) {
@@ -78,6 +94,8 @@ void ExecWrapper::processFinished(int exitCode, QProcess::ExitStatus status) {
 
 void ExecWrapper::processError(QProcess::ProcessError error) {
   emit stderr(tr("Script \"%1\" caused error %2.").arg(_scriptName).arg(error));
 
 void ExecWrapper::processError(QProcess::ProcessError error) {
   emit stderr(tr("Script \"%1\" caused error %2.").arg(_scriptName).arg(error));
+  if(_process.state() != QProcess::Running)
+    deleteLater();
 }
 
 void ExecWrapper::processReadStdout() {
 }
 
 void ExecWrapper::processReadStdout() {
@@ -93,7 +111,7 @@ void ExecWrapper::processReadStderr() {
   _stderrBuffer.append(_process.readAllStandardError());
   int idx;
   while((idx = _stderrBuffer.indexOf('\n')) >= 0) {
   _stderrBuffer.append(_process.readAllStandardError());
   int idx;
   while((idx = _stderrBuffer.indexOf('\n')) >= 0) {
-    emit stdout(_stderrBuffer.left(idx));
+    emit stderr(_stderrBuffer.left(idx));
     _stderrBuffer = _stderrBuffer.mid(idx + 1);
   }
 }
     _stderrBuffer = _stderrBuffer.mid(idx + 1);
   }
 }
index b0c52be..b8a73b7 100644 (file)
@@ -32,7 +32,7 @@ public:
   ExecWrapper(QObject *parent = 0);
 
 public slots:
   ExecWrapper(QObject *parent = 0);
 
 public slots:
-  void start(const BufferInfo &info, const QString &scriptName, const QStringList &params = QStringList());
+  void start(const BufferInfo &info, const QString &command);
 
 signals:
   void stderr(const QString &errorMsg);
 
 signals:
   void stderr(const QString &errorMsg);