]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Ensure that when labelling a tape with Slot=0 that InChanger
authorKern Sibbald <kern@sibbald.com>
Fri, 25 May 2007 17:24:50 +0000 (17:24 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 25 May 2007 17:24:50 +0000 (17:24 +0000)
     is not set.
kes  Use DISTINCT to make MySQL and PostgreSQL uar_list_temp query
     the same.
kes  Add StartTime to final uar_sel_jobid_temp query so that we can
     add DISTINCT (required by PostgreSQL).
kes  Implement BSOCK authenticate_director() method. Eventually will
     authenicate all daemons.
kes  Move several more functions into the BSOCK class.

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

12 files changed:
bacula/src/cats/sql_cmds.c
bacula/src/dird/autoprune.c
bacula/src/dird/ua_label.c
bacula/src/dird/ua_prune.c
bacula/src/lib/bsock.c
bacula/src/lib/bsock.h
bacula/src/lib/btimers.h
bacula/src/lib/cram-md5.c
bacula/src/lib/protos.h
bacula/src/lib/tls.c
bacula/src/version.h
bacula/technotes-2.1

index d45a500ee5564fbbeb1fdaf41fe7fbe0bb358ccf..19dd8b7adb996f0322bf2d0f2def84fa2ec027ba 100644 (file)
  *
  *   Version $Id$
  */
+/*
+ * Note, PostgreSQL imposes some constraints on using DISTINCT and GROUP BY
+ *  for example, the following is illegal in PostgreSQL:
+ *  SELECT DISTINCT JobId FROM temp ORDER BY StartTime ASC;
+ *  because all the ORDER BY expressions must appear in the SELECT list!
+ */
+
 
 #include "bacula.h"
 #include "cats.h"
@@ -398,23 +405,14 @@ const char *uar_inc =
    "AND FileSet.FileSet='%s' "
    "%s";
 
-#ifdef HAVE_POSTGRESQL
-/* Note, the PostgreSQL will have a much uglier looking
- * list since it cannot do GROUP BY of different values.
- */
 const char *uar_list_temp =
-   "SELECT JobId,Level,JobFiles,JobBytes,StartTime,VolumeName,StartFile"
+   "SELECT DISTINCT JobId,Level,JobFiles,JobBytes,StartTime,VolumeName"
    " FROM temp"
-   " ORDER BY StartTime,StartFile ASC";
-#else
-const char *uar_list_temp =
-   "SELECT JobId,Level,JobFiles,JobBytes,StartTime,VolumeName,StartFile"
-   " FROM temp"
-   " GROUP BY JobId ORDER BY StartTime,StartFile ASC";
-#endif
+   " ORDER BY StartTime ASC";
 
 
-const char *uar_sel_jobid_temp = "SELECT JobId FROM temp ORDER BY StartTime ASC";
+const char *uar_sel_jobid_temp = 
+   "SELECT DISTINCT JobId,StartTime FROM temp ORDER BY StartTime ASC";
 
 const char *uar_sel_all_temp1 = "SELECT * FROM temp1";
 
index b745aac8db8ed81209c3a9e09c45547e8ba164c2..0137734d348b71f84d1616fbe4c0fa189f1477ee 100644 (file)
@@ -1,16 +1,7 @@
-/*
- *
- *   Bacula Director -- Automatic Pruning
- *      Applies retention periods
- *
- *     Kern Sibbald, May MMII
- *
- *   Version $Id$
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-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 Director -- Automatic Pruning
+ *      Applies retention periods
+ *
+ *     Kern Sibbald, May MMII
+ *
+ *   Version $Id$
+ */
 
 #include "bacula.h"
 #include "dird.h"
@@ -57,7 +57,6 @@ void do_autoprune(JCR *jcr)
    }
 
    ua = new_ua_context(jcr);
-
    client = jcr->client;
 
    if (jcr->job->PruneJobs || jcr->client->AutoPrune) {
@@ -76,7 +75,6 @@ void do_autoprune(JCR *jcr)
    if (pruned) {
       Jmsg(jcr, M_INFO, 0, _("End auto prune.\n\n"));
    }
-
    free_ua_context(ua);
    return;
 }
index 4f8266371cd67919bffb166f91c023a99e5671c1..20ed2bd493e0f87efe1a418ad9599ea4f59b3c02 100644 (file)
@@ -249,7 +249,7 @@ void update_slots(UAContext *ua)
       db_make_inchanger_unique(ua->jcr, ua->db, &mr);
       db_unlock(ua->db);
       if (!vl->VolName) {
-         Dmsg1(000, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot);
+         Dmsg1(100, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot);
          ua->info_msg(_("No VolName for Slot=%d InChanger set to zero.\n"), vl->Slot);
          continue;
       }
