/*
Bacula® - The Network Backup Solution
- Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2007-2008 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.
This program is Free Software; you can redistribute it and/or
modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation plus additions
- that are listed in the file LICENSE.
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
destroy();
}
+void BSOCK::free_tls()
+{
+ free_tls_connection(this->tls);
+ this->tls = NULL;
+}
+
/*
* Try to connect to host for max_retry_time at retry_time intervals.
* Note, you must have called the constructor prior to calling
/* Try to trap out of OS call when time expires */
if (max_retry_time) {
- tid = start_thread_timer(pthread_self(), (uint32_t)max_retry_time);
+ tid = start_thread_timer(jcr, pthread_self(), (uint32_t)max_retry_time);
}
for (i = 0; !open(jcr, name, host, service, port, heart_beat, &fatal);
/* send data packet */
timer_start = watchdog_time; /* start timer */
- m_timed_out = 0;
+ clear_timed_out();
/* Full I/O done in one write */
rc = write_nbytes(this, (char *)hdr, pktsiz);
timer_start = 0; /* clear timer */
read_seqno++; /* bump sequence number */
timer_start = watchdog_time; /* set start wait time */
- m_timed_out = 0;
+ clear_timed_out();
/* get data size -- in int32_t */
if ((nbytes = read_nbytes(this, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
timer_start = 0; /* clear timer */
}
timer_start = watchdog_time; /* set start wait time */
- m_timed_out = 0;
+ clear_timed_out();
/* now read the actual data */
if ((nbytes = read_nbytes(this, msg, pktsiz)) <= 0) {
timer_start = 0; /* clear timer */
* Note, this routine closes and destroys all the sockets
* that are open including the duped ones.
*/
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
void BSOCK::close()
{
BSOCK *bsock = this;
bsock->tls = NULL;
}
if (bsock->is_timed_out()) {
- shutdown(bsock->m_fd, 2); /* discard any pending I/O */
+ shutdown(bsock->m_fd, SHUT_RDWR); /* discard any pending I/O */
}
socketClose(bsock->m_fd); /* normal close */
}
}
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;
+}