*
* 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"
"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";
-/*
- *
- * 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"
}
ua = new_ua_context(jcr);
-
client = jcr->client;
if (jcr->job->PruneJobs || jcr->client->AutoPrune) {
if (pruned) {
Jmsg(jcr, M_INFO, 0, _("End auto prune.\n\n"));
}
-
free_ua_context(ua);
return;
}
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;
}
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;
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));
}
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
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));
} 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)) {
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;
}
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;
+}
* 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:
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);
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; };
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); };
};
/*
int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes);
BSOCK *new_bsock();
+
+#endif /* __BSOCK_H_ */
-/*
- * 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_ */
* 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;
}
/* 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];
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 */
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 */
/* 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));
}
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.
}
}
-
success:
X509_free(cert);
/* 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 */
free(tls);
}
}
+bool get_tls_require(TLS_CONTEXT *ctx)
+{
+ return false;
+}
+
+bool get_tls_enable(TLS_CONTEXT *ctx)
+{
+ return false;
+}
#endif /* HAVE_TLS */
#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 */
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,