@@ -417,13 +417,19 @@ checkName:
    i = find_arg_with_value(ua, "slot");
    if (i >= 0) {
       mr.Slot = atoi(ua->argv[i]);
-      mr.InChanger = 1;               /* assumed if we are labeling it */
+      if (mr.Slot < 0) {
+         mr.Slot = 0;
+      }
+      mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
    } else if (store.store->autochanger) {
       if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
          return 1;
       }
       mr.Slot = ua->pint32_val;
-      mr.InChanger = 1;               /* assumed if we are labeling it */
+      if (mr.Slot < 0) {
+         mr.Slot = 0;
+      }
+      mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
    }
    mr.StorageId = store.store->StorageId;
 
@@ -553,7 +559,7 @@ static void label_from_barcodes(UAContext *ua, int drive)
              ua->warning_msg(_("Media record for Slot %d Volume \"%s\" already exists.\n"),
                 vl->Slot, mr.VolumeName);
              mr.Slot = vl->Slot;
-             mr.InChanger = 1;
+             mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
              mr.StorageId = store->StorageId;
              if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
                 ua->error_msg(_("Error setting InChanger: ERR=%s"), db_strerror(ua->db));
@@ -562,7 +568,7 @@ static void label_from_barcodes(UAContext *ua, int drive)
           }
           media_record_exists = true;
       }
-      mr.InChanger = 1;
+      mr.InChanger = mr.Slot > 0;  /* if slot give assume in changer */
       mr.StorageId = store->StorageId;
       /*
        * Deal with creating cleaning tape here. Normal tapes created in
@@ -711,7 +717,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
    if (ok) {
       if (media_record_exists) {      /* we update it */
          mr->VolBytes = VolBytes;
-         mr->InChanger = 1;
+         mr->InChanger = mr->Slot > 0;  /* if slot give assume in changer */
          mr->StorageId = ua->jcr->wstore->StorageId;
          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
              ua->error_msg("%s", db_strerror(ua->db));
