]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Add first (not yet tested) cut of bcomm to the qt-console directory.
authorKern Sibbald <kern@sibbald.com>
Fri, 17 Aug 2007 10:18:43 +0000 (10:18 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 17 Aug 2007 10:18:43 +0000 (10:18 +0000)
     This class is intended to allow us to open a second bsock to the
     Director while in the restore subdialog.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5366 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/LICENSE
bacula/autoconf/Make.common.in
bacula/src/qt-console/bat.h
bacula/src/qt-console/bat.pro.in
bacula/src/qt-console/bcomm/dircomm.cpp [new file with mode: 0644]
bacula/src/qt-console/bcomm/dircomm.h [new file with mode: 0644]
bacula/src/qt-console/bcomm/dircomm_auth.cpp [new file with mode: 0644]
bacula/src/qt-console/console/console.cpp
bacula/technotes-2.1

index e105b738836f2bde058cffea9091f9fe404f254d..07a17f8eeebddd149530f72abaad3d78655828ec 100644 (file)
@@ -12,8 +12,9 @@ The name Bacula is a registered trademark.
 License:
 For the most part, Bacula is licensed under the GPL version 2
 this code is listed under Copyright Free Software Foundation
-Europe e.V. A small part of the code (less than 20 files) is
-copyrighted under the GPL by other people (FSF, Sun, ...). 
+Europe e.V. A small part of the code (less than 10 files) is
+copyrighted under the GPL by FSF, or under BSD licenses by various
+authors (see below).
 
 What follows is information from the authors of the code:
 
@@ -21,7 +22,7 @@ Linking:
 Bacula may be linked with any libraries permitted under the GPL.
 However, if configured with encryption Bacula does use the
 OpenSSL libraries which are, unfortunately, not compatible with
-GPL v2.  To the best of our knowledge these libaries are not
+GPL v2.  To the best of our knowledge these libraries are not
 distributed with Bacula code because they are shared objects, and
 as such there is no conflict with the GPL according what I (Kern)
 understand in talking to FSFE, and in any case, for the code that
@@ -88,7 +89,7 @@ Bacula File daemon is copyrighted and or trademarked by Microsoft
 and may contain Microsoft intellectual property (examples:
 Microsoft VC++, the source to the VSS libraries, the Microsoft C
 runtime libraries).  As such we cannot and do not distribute that
-software.  We are permitted however to distribut Bacula with the
+software.  We are permitted however to distribute Bacula with the
 necessary Microsoft libraries in binary form.
 
 You may obtain the parts that we cannot distribute as follows.  The
@@ -101,6 +102,42 @@ so themselves.  Our intention is to respect as closely as possible Open
 Source practices while maintaining full respect for proprietary and
 copyrighted code.
 
+BSD code used in the Windows version only:
+Code falling under the BSD license has the following license:
+
+   Copyright (c)2002-2003 Mark K. Kim
+   All rights reserved.
+   
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in
+       the documentation and/or other materials provided with the
+       distribution.
+
+     * Neither the original author of this software nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+   DAMAGE.
+
+
 =====================================
 
 The entire GPL is reproduced below, in the manuals distributed with the
@@ -124,8 +161,8 @@ freedom to publish or distribute modified versions when you wish.
 
 Other Licenses:
 Certain parts of the Bacula software are licensed by their
-copyright holder(s) under the GPL. These software files are
-clearly marked as such.
+copyright holder(s) under the GPL or under the BSD license. 
+These software files are clearly marked as such.
 
 Bacula can be enabled with data encryption and/or communications
 encryption. If this is the case, you will be including OpenSSL code that
@@ -151,6 +188,9 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+=====================================
+
+
 ============== Text of GPL version 2 license ========
 
                     GNU GENERAL PUBLIC LICENSE
index 60d2f621e20f6ec665761e044cdd88051f060bfc..155e4e591edea2cfaad80f5f63eb77972777e728 100644 (file)
@@ -1,5 +1,8 @@
-# autoconf/Make.common.in       -*- Makefile -*-
-# release date (man), LSM date, version number/name, current maintainer
+#
+# This file is pulled in by all the Unix Bacula Makefiles
+#   so it has all the "common" definitions
+#
+
 DATE="@DATE@"
 LSMDATE=@LSMDATE@
 VERSION=@VERSION@
index 85deda5cc5d4881a703574077940420ba1e25207..608b15cc603e465d33404b8491a3dd77aec4ebcb 100644 (file)
@@ -42,9 +42,7 @@
 #include "bat_conf.h"
 #include "jcr.h"
 #include "console.h"
-#include "qstd.h"
 
-using namespace qstd;
 
 extern MainWin *mainWin;
 extern QApplication *app;
index ce99dc83355cdd4c136b9813535d7e559235f031..acb80cf356047608d7b9c887d9bb306f66dc9cbe 100644 (file)
@@ -14,19 +14,18 @@ bins.files = ./bat
 confs.path = /$(DESTDIR)@sysconfdir@
 confs.commands = ./install_conf_file   
 
-TEMPLATE = app
-TARGET = bat
-DEPENDPATH += .
+TEMPLATE     = app
+TARGET       = bat
+DEPENDPATH  += .
 INCLUDEPATH += .. . ./console ./restore ./select
-INCLUDEPATH += @QWT_INC@
-LIBS        += -L../lib            
-LIBS        += -lbac
-LIBS        += -lssl -lcrypto
+INCLUDEPATH += @QWT_INC@ 
+LIBS        += -L../lib -lbac @OPENSSL_LIBS@
 LIBS        += @QWT_LDFLAGS@ -lqwt
-RESOURCES = main.qrc
-MOC_DIR = moc
-OBJECTS_DIR = obj
-UI_DIR = ui
+
+RESOURCES    = main.qrc
+MOC_DIR      = moc
+OBJECTS_DIR  = obj
+UI_DIR       = ui
 
 # Main window
 FORMS += main.ui 
@@ -45,8 +44,13 @@ FORMS += joblog/joblog.ui jobs/jobs.ui
 FORMS += help/help.ui
 FORMS += jobgraphs/jobplotcontrols.ui
 
-HEADERS += mainwin.h bat.h bat_conf.h qstd.h
-SOURCES += main.cpp bat_conf.cpp mainwin.cpp qstd.cpp
+# Main directory
+HEADERS += mainwin.h bat.h bat_conf.h qstd.h pages.h
+SOURCES += main.cpp bat_conf.cpp mainwin.cpp qstd.cpp pages.cpp
+
+# bcomm
+HEADERS += bcomm/dircomm.h
+SOURCES += bcomm/dircomm.cpp bcomm/dircomm_auth.cpp
 
 # Console
 HEADERS += console/console.h
@@ -76,10 +80,6 @@ SOURCES += run/run.cpp run/runcmd.cpp run/estimate.cpp run/prune.cpp
 HEADERS += select/select.h
 SOURCES += select/select.cpp
 
-## Pages
-HEADERS += pages.h
-SOURCES += pages.cpp
-
 ## MediaList
 HEADERS += medialist/medialist.h
 SOURCES += medialist/medialist.cpp
diff --git a/bacula/src/qt-console/bcomm/dircomm.cpp b/bacula/src/qt-console/bcomm/dircomm.cpp
new file mode 100644 (file)
index 0000000..b045645
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   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
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ *   Version $Id$
+ *
+ *  Bacula Communications class that is at a higher level than BSOCK
+ *
+ *   Kern Sibbald, May MMVII
+ *
+ */ 
+
+#include "bat.h"
+#include "console.h"
+#include "restore.h"
+#include "select.h"
+#include "run/run.h"
+#include "dircomm.h"
+
+static int tls_pem_callback(char *buf, int size, const void *userdata);
+
+
+DirComm::DirComm(Console *console)
+{
+   m_console = console;
+   m_sock = NULL;
+   m_at_prompt = false;
+   m_at_main_prompt = false;
+   m_timer = NULL;
+}
+
+DirComm::~DirComm()
+{
+   if (m_timer) {
+      stopTimer();
+   }
+}
+
+void DirComm::startTimer()
+{
+   m_timer = new QTimer(m_console);
+   QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
+   m_timer->start(mainWin->m_checkMessagesInterval*1000);
+}
+
+void DirComm::stopTimer()
+{
+   if (m_timer) {
+      QWidget::disconnect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
+      m_timer->stop();
+      delete m_timer;
+      m_timer = NULL;
+   }
+}
+      
+void DirComm::poll_messages()
+{
+   m_messages_pending = true;
+   if ((m_at_main_prompt) && (mainWin->m_checkMessages)){
+      write(".messages");
+      displayToPrompt();
+   }
+}
+
+/* Terminate any open socket */
+void DirComm::terminate()
+{
+   if (m_sock) {
+      stopTimer();
+      m_sock->close();
+      m_sock = NULL;
+   }
+}
+
+/*
+ * Connect to Director. 
+ */
+void DirComm::connect_dir(DIRRES *dir, CONRES *cons)
+{
+   JCR jcr;
+   utime_t heart_beat;
+   char buf[1024];
+
+   m_dir = dir;
+   if (!m_dir) {          
+      mainWin->set_status("No Director found.");
+      return;
+   }
+   if (m_sock) {
+      mainWin->set_status("Already connected.");
+      return;
+   }
+
+   memset(&jcr, 0, sizeof(jcr));
+
+   mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
+   m_console->display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
+
+   /* Give GUI a chance */
+   app->processEvents();
+   
+   /* Initialize Console TLS context once */
+   if (cons && !cons->tls_ctx && (cons->tls_enable || cons->tls_require)) {
+      /* Generate passphrase prompt */
+      bsnprintf(buf, sizeof(buf), "Passphrase for Console \"%s\" TLS private key: ", 
+                cons->name());
+
+      /* Initialize TLS context:
+       * Args: CA certfile, CA certdir, Certfile, Keyfile,
+       * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer   
+       */
+      cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
+         cons->tls_ca_certdir, cons->tls_certfile,
+         cons->tls_keyfile, tls_pem_callback, &buf, NULL, true);
+
+      if (!cons->tls_ctx) {
+         m_console->display_textf(_("Failed to initialize TLS context for Console \"%s\".\n"),
+            m_dir->name());
+         return;
+      }
+   }
+
+   /* Initialize Director TLS context once */
+   if (!m_dir->tls_ctx && (m_dir->tls_enable || m_dir->tls_require)) {
+      /* Generate passphrase prompt */
+      bsnprintf(buf, sizeof(buf), "Passphrase for Director \"%s\" TLS private key: ", 
+                m_dir->name());
+
+      /* Initialize TLS context:
+       * Args: CA certfile, CA certdir, Certfile, Keyfile,
+       * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
+      m_dir->tls_ctx = new_tls_context(m_dir->tls_ca_certfile,
+                          m_dir->tls_ca_certdir, m_dir->tls_certfile,
+                          m_dir->tls_keyfile, tls_pem_callback, &buf, NULL, true);
+
+      if (!m_dir->tls_ctx) {
+         m_console->display_textf(_("Failed to initialize TLS context for Director \"%s\".\n"),
+            m_dir->name());
+         mainWin->set_status("Connection failed");
+         return;
+      }
+   }
+
+   if (m_dir->heartbeat_interval) {
+      heart_beat = m_dir->heartbeat_interval;
+   } else if (cons) {
+      heart_beat = cons->heartbeat_interval;
+   } else {
+      heart_beat = 0;
+   }        
+
+   m_sock = bnet_connect(NULL, 5, 15, heart_beat,
+                          _("Director daemon"), m_dir->address,
+                          NULL, m_dir->DIRport, 0);
+   if (m_sock == NULL) {
+      mainWin->set_status("Connection failed");
+      return;
+   } else {
+      /* Update page selector to green to indicate that Console is connected */
+      mainWin->actionConnect->setIcon(QIcon(":images/connected.png"));
+      QBrush greenBrush(Qt::green);
+      QTreeWidgetItem *item = mainWin->getFromHash(this);
+      item->setForeground(0, greenBrush);
+   }
+
+   jcr.dir_bsock = m_sock;
+
+   if (!authenticate_director(&jcr, m_dir, cons, buf, sizeof(buf))) {
+      m_console->display_text(buf);
+      return;
+   }
+   if (buf[0]) {
+      m_console->display_text(buf);
+   }
+
+   /* Give GUI a chance */
+   app->processEvents();
+
+   mainWin->set_status(_("Initializing ..."));
+
+   /* Set up input notifier */
+   m_notifier = new QSocketNotifier(m_sock->m_fd, QSocketNotifier::Read, 0);
+   QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
+
+   mainWin->set_status(_("Connected"));
+   startTimer();                      /* start message timer */
+   return;
+}
+
+bool DirComm::dir_cmd(QString &cmd, QStringList &results)
+{
+   return dir_cmd(cmd.toUtf8().data(), results);
+}
+
+/*
+ * Send a command to the Director, and return the
+ *  results in a QStringList.  
+ */
+bool DirComm::dir_cmd(const char *cmd, QStringList &results)
+{
+   int stat;
+
+   notify(false);
+   write(cmd);
+   while ((stat = read()) > 0) {
+      if (mainWin->m_displayAll) m_console->display_text(msg());
+      strip_trailing_junk(msg());
+      results << msg();
+   }
+   notify(true);
+   discardToPrompt();
+   return true;              /* ***FIXME*** return any command error */
+}
+
+bool DirComm::sql_cmd(QString &query, QStringList &results)
+{
+   return sql_cmd(query.toUtf8().data(), results);
+}
+
+/*
+ * Send an sql query to the Director, and return the
+ *  results in a QStringList.  
+ */
+bool DirComm::sql_cmd(const char *query, QStringList &results)
+{
+   int stat;
+   POOL_MEM cmd(PM_MESSAGE);
+
+   if (!is_connectedGui()) {
+      return false;
+   }
+
+   notify(false);
+   
+   pm_strcpy(cmd, ".sql query=\"");
+   pm_strcat(cmd, query);
+   pm_strcat(cmd, "\"");
+   write(cmd.c_str());
+   while ((stat = read()) > 0) {
+      if (mainWin->m_displayAll) m_console->display_text(msg());
+      strip_trailing_junk(msg());
+      results << msg();
+   }
+   notify(true);
+   discardToPrompt();
+   return true;              /* ***FIXME*** return any command error */
+}
+
+/* 
+ * This should be moved into a bSocket class 
+ */
+char *DirComm::msg()
+{
+   if (m_sock) {
+      return m_sock->msg;
+   }
+   return NULL;
+}
+
+/* Send a command to the Director */
+void DirComm::write_dir(const char *msg)
+{
+   if (m_sock) {
+      mainWin->set_status(_("Processing command ..."));
+      QApplication::setOverrideCursor(Qt::WaitCursor);
+      write(msg);
+   } else {
+      mainWin->set_status(" Director not connected. Click on connect button.");
+      mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
+      QBrush redBrush(Qt::red);
+      QTreeWidgetItem *item = mainWin->getFromHash(this);
+      item->setForeground(0, redBrush);
+      m_at_prompt = false;
+      m_at_main_prompt = false;
+   }
+}
+
+int DirComm::write(const QString msg)
+{
+   return write(msg.toUtf8().data());
+}
+
+int DirComm::write(const char *msg)
+{
+   if (!m_sock) {
+      return -1;
+   }
+   m_sock->msglen = pm_strcpy(m_sock->msg, msg);
+   m_at_prompt = false;
+   m_at_main_prompt = false;
+   if (mainWin->m_commDebug) Pmsg1(000, "send: %s\n", msg);
+   return m_sock->send();
+
+}
+
+/*
+ * Get to main command prompt -- i.e. abort any suDirCommand
+ */
+void DirComm::beginNewCommand()
+{
+   for (int i=0; i < 3; i++) {
+      write(".\n");
+      while (read() > 0) {
+         if (mainWin->m_displayAll) m_console->display_text(msg());
+      }
+      if (m_at_main_prompt) {
+         break;
+      }
+   }
+   m_console->display_text("\n");
+}
+
+void DirComm::displayToPrompt()
+{ 
+   int stat = 0;
+   if (mainWin->m_commDebug) Pmsg0(000, "DisplaytoPrompt\n");
+   while (!m_at_prompt) {
+      if ((stat=read()) > 0) {
+         m_console->display_text(msg());
+      }
+   }
+   if (mainWin->m_commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
+}
+
+void DirComm::discardToPrompt()
+{ 
+   int stat = 0;
+   if (mainWin->m_commDebug) Pmsg0(000, "discardToPrompt\n");
+   while (!m_at_prompt) {
+      if ((stat=read()) > 0) {
+         if (mainWin->m_displayAll) m_console->display_text(msg());
+      }
+   }
+   if (mainWin->m_commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
+}
+
+
+/* 
+ * Blocking read from director
+ */
+int DirComm::read()
+{
+   int stat = 0;
+   while (m_sock) {
+      for (;;) {
+         stat = bnet_wait_data_intr(m_sock, 1);
+         if (stat > 0) {
+            break;
+         } 
+         app->processEvents();
+         if (m_api_set && m_messages_pending) {
+            write_dir(".messages");
+            m_messages_pending = false;
+         }
+      }
+      m_sock->msg[0] = 0;
+      stat = m_sock->recv();
+      if (stat >= 0) {
+         if (mainWin->m_commDebug) Pmsg1(000, "got: %s\n", m_sock->msg);
+         if (m_at_prompt) {
+            m_console->display_text("\n");
+            m_at_prompt = false;
+            m_at_main_prompt = false;
+         }
+      }
+      switch (m_sock->msglen) {
+      case BNET_MSGS_PENDING :
+         if (m_notifier->isEnabled()) {
+            if (mainWin->m_commDebug) Pmsg0(000, "MSGS PENDING\n");
+            write_dir(".messages");
+            displayToPrompt();
+            m_messages_pending = false;
+         }
+         m_messages_pending = true;
+         continue;
+      case BNET_CMD_OK:
+         if (mainWin->m_commDebug) Pmsg0(000, "CMD OK\n");
+         m_at_prompt = false;
+         m_at_main_prompt = false;
+         mainWin->set_status(_("Command completed ..."));
+         continue;
+      case BNET_CMD_BEGIN:
+         if (mainWin->m_commDebug) Pmsg0(000, "CMD BEGIN\n");
+         m_at_prompt = false;
+         m_at_main_prompt = false;
+         mainWin->set_status(_("Processing command ..."));
+         continue;
+      case BNET_MAIN_PROMPT:
+         if (mainWin->m_commDebug) Pmsg0(000, "MAIN PROMPT\n");
+         m_at_prompt = true;
+         m_at_main_prompt = true;
+         mainWin->set_status(_("At main prompt waiting for input ..."));
+         QApplication::restoreOverrideCursor();
+         break;
+      case BNET_PROMPT:
+         if (mainWin->m_commDebug) Pmsg0(000, "PROMPT\n");
+         m_at_prompt = true;
+         m_at_main_prompt = false;
+         mainWin->set_status(_("At prompt waiting for input ..."));
+         QApplication::restoreOverrideCursor();
+         break;
+      case BNET_CMD_FAILED:
+         if (mainWin->m_commDebug) Pmsg0(000, "CMD FAILED\n");
+         mainWin->set_status(_("Command failed."));
+         QApplication::restoreOverrideCursor();
+         break;
+      /* We should not get this one */
+      case BNET_EOD:
+         if (mainWin->m_commDebug) Pmsg0(000, "EOD\n");
+         mainWin->set_status_ready();
+         QApplication::restoreOverrideCursor();
+         if (!m_api_set) {
+            break;
+         }
+         continue;
+      case BNET_START_SELECT:
+         if (mainWin->m_commDebug) Pmsg0(000, "START SELECT\n");
+         new selectDialog(m_console);
+         break;
+      case BNET_YESNO:
+         if (mainWin->m_commDebug) Pmsg0(000, "YESNO\n");
+         new yesnoPopUp(m_console);
+         break;
+      case BNET_RUN_CMD:
+         if (mainWin->m_commDebug) Pmsg0(000, "RUN CMD\n");
+         new runCmdPage();
+         break;
+      case BNET_ERROR_MSG:
+         if (mainWin->m_commDebug) Pmsg0(000, "ERROR MSG\n");
+         m_sock->recv();              /* get the message */
+         m_console->display_text(msg());
+         QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
+         break;
+      case BNET_WARNING_MSG:
+         if (mainWin->m_commDebug) Pmsg0(000, "WARNING MSG\n");
+         m_sock->recv();              /* get the message */
+         m_console->display_text(msg());
+         QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
+         break;
+      case BNET_INFO_MSG:
+         if (mainWin->m_commDebug) Pmsg0(000, "INFO MSG\n");
+         m_sock->recv();              /* get the message */
+         m_console->display_text(msg());
+         mainWin->set_status(msg());
+         break;
+      }
+      if (is_bnet_stop(m_sock)) {         /* error or term request */
+         if (mainWin->m_commDebug) Pmsg0(000, "BNET STOP\n");
+         stopTimer();
+         m_sock->close();
+         m_sock = NULL;
+         mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
+         QBrush redBrush(Qt::red);
+         QTreeWidgetItem *item = mainWin->getFromHash(this);
+         item->setForeground(0, redBrush);
+         m_notifier->setEnabled(false);
+         delete m_notifier;
+         m_notifier = NULL;
+         mainWin->set_status(_("Director disconnected."));
+         QApplication::restoreOverrideCursor();
+         stat = BNET_HARDEOF;
+      }
+      break;
+   } 
+   return stat;
+}
+
+/* Called by signal when the Director has output for us */
+void DirComm::read_dir(int /* fd */)
+{
+   if (mainWin->m_commDebug) Pmsg0(000, "read_dir\n");
+   while (read() >= 0) {
+      m_console->display_text(msg());
+   }
+}
+
+/*
+ * When the notifier is enabled, read_dir() will automatically be
+ * called by the Qt event loop when ever there is any output 
+ * from the Directory, and read_dir() will then display it on
+ * the console.
+ *
+ * When we are in a bat dialog, we want to control *all* output
+ * from the Directory, so we set notify to off.
+ *    m_console->notifiy(false);
+ */
+void DirComm::notify(bool enable) 
+{ 
+   m_notifier->setEnabled(enable);   
+}
+
+bool DirComm::is_connectedGui()
+{
+   if (is_connected()) {
+      return true;
+   } else {
+      QString message("Director ");
+      message += " is curerntly disconnected\n  Please reconnect!!";
+      QMessageBox::warning(this, tr("Bat"),
+         tr(message.toUtf8().data()), QMessageBox::Ok );
+      return false;
+   }
+}
+
+/*
+ * Call-back for reading a passphrase for an encrypted PEM file
+ * This function uses getpass(), 
+ *  which uses a static buffer and is NOT thread-safe.
+ */
+static int tls_pem_callback(char *buf, int size, const void *userdata)
+{
+   (void)size;
+   (void)userdata;
+#ifdef HAVE_TLS
+   const char *prompt = (const char *)userdata;
+# if defined(HAVE_WIN32)
+   sendit(prompt);
+   if (win32_cgets(buf, size) == NULL) {
+      buf[0] = 0;
+      return 0;
+   } else {
+      return strlen(buf);
+   }
+# else
+   char *passwd;
+
+   passwd = getpass(prompt);
+   bstrncpy(buf, passwd, size);
+   return strlen(buf);
+# endif
+#else
+   buf[0] = 0;
+   return 0;
+#endif
+}
diff --git a/bacula/src/qt-console/bcomm/dircomm.h b/bacula/src/qt-console/bcomm/dircomm.h
new file mode 100644 (file)
index 0000000..08488b9
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef _DIRCOMM_H_
+#define _DIRCOMM_H_
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   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
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ *   Version $Id$
+ * 
+ *   This is an attempt to move the higher level read/write type
+ *     functionality to the Director out of the Console class into
+ *     a Bacula Communications class.  This class builds on the 
+ *     BSOCK class.
+ * 
+ *
+ *   Kern Sibbald, May 2007
+ */
+
+#include "bat.h"
+#include "pages.h"
+
+class DIRRES;
+class BSOCK;
+class CONRES;
+
+class DirComm : public Pages
+{
+   Q_OBJECT
+
+public:
+   DirComm(Console *console);
+   ~DirComm();
+   void display_text(const char *buf);
+   void display_text(const QString buf);
+   void display_textf(const char *fmt, ...);
+   void display_html(const QString buf);
+   void update_cursor(void);
+   void write_dir(const char *buf);
+   bool dir_cmd(const char *cmd, QStringList &results);
+   bool dir_cmd(QString &cmd, QStringList &results);
+   bool sql_cmd(const char *cmd, QStringList &results);
+   bool sql_cmd(QString &cmd, QStringList &results);
+   bool authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons, 
+          char *buf, int buflen);
+   bool is_connected() { return m_sock != NULL; };
+   bool is_connectedGui();
+   char *msg();
+   void notify(bool enable);
+   void terminate();
+   void beginNewCommand();
+   void displayToPrompt();
+   void discardToPrompt();
+   void setDirectorTreeItem(QTreeWidgetItem *);
+   void setDirRes(DIRRES *dir);
+   void getDirResName(QString &);
+   void startTimer();
+   void stopTimer();
+
+public slots:
+   void connect_dir(DIRRES *dir, CONRES *cons);
+   void read_dir(int fd);
+   int read(void);
+   int write(const char *msg);
+   int write(QString msg);
+   void poll_messages(void);
+
+public:
+
+private:
+   DIRRES *m_dir;
+   BSOCK *m_sock;   
+   bool m_at_prompt;
+   bool m_at_main_prompt;
+   QSocketNotifier *m_notifier;
+   Console *m_console;
+   bool m_api_set;
+   bool m_messages_pending;
+   QTimer *m_timer;
+};
+
+#endif /* _DIRCOMM_H_ */
diff --git a/bacula/src/qt-console/bcomm/dircomm_auth.cpp b/bacula/src/qt-console/bcomm/dircomm_auth.cpp
new file mode 100644 (file)
index 0000000..8d47785
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2001-2007 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   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
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+
+/*
+ *
+ *   Bacula UA authentication. Provides authentication with
+ *     the Director.
+ *
+ *     Kern Sibbald, June MMI   adapted to bat, Jan MMVI
+ *
+ *     Version $Id$
+ *
+ */
+
+
+#include "bat.h"
+#include "dircomm.h"
+
+
+/* Commands sent to Director */
+static char hello[]    = "Hello %s calling\n";
+
+/* Response from Director */
+static char OKhello[]   = "1000 OK:";
+
+/* Forward referenced functions */
+
+/*
+ * Authenticate Director
+ */
+bool DirComm::authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons, 
+                char *errmsg, int errmsg_len) 
+{
+   BSOCK *dir = jcr->dir_bsock;
+   int tls_local_need = BNET_TLS_NONE;
+   int tls_remote_need = BNET_TLS_NONE;
+   int compatible = true;
+   char bashed_name[MAX_NAME_LENGTH];
+   char *password;
+   TLS_CONTEXT *tls_ctx = NULL;
+
+   errmsg[0] = 0;
+   /*
+    * Send my name to the Director then do authentication
+    */
+   if (cons) {
+      bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
+      bash_spaces(bashed_name);
+      password = cons->password;
+      /* TLS Requirement */
+      if (cons->tls_enable) {
+         if (cons->tls_require) {
+            tls_local_need = BNET_TLS_REQUIRED;
+         } else {
+            tls_local_need = BNET_TLS_OK;
+         }
+      }
+      tls_ctx = cons->tls_ctx;
+   } else {
+      bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
+      password = director->password;
+      /* TLS Requirement */
+      if (director->tls_enable) {
+         if (director->tls_require) {
+            tls_local_need = BNET_TLS_REQUIRED;
+         } else {
+            tls_local_need = BNET_TLS_OK;
+         }
+      }
+
+      tls_ctx = director->tls_ctx;
+   }
+   /* Timeout Hello after 15 secs */
+   dir->start_timer(15);
+   dir->fsend(hello, bashed_name);
+
+   /* respond to Dir challenge */
+   if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
+       /* Now challenge dir */
+       !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
+      bsnprintf(errmsg, errmsg_len, _("Director authorization problem at \"%s:%d\"\n"),
+         dir->host(), dir->port());
+      goto bail_out;
+   }
+
+   /* Verify that the remote host is willing to meet our TLS requirements */
+   if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
+      bsnprintf(errmsg, errmsg_len, _("Authorization problem:"
+             " Remote server at \"%s:%d\" did not advertise required TLS support.\n"),
+             dir->host(), dir->port());
+      goto bail_out;
+   }
+
+   /* Verify that we are willing to meet the remote host's requirements */
+   if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
+      bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\":"
+                     " Remote server requires TLS.\n"),
+                     dir->host(), dir->port());
+
+      goto bail_out;
+   }
+
+   /* Is TLS Enabled? */
+   if (have_tls) {
+      if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
+         /* Engage TLS! Full Speed Ahead! */
+         if (!bnet_tls_client(tls_ctx, dir, NULL)) {
+            bsnprintf(errmsg, errmsg_len, _("TLS negotiation failed with Director at \"%s:%d\"\n"),
+               dir->host(), dir->port());
+            goto bail_out;
+         }
+      }
+   }
+
+   Dmsg1(6, ">dird: %s", dir->msg);
+   if (dir->recv() <= 0) {
+      dir->stop_timer();
+      bsnprintf(errmsg, errmsg_len, _("Bad response to Hello command: ERR=%s\n"
+                      "The Director at \"%s:%d\" is probably not running.\n"),
+                    dir->bstrerror(), dir->host(), dir->port());
+      return false;
+   }
+
+   dir->stop_timer();
+   Dmsg1(10, "<dird: %s", dir->msg);
+   if (strncmp(dir->msg, OKhello, sizeof(OKhello)-1) != 0) {
+      bsnprintf(errmsg, errmsg_len, _("Director at \"%s:%d\" rejected Hello command\n"),
+         dir->host(), dir->port());
+      return false;
+   } else {
+      bsnprintf(errmsg, errmsg_len, "%s", dir->msg);
+   }
+   return true;
+
+bail_out:
+   dir->stop_timer();
+   bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\"\n"
+             "Most likely the passwords do not agree.\n"
+             "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n"
+             "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"), 
+             dir->host(), dir->port());
+   return false;
+}
index 9a81e26053b684aee768f8d1bb6621b6340a8e87..0c50f13579af3d8b7680168b53a1b461a53c253c 100644 (file)
@@ -34,7 +34,6 @@
  *
  */ 
 
-//#include <QAbstractEventDispatcher>
 #include "bat.h"
 #include "console.h"
 #include "restore.h"
index 6e97242aaa58d3c14d8ab0694c5d83eb41cb4a2d..9f311b8d7185b53f881d255ab26d602fc7414f31 100644 (file)
@@ -1,11 +1,16 @@
               Technical notes on version 2.3
 
 General:
+17Aug07
+kes  Add first (not yet tested) cut of bcomm to the qt-console directory.
+     This class is intended to allow us to open a second bsock to the
+     Director while in the restore subdialog.  
 16Aug07
 kes  Fix configure to create bat Makefile before creating dependencies.
 kes  Eliminate the egg files from the tray-monitor. Use gtk calls.
 kes  Add a tooltip to the tray monitor.
-dvl  Set the Director's PID file before dropping privs.
+dvl  Set the Director's PID file before dropping privs. This fixes
+     bug #923.
 15Aug07
 kes  Update AUTHORs file
 kes  Increase the default max concurrent jobs to 20 in FD and SD to