]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/hello.c
Big backport from Enterprise
[bacula/bacula] / bacula / src / filed / hello.c
index 87a31ba5e4e98233286e532827ef16c12d44a72f..ce379ff816f36af4c965f541c06f91175fe42707 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula(R) - The Network Backup Solution
 
-   Copyright (C) 2000-2016 Kern Sibbald
+   Copyright (C) 2000-2017 Kern Sibbald
 
    The original author of Bacula is Kern Sibbald, with contributions
    from many others, a complete list can be found in the file AUTHORS.
@@ -11,7 +11,7 @@
    Public License, v3.0 ("AGPLv3") and some additional permissions and
    terms pursuant to its AGPLv3 Section 7.
 
-   This notice must be preserved when any source code is 
+   This notice must be preserved when any source code is
    conveyed and/or propagated.
 
    Bacula(R) is a registered trademark of Kern Sibbald.
@@ -20,7 +20,6 @@
  * Authenticate Director who is attempting to connect.
  *
  *   Kern Sibbald, October 2000
- *
  */
 
 #include "bacula.h"
@@ -34,20 +33,21 @@ const int dbglvl = 50;
  *   None prior to 10Mar08
  *   1 10Mar08
  *   2 13Mar09 - added the ability to restore from multiple storages
- *   3 03Sep10 - added the restore object command
+ *   3 03Sep10 - added the restore object command for vss plugin 4.0
  *   4 25Nov10 - added bandwidth command 5.1
- *   5 24Nov11 - added new restore object command format (pluginname)
+ *   5 24Nov11 - added new restore object command format (pluginname) 6.0
  *   6 15Feb12 - added Component selection information list
  *   7 19Feb12 - added Expected files to restore
  *   8 22Mar13 - added restore options + version for SD
  *   9 06Aug13 - skipped
- *  10 01Jan14 - added SD Calls Client
+ *  10 01Jan14 - added SD Calls Client and api version to status command
  *  11 O4May14 - skipped
  *  12 22Jun14 - skipped
  * 213 04Feb15 - added snapshot protocol with the DIR
+ * 214 20Mar17 - added comm line compression
  */
 
-#define FD_VERSION 213 /* FD version */
+#define FD_VERSION 21 /* FD version */
 
 static char hello_sd[]  = "Hello Bacula SD: Start Job %s %d\n";
 static char hello_dir[] = "2000 OK Hello %d\n";
@@ -81,7 +81,8 @@ bool validate_dir_hello(JCR *jcr)
    dirname = check_pool_memory_size(dirname, dir->msglen);
 
    if (sscanf(dir->msg, "Hello Director %127s calling %d", dirname, &dir_version) != 2 &&
-       sscanf(dir->msg, "Hello Director %127s calling", dirname) != 1) {
+       sscanf(dir->msg, "Hello Director %127s calling", dirname) != 1 && 
+       sscanf(dir->msg, "Hello %127s calling %d", dirname, &dir_version) != 2 ) {
       char addr[64];
       char *who = dir->get_peer(addr, sizeof(addr)) ? dir->who() : addr;
       dir->msg[100] = 0;
@@ -91,6 +92,12 @@ bool validate_dir_hello(JCR *jcr)
             who, dir->msg);
       goto auth_fatal;
    }
+   if (dir_version >= 1 && me->comm_compression) {
+      dir->set_compress();
+   } else {
+      dir->clear_compress();
+      Dmsg0(050, "*** No FD compression to DIR\n");
+   }
    unbash_spaces(dirname);
    foreach_res(director, R_DIRECTOR) {
       if (strcmp(director->hdr.name, dirname) == 0)
@@ -168,6 +175,15 @@ void *handle_storage_connection(BSOCK *sd)
       return NULL;
    }
 
+   /* Turn on compression for newer FDs */
+   if (sd_version >= 1 && me->comm_compression) {
+      sd->set_compress();             /* set compression allowed */
+   } else {
+      sd->clear_compress();
+      Dmsg2(050, "******** No FD compression to SD. sd_ver=%d compres=%d\n",
+            sd_version, me->comm_compression);
+   }
+
    if (!jcr->max_bandwidth) {
       if (jcr->director->max_bandwidth_per_job) {
          jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
@@ -178,6 +194,8 @@ void *handle_storage_connection(BSOCK *sd)
    }
    sd->set_bwlimit(jcr->max_bandwidth);
 
+   Dmsg1(200, "sd_version=%ld\n", sd_version);
+
    pthread_cond_signal(&jcr->job_start_wait); /* wake waiting job */
    free_jcr(jcr);
    return NULL;
@@ -211,3 +229,141 @@ bool send_hello_sd(JCR *jcr, char *Job)
    Dmsg1(100, "Send to SD: %s\n", sd->msg);
    return rtn;
 }
