From 51694687ab0c72a2000b06aa450ab4e650214395 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Fri, 25 May 2007 17:24:50 +0000 Subject: [PATCH] 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. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@4905 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/cats/sql_cmds.c | 24 +++++---- bacula/src/dird/autoprune.c | 22 ++++----- bacula/src/dird/ua_label.c | 20 +++++--- bacula/src/dird/ua_prune.c | 2 +- bacula/src/lib/bsock.c | 99 +++++++++++++++++++++++++++++++++++++ bacula/src/lib/bsock.h | 15 ++++++ bacula/src/lib/btimers.h | 23 +++++---- bacula/src/lib/cram-md5.c | 4 +- bacula/src/lib/protos.h | 6 ++- bacula/src/lib/tls.c | 25 ++++++++-- bacula/src/version.h | 4 +- bacula/technotes-2.1 | 10 ++++ 12 files changed, 202 insertions(+), 52 deletions(-) diff --git a/bacula/src/cats/sql_cmds.c b/bacula/src/cats/sql_cmds.c index d45a500ee5..19dd8b7adb 100644 --- a/bacula/src/cats/sql_cmds.c +++ b/bacula/src/cats/sql_cmds.c @@ -33,6 +33,13 @@ * * 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"; diff --git a/bacula/src/dird/autoprune.c b/bacula/src/dird/autoprune.c index b745aac8db..0137734d34 100644 --- a/bacula/src/dird/autoprune.c +++ b/bacula/src/dird/autoprune.c @@ -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. @@ -34,6 +25,15 @@ (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; } diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 4f8266371c..20ed2bd493 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -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)) { diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c index de27693dde..2c764d7679 100644 --- a/bacula/src/dird/ua_prune.c +++ b/bacula/src/dird/ua_prune.c @@ -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; diff --git a/bacula/src/lib/bsock.c b/bacula/src/lib/bsock.c index 96e7f182f6..98a6f36db1 100644 --- a/bacula/src/lib/bsock.c +++ b/bacula/src/lib/bsock.c @@ -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, "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; +} diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h index 0cfe61203e..704048ee20 100644 --- a/bacula/src/lib/bsock.h +++ b/bacula/src/lib/bsock.h @@ -41,6 +41,14 @@ * 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_ */ diff --git a/bacula/src/lib/btimers.h b/bacula/src/lib/btimers.h index 51329d495b..a5ad649683 100644 --- a/bacula/src/lib/btimers.h +++ b/bacula/src/lib/btimers.h @@ -1,13 +1,7 @@ -/* - * Process and thread timer routines, built on top of watchdogs. - * - * Nic Bellamy , 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. @@ -31,14 +25,23 @@ (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 , 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_ */ diff --git a/bacula/src/lib/cram-md5.c b/bacula/src/lib/cram-md5.c index 83c43059e9..e8595a4dba 100644 --- a/bacula/src/lib/cram-md5.c +++ b/bacula/src/lib/cram-md5.c @@ -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]; diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index cbfd34ba4b..930151e28b 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -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 */ diff --git a/bacula/src/lib/tls.c b/bacula/src/lib/tls.c index 807a6f4dc0..85aeb1dbcd 100644 --- a/bacula/src/lib/tls.c +++ b/bacula/src/lib/tls.c @@ -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 */ diff --git a/bacula/src/version.h b/bacula/src/version.h index 27827ae4fc..1dd6eb5072 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -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 */ diff --git a/bacula/technotes-2.1 b/bacula/technotes-2.1 index eeb0865b19..f140f418a4 100644 --- a/bacula/technotes-2.1 +++ b/bacula/technotes-2.1 @@ -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, -- 2.39.5