]> git.sur5r.net Git - bacula/bacula/commitdiff
Begin adding TLS support to bat.
authorKern Sibbald <kern@sibbald.com>
Mon, 21 May 2007 10:54:24 +0000 (10:54 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 21 May 2007 10:54:24 +0000 (10:54 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@4864 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/console/authenticate.c
bacula/src/qt-console/console/authenticate.cpp
bacula/src/qt-console/console/console.cpp
bacula/src/version.h
bacula/src/wx-console/authenticate.c
bacula/technotes-2.1

index 2cb65cbd62c245390bc15ce268f12e1da22b219f..f99331172ca034263dafee4d8b2ac45ae4088c10 100644 (file)
@@ -102,7 +102,7 @@ int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
    
    /* Timeout Hello after 5 mins */
    btimer_t *tid = start_bsock_timer(dir, 60 * 5);
-   bnet_fsend(dir, hello, bashed_name);
+   dir->fsend(hello, bashed_name);
 
    if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
        !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
@@ -139,9 +139,9 @@ int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
     * be dropped here if an invalid client certificate was presented
     */
    Dmsg1(6, ">dird: %s", dir->msg);
-   if (bnet_recv(dir) <= 0) {
+   if (dir->recv() <= 0) {
       senditf(_("Bad response to Hello command: ERR=%s\n"),
-         bnet_strerror(dir));
+         dir->bstrerror());
       goto bail_out;
    }
 
index dd5b3533a6af3dcb999f716b919835fa076ae1cf..7ef47a1431a04c8c5e599ccf73834f976d21a3e2 100644 (file)
@@ -60,6 +60,7 @@ bool Console::authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
    int compatible = true;
    char bashed_name[MAX_NAME_LENGTH];
    char *password;
+   TLS_CONTEXT *tls_ctx = NULL;
 
    /*
     * Send my name to the Director then do authentication
@@ -68,36 +69,79 @@ bool Console::authenticate_director(JCR *jcr, DIRRES *director, CONRES *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 5 mins */
-   btimer_t *tid = start_bsock_timer(dir, 60 * 5);
-   bnet_fsend(dir, hello, bashed_name);
+   /* Timeout Hello after 30 secs */
+   btimer_t *tid = start_bsock_timer(dir, 30);
+   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)) {
-      stop_bsock_timer(tid);
       printf(_("%s: Director authorization problem.\n"), my_name);
       display_text(_("Director authorization problem.\n"));    
-      display_text(_(
-       "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
-      return false;
+      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) {
+      display_text(_("Authorization problem:"
+             " Remote server did not advertise required TLS support.\n"));
+      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) {
+      display_text(_("Authorization problem:"
+                     " Remote server requires TLS.\n"));
+      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)) {
+            display_text(_("TLS negotiation failed\n"));
+            goto bail_out;
+         }
+      }
    }
 
    Dmsg1(6, ">dird: %s", dir->msg);
-   if (bnet_recv(dir) <= 0) {
+   if (dir->recv() <= 0) {
       stop_bsock_timer(tid);
       display_textf(_("Bad response to Hello command: ERR=%s\n"),
-         bnet_strerror(dir));
+         dir->bstrerror());
       printf(_("%s: Bad response to Hello command: ERR=%s\n"),
-         my_name, bnet_strerror(dir));
+         my_name, dir->bstrerror());
       display_text(_("The Director is probably not running.\n"));
       return false;
    }
+
   stop_bsock_timer(tid);
    Dmsg1(10, "<dird: %s", dir->msg);
    if (strncmp(dir->msg, OKhello, sizeof(OKhello)-1) != 0) {
@@ -107,4 +151,12 @@ bool Console::authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
       display_text(dir->msg);
    }
    return true;
+
+bail_out:
+   stop_bsock_timer(tid);
+   display_text(_("Director authorization problem.\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"));
+   return false;
 }
index f1bec8d87376d613db1ad40ca149794b6ab105a6..168ef978235bc2c7c5603dd78afb53e6db2df6c3 100644 (file)
@@ -41,6 +41,9 @@
 #include "select.h"
 #include "run/run.h"
 
+static int tls_pem_callback(char *buf, int size, const void *userdata);
+
+
 Console::Console(QStackedWidget *parent)
 {
    QFont font;
@@ -119,6 +122,48 @@ void Console::connect()
    CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
    UnlockRes();
 
+   char buf[1024];
+   /* Initialize Console TLS context */
+   if (cons && (cons->tls_enable || cons->tls_require)) {
+      /* Generate passphrase prompt */
+      bsnprintf(buf, sizeof(buf), "Passphrase for Console \"%s\" TLS private key: ", cons->hdr.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) {
+         display_textf(_("Failed to initialize TLS context for Console \"%s\".\n"),
+            m_dir->hdr.name);
+         return;
+      }
+   }
+
+   /* Initialize Director TLS context */
+   if (m_dir->tls_enable || m_dir->tls_require) {
+      /* Generate passphrase prompt */
+      bsnprintf(buf, sizeof(buf), "Passphrase for Director \"%s\" TLS private key: ", 
+                m_dir->hdr.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) {
+         display_textf(_("Failed to initialize TLS context for Director \"%s\".\n"),
+            m_dir->hdr.name);
+         mainWin->set_status("Connection failed");
+         return;
+      }
+   }
+
    if (m_dir->heartbeat_interval) {
       heart_beat = m_dir->heartbeat_interval;
    } else if (cons) {
@@ -727,3 +772,33 @@ bool Console::preventInUseConnect()
       return true;
    }
 }
+
+/*
+ * 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)
+{
+#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
+}
index 6fafdc1755d2a0db52aa10681fb04a508b18ab61..3dd249fe894208fd63f7ccaaaf47b1430a03dd9c 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "2.1.11"
-#define BDATE   "20 May 2007"
-#define LSMDATE "20May07"
+#define BDATE   "21 May 2007"
+#define LSMDATE "21May07"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2007"       /* year for copyright messages in progs */
index 5baa3ff1e171edc0d8473489b4f207736aa9218e..ca6d0bd7e09980e170ddc435adc576a0df390d0a 100644 (file)
@@ -1,19 +1,7 @@
-/*
- *
- *   Bacula UA authentication. Provides authentication with
- *     the Director.
- *
- *     Kern Sibbald, June MMI
- *
- *    This routine runs as a thread and must be thread reentrant.
- *
- *  Basic tasks done here:
- *
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
+   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.
    (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
+ *
+ *    This routine runs as a thread and must be thread reentrant.
+ *
+ *  Basic tasks done here:
+ *
+ */
 
 /* _("...") macro returns a wxChar*, so if we need a char*, we need to convert it with:
  * wxString(_("...")).mb_str(*wxConvCurrent) */
index a352b9161aadfce8cf5a1fc29095854e6037ab80..2fe5018630f2085914af58ef5ab9065b9c16ed8a 100644 (file)
@@ -2,6 +2,7 @@
 
 General:
 21May07
+kes  Begin adding TLS support to bat.
 kes  Apply UTF-8/16 patch from Yves Orton <demerphq@gmail.com> to
      clean up lex.c and make it more readable.
 20May07