@@ -720,7 +726,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
       } else {                        /* create the media record */
          set_pool_dbr_defaults_in_media_dbr(mr, pr);
          mr->VolBytes = VolBytes;
-         mr->InChanger = 1;
+         mr->InChanger = mr->Slot > 0;  /* if slot give assume in changer */
          mr->StorageId = ua->jcr->wstore->StorageId;
          mr->Enabled = 1;
          if (db_create_media_record(ua->jcr, ua->db, mr)) {
index de27693dde46b61fca73a721d6f1672e5a0331b2..2c764d7679aba2d1be8d7474e82e52f22059c285 100644 (file)
@@ -297,7 +297,7 @@ int prune_jobs(UAContext *ua, CLIENT *client, int JobType)
    memset(&cr, 0, sizeof(cr));
    memset(&del, 0, sizeof(del));
 
-   bstrncpy(cr.Name, client->hdr.name, sizeof(cr.Name));
+   bstrncpy(cr.Name, client->name(), sizeof(cr.Name));
    if (!db_create_client_record(ua->jcr, ua->db, &cr)) {
       db_unlock(ua->db);
       return 0;
index 96e7f182f64dbee88920648ad896a747d7930db3..98a6f36db1fd71c697400716a7c3938a198ecaea 100644 (file)
@@ -830,3 +830,102 @@ void BSOCK::destroy()
    }
    free(this);
 }
+
+/* Commands sent to Director */
+static char hello[]    = "Hello %s calling\n";
+
+/* Response from Director */
+static char OKhello[]   = "1000 OK:";
+
+/*
+ * Authenticate Director
+ */
+bool BSOCK::authenticate_director(const char *name, const char *password,
+               TLS_CONTEXT *tls_ctx, char *msg, int msglen)
+{
+   int tls_local_need = BNET_TLS_NONE;
+   int tls_remote_need = BNET_TLS_NONE;
+   int compatible = true;
+   char bashed_name[MAX_NAME_LENGTH];
+   BSOCK *dir = this;        /* for readability */
+
+   msg[0] = 0;
+   /*
+    * Send my name to the Director then do authentication
+    */
+
+   /* Timeout Hello after 15 secs */
+   dir->start_timer(15);
+   dir->fsend(hello, bashed_name);
+
+   if (get_tls_enable(tls_ctx)) {
+      tls_local_need = get_tls_enable(tls_ctx) ? BNET_TLS_REQUIRED : BNET_TLS_OK;
+   }
+
+   /* 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(msg, msglen, _("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(msg, msglen, _("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(msg, msglen, _("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(msg, msglen, _("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(msg, msglen, _("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(msg, msglen, _("Director at \"%s:%d\" rejected Hello command\n"),
+         dir->host(), dir->port());
+      return false;
+   } else {
+      bsnprintf(msg, msglen, "%s", dir->msg);
+   }
+   return true;
+
+bail_out:
+   dir->stop_timer();
+   bsnprintf(msg, msglen, _("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 0cfe61203e0f858b4a14e11913a33bef781e96e9..704048ee20307359d875369662013232766abe5d 100644 (file)
  *   Version $Id$
  */
 
+#ifndef __BSOCK_H_
+#define __BSOCK_H_
+
+struct btimer_t;                      /* forward reference */
+class BSOCK;
+btimer_t *start_bsock_timer(BSOCK *bs, uint32_t wait);
+void stop_bsock_timer(btimer_t *wid);
+
 
 class BSOCK {
 private:
@@ -49,6 +57,7 @@ private:
    char *m_who;                       /* Name of daemon to which we are talking */
    char *m_host;                      /* Host name/IP */
    int m_port;                        /* desired port */
+   btimer_t *m_tid;                   /* timer id */
 
    void fin_init(JCR * jcr, int sockfd, const char *who, const char *host, int port,
                struct sockaddr *lclient_addr);
@@ -100,6 +109,8 @@ public:
    void restore_blocking(int flags);
    int wait_data(int sec);
    int wait_data_intr(int sec);
+   bool authenticate_director(const char *name, const char *password,
+                  TLS_CONTEXT *tls_ctx, char *msg, int msglen);
 
    /* Inline functions */
    void set_jcr(JCR *jcr) { m_jcr = jcr; };
@@ -114,6 +125,8 @@ public:
    bool is_terminated() { return m_terminated; };
    bool is_timed_out() { return m_timed_out; };
    void set_terminated() { m_terminated = true; };
+   void start_timer(int sec) { m_tid = start_bsock_timer(this, sec); };
+   void stop_timer() { stop_bsock_timer(m_tid); };
 };
 
 /* 
@@ -175,3 +188,5 @@ int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes);
 int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes);
 
 BSOCK *new_bsock();
+
+#endif /* __BSOCK_H_ */
index 51329d495b513511b9debd28c47008df121474dc..a5ad64968335b9c89bee2292de8997c7c1834457 100644 (file)
@@ -1,13 +1,7 @@
-/*
- * Process and thread timer routines, built on top of watchdogs.
- *
- *    Nic Bellamy <nic@bellamy.co.nz>, October 2003.
- *
-*/
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2003-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2003-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.
 */
+/*
+ * Process and thread timer routines, built on top of watchdogs.
+ *
+ *    Nic Bellamy <nic@bellamy.co.nz>, October 2003.
+ *
+*/
+
+#ifndef __BTIMERS_H_
+#define __BTIMERS_H_
 
-typedef struct s_btimer_t {
+struct btimer_t {
    watchdog_t *wd;                    /* Parent watchdog */
    int type;
    bool killed;
    pid_t pid;                         /* process id if TYPE_CHILD */
    pthread_t tid;                     /* thread id if TYPE_PTHREAD */
    BSOCK *bsock;                      /* Pointer to BSOCK */
-} btimer_t;
+};
 
-/* EOF */
+#endif /* __BTIMERS_H_ */
index 83c43059e97e2b9ee798cafdf187d59928d99e5a..e8595a4dbacd008b65e167755c25874515b51696 100644 (file)
@@ -46,7 +46,7 @@
  *   Returns: false if authentication failed
  *            true if OK
  */
-bool cram_md5_challenge(BSOCK *bs, char *password, int tls_local_need, int compatible)
+bool cram_md5_challenge(BSOCK *bs, const char *password, int tls_local_need, int compatible)
 {
    struct timeval t1;
    struct timeval t2;
@@ -113,7 +113,7 @@ bool cram_md5_challenge(BSOCK *bs, char *password, int tls_local_need, int compa
 }
 
 /* Respond to challenge from other end */
-bool cram_md5_respond(BSOCK *bs, char *password, int *tls_remote_need, int *compatible)
+bool cram_md5_respond(BSOCK *bs, const char *password, int *tls_remote_need, int *compatible)
 {
    char chal[MAXSTRING];
    uint8_t hmac[20];
index cbfd34ba4bd9b0b5337a9fe42da5de28be15e708..930151e28b7042565c57348cae2ee1588a451b7f 100644 (file)
@@ -123,8 +123,8 @@ int              close_wpipe(BPIPE *bpipe);
 int              close_bpipe(BPIPE *bpipe);
 
 /* cram-md5.c */
-bool cram_md5_respond(BSOCK *bs, char *password, int *tls_remote_need, int *compatible);
-bool cram_md5_challenge(BSOCK *bs, char *password, int tls_local_need, int compatible);
+bool cram_md5_respond(BSOCK *bs, const char *password, int *tls_remote_need, int *compatible);
+bool cram_md5_challenge(BSOCK *bs, const char *password, int tls_local_need, int compatible);
 void hmac_md5(uint8_t* text, int text_len, uint8_t* key, int key_len, uint8_t *hmac);
 
 /* crc32.c */
@@ -297,6 +297,8 @@ void             tls_bsock_shutdown      (BSOCK *bsock);
 int              tls_bsock_writen        (BSOCK *bsock, char *ptr, int32_t nbytes);
 int              tls_bsock_readn         (BSOCK *bsock, char *ptr, int32_t nbytes);
 #endif /* HAVE_TLS */
+bool             get_tls_require         (TLS_CONTEXT *ctx);
+bool             get_tls_enable          (TLS_CONTEXT *ctx);
 
 
 /* util.c */
index 807a6f4dc0680656d6ff6d18483c2b7c976af5bb..85aeb1dbcd4ae5c34f48ab7f279fa4ff85345aef 100644 (file)
@@ -102,7 +102,7 @@ static int openssl_verify_peer(int ok, X509_STORE_CTX *store)
 /* Dispatch user PEM encryption callbacks */
 static int tls_pem_callback_dispatch (char *buf, int size, int rwflag, void *userdata)
 {
-   TLS_CONTEXT *ctx = (TLS_CONTEXT *) userdata;
+   TLS_CONTEXT *ctx = (TLS_CONTEXT *)userdata;
    return (ctx->pem_callback(buf, size, ctx->pem_userdata));
 }
 
@@ -231,6 +231,17 @@ void free_tls_context(TLS_CONTEXT *ctx)
    free(ctx);
 }
 
+bool get_tls_require(TLS_CONTEXT *ctx) 
+{
+   return ctx->tls_require;
+}
+
+bool get_tls_enable(TLS_CONTEXT *ctx) 
+{
+   return ctx->tls_enable;
+}
+
+
 /*
  * Verifies a list of common names against the certificate
  * commonName attribute.
@@ -368,7 +379,6 @@ bool tls_postconnect_verify_host(TLS_CONNECTION *tls, const char *host)
       }
    }
 
-
 success:
    X509_free(cert);
 
@@ -412,7 +422,7 @@ TLS_CONNECTION *new_tls_connection(TLS_CONTEXT *ctx, int fd)
    /* Non-blocking partial writes */
    SSL_set_mode(tls->openssl, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
 
-   return (tls);
+   return tls;
 
 err:
    /* Clean up */
@@ -704,5 +714,14 @@ void free_tls_connection(TLS_CONNECTION *tls)
       free(tls);
    }
 }
+bool get_tls_require(TLS_CONTEXT *ctx) 
+{
+   return false;
+}
+
+bool get_tls_enable(TLS_CONTEXT *ctx) 
+{
+   return false;
+}
 
 #endif /* HAVE_TLS */
index 27827ae4fcc63290cc36a897b81eebd9481531c5..1dd6eb5072140f472a3bb4389f3f98233532dfd6 100644 (file)
@@ -4,8 +4,8 @@
 
 #undef  VERSION
 #define VERSION "2.1.11"
-#define BDATE   "24 May 2007"
-#define LSMDATE "24May07"
+#define BDATE   "25 May 2007"
+#define LSMDATE "25May07"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2007"       /* year for copyright messages in progs */
index eeb0865b1954121202a18545a46be32bfacb0a39..f140f418a4f57d176abd8088430018aaedf2eb48 100644 (file)
@@ -1,6 +1,16 @@
               Technical notes on version 2.1
 
 General:
+25May07
+kes  Ensure that when labelling a tape with Slot=0 that InChanger
+     is not set.
+kes  Use DISTINCT to make MySQL and PostgreSQL uar_list_temp query        
+     the same.
+kes  Add StartTime to final uar_sel_jobid_temp query so that we can
+     add DISTINCT (required by PostgreSQL).
+kes  Implement BSOCK authenticate_director() method. Eventually will
+     authenicate all daemons.
+kes  Move several more functions into the BSOCK class.
 24May07
 kes  Add code to tell the OS that we no longer need a cached
      file that we were reading. In findlib/bfile.c.  Also,