+
+/* ======================== */
+
+bool send_fdcaps(JCR *jcr, BSOCK *sd) { return false; }
+bool recv_sdcaps(JCR *jcr) { return false; }
+
+/* Commands sent to Director */
+static char hello[]    = "Hello %s calling %d\n";
+
+/* Response from Director */
+static char DirOKhello[] = "1000 OK: %d";
+#define UA_VERSION 1
+
+BSOCK *connect_director(JCR *jcr, CONSRES *dir)
+{
+   int tls_local_need = BNET_TLS_NONE;
+   int tls_remote_need = BNET_TLS_NONE;
+   bool tls_authenticate;
+   int compatible = true;
+   int dir_version = 0;
+   char bashed_name[MAX_NAME_LENGTH];
+   char *password;
+   TLS_CONTEXT *tls_ctx = NULL;
+   BSOCK *UA_sock = NULL;
+   int heart_beat;
+
+   if (!dir) {
+      return 0;
+   }
+
+   Dmsg2(0, "Connecting to Director %s:%d\n", dir->address, dir->DIRport);
+
+   if (dir) {
+      heart_beat = dir->heartbeat_interval;
+   } else {
+      heart_beat = 0;
+   }
+   UA_sock = new_bsock();
+   if (!UA_sock->connect(NULL, 5, 15, heart_beat, "Director daemon", dir->address,
+                          NULL, dir->DIRport, 0)) {
+      free_bsock(UA_sock);
+      return NULL;
+   }
+
+   /*
+    * Send my name to the Director then do authentication
+    */
+   bstrncpy(bashed_name, dir->hdr.name, sizeof(bashed_name));
+   bash_spaces(bashed_name);
+   password = dir->password;
+   /* TLS Requirement */
+   if (dir->tls_enable) {
+      if (dir->tls_require) {
+         tls_local_need = BNET_TLS_REQUIRED;
+      } else {
+         tls_local_need = BNET_TLS_OK;
+      }
+   }
+   if (dir->tls_authenticate) {
+      tls_local_need = BNET_TLS_REQUIRED;
+   }
+   tls_authenticate = dir->tls_authenticate;
+   tls_ctx = dir->tls_ctx;
+
+   /* Timeout Hello after 15 secs */
+   btimer_t *tid = start_bsock_timer(UA_sock, 15);
+   UA_sock->fsend(hello, bashed_name, UA_VERSION);
+
+   if (!cram_md5_respond(UA_sock, password, &tls_remote_need, &compatible) ||
+       !cram_md5_challenge(UA_sock, password, tls_local_need, compatible)) {
+      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) {
+      Mmsg(jcr->errmsg, _("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) {
+      Mmsg(jcr->errmsg, _("Authorization problem:"
+             " Remote server requires TLS.\n"));
+      goto bail_out;
+   }
+
+   /* Is TLS Enabled? */
+   if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
+      /* Engage TLS! Full Speed Ahead! */
+      if (!bnet_tls_client(tls_ctx, UA_sock, NULL)) {
+         Mmsg(jcr->errmsg, _("TLS negotiation failed\n"));
+         goto bail_out;
+      }
+      if (tls_authenticate) {           /* Authenticate only? */
+         UA_sock->free_tls();           /* yes, shutdown tls */
+      }
+   }
+
+   /*
+    * It's possible that the TLS connection will
+    * be dropped here if an invalid client certificate was presented
+    */
+   Dmsg1(6, ">dird: %s", UA_sock->msg);
+   if (UA_sock->recv() <= 0) {
+      Mmsg(jcr->errmsg, _("Bad response to Hello command: ERR=%s\n"),
+                         UA_sock->bstrerror());
+      goto bail_out;
+   }
+
+   Dmsg1(10, "<dird: %s", UA_sock->msg);
+   if (strncmp(UA_sock->msg, DirOKhello, sizeof(DirOKhello)-3) == 0) {
+      sscanf(UA_sock->msg, DirOKhello, &dir_version);
+      Dmsg1(0, "%s\n", UA_sock->msg);
+
+   } else {
+      Mmsg(jcr->errmsg, _("Director rejected Hello command\n"));
+      goto bail_out;
+   }
+   /* Turn on compression for newer Directors */
+   if (dir_version >= 1 && (!dir || dir->comm_compression)) {
+      UA_sock->set_compress();
+   } else {
+      UA_sock->clear_compress();
+   }
+   stop_bsock_timer(tid);
+   return UA_sock;
+
+bail_out:
+   free_bsock(UA_sock);
+   stop_bsock_timer(tid);
+   Mmsg(jcr->errmsg,
+        ( _("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"
+            "For help, please see " MANUAL_AUTH_URL "\n")));
+   return NULL;
+}