Navigation Menu

Skip to content

Commit

Permalink
console-dir: allow bconsole < Bareos-18.2 to connect to director
Browse files Browse the repository at this point in the history
  • Loading branch information
franku committed Jan 7, 2019
1 parent 069fb36 commit 6e72314
Show file tree
Hide file tree
Showing 9 changed files with 420 additions and 146 deletions.
378 changes: 276 additions & 102 deletions core/src/dird/authenticate_console.cc

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions core/src/include/version_numbers.h
@@ -0,0 +1,35 @@
/*
BAREOS® - Backup Archiving REcovery Open Sourced
Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
Copyright (C) 2011-2012 Planets Communications B.V.
Copyright (C) 2013-2016 Bareos GmbH & Co. KG
This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/

#ifndef BAREOS_INCLUDE_RELEASE_NUMBERS_H_
#define BAREOS_INCLUDE_RELEASE_NUMBERS_H_

#include "include/bc_types.h"

enum class BareosVersionNumber : uint32_t
{
kRelease_18_2 = static_cast<uint32_t>(1802),
kUndefined = static_cast<uint32_t>(1)
};

#endif /* BAREOS_INCLUDE_RELEASE_NUMBERS_H_ */
22 changes: 12 additions & 10 deletions core/src/lib/bsock.cc
Expand Up @@ -55,6 +55,7 @@ BareosSocket::BareosSocket()
, sleep_time_after_authentication_error(5)
, client_addr{0}
, peer_addr{0}
, connected_daemon_version_(BareosVersionNumber::kUndefined)

/* protected: */
, jcr_(nullptr)
Expand Down Expand Up @@ -100,6 +101,7 @@ BareosSocket::BareosSocket(const BareosSocket &other)
client_addr = other.client_addr;
peer_addr = other.peer_addr;
tls_conn = other.tls_conn;
connected_daemon_version_ = other.connected_daemon_version_;

/* protected: */
jcr_ = other.jcr_;
Expand Down Expand Up @@ -318,10 +320,6 @@ void BareosSocket::SetKillable(bool killable)
if (jcr_) { jcr_->SetKillable(killable); }
}

/** Commands sent to Director */
static char hello[] = "Hello %s calling\n";


bool BareosSocket::ConsoleAuthenticateWithDirector(JobControlRecord *jcr,
const char *identity,
s_password &password,
Expand All @@ -336,7 +334,7 @@ bool BareosSocket::ConsoleAuthenticateWithDirector(JobControlRecord *jcr,
BashSpaces(bashed_name);

dir->StartTimer(60 * 5); /* 5 minutes */
dir->fsend(hello, bashed_name);
dir->fsend("Hello %s calling version %s\n", bashed_name, VERSION);

if (!AuthenticateOutboundConnection(jcr, "Director", identity, password, tls_resource)) {
Dmsg0(100, "Authenticate outbound connection failed\n");
Expand Down Expand Up @@ -588,8 +586,9 @@ bool BareosSocket::AuthenticateInboundConnection(JobControlRecord *jcr,
}

bool BareosSocket::EvaluateCleartextBareosHello(bool &cleartext_hello,
std::string &client_name,
std::string &r_code_str) const
std::string &client_name_out,
std::string &r_code_str_out,
BareosVersionNumber &version_out) const
{
char buffer[256] {0};

Expand All @@ -605,9 +604,12 @@ bool BareosSocket::EvaluateCleartextBareosHello(bool &cleartext_hello,
if (cleartext_hello) {
std::string name;
std::string code;
if (GetNameAndResourceTypeFromHello(received, name, code)) {
client_name = name;
r_code_str = code;
BareosVersionNumber version = BareosVersionNumber::kUndefined;
if (GetNameAndResourceTypeAndVersionFromHello(received, name, code, version)) {
Dmsg3(200, "Identified from cleartext handshake: %s-%s recognized version: %d\n", name.c_str(), code.c_str(), version);
client_name_out = name;
r_code_str_out = code;
version_out = version;
success = true;
}
} else { /* not cleartext hello */
Expand Down
7 changes: 5 additions & 2 deletions core/src/lib/bsock.h
Expand Up @@ -43,6 +43,7 @@
#include <functional>
#include "lib/tls.h"
#include "lib/s_password.h"
#include "include/version_numbers.h"

struct btimer_t; /* forward reference */
class BareosSocket;
Expand Down Expand Up @@ -80,6 +81,7 @@ class BareosSocket : public SmartAlloc {
bool TlsEstablished() const { return tls_established_; }
std::shared_ptr<Tls> tls_conn; /* Associated tls connection */
std::unique_ptr<Tls> tls_conn_init; /* during initialization */
BareosVersionNumber connected_daemon_version_;

protected:
JobControlRecord *jcr_; /* JobControlRecord or NULL for error msgs */
Expand Down Expand Up @@ -187,8 +189,9 @@ class BareosSocket : public SmartAlloc {
void SetSourceAddress(dlist *src_addr_list);
void ControlBwlimit(int bytes); /* in bsock.c */
bool EvaluateCleartextBareosHello(bool &cleartext,
std::string &client_name,
std::string &r_code_str) const;
std::string &client_name_out,
std::string &r_code_str_out,
BareosVersionNumber &version_out) const;
void OutputCipherMessageString(std::function<void(const char *)>);
void GetCipherMessageString(std::string &str) const;
bool ReceiveAndEvaluateResponseMessage(uint32_t &id_out, BStringList &args_out);
Expand Down
13 changes: 10 additions & 3 deletions core/src/lib/try_tls_handshake_as_a_server.cc
Expand Up @@ -36,18 +36,22 @@ static ConnectionHandshakeMode GetHandshakeMode(BareosSocket *bs,
bool cleartext_hello;
std::string client_name;
std::string r_code_str;
BareosVersionNumber version = BareosVersionNumber::kUndefined;

if (!bs->EvaluateCleartextBareosHello(cleartext_hello,
client_name,
r_code_str)) {
r_code_str,
version)) {
Dmsg0(100, "Error occured when trying to peek cleartext hello\n");
return ConnectionHandshakeMode::CloseConnection;
}

bs->connected_daemon_version_ = static_cast<BareosVersionNumber>(version);

if (cleartext_hello) {
TlsPolicy tls_policy;
if (!config->GetConfiguredTlsPolicyFromCleartextHello(r_code_str, client_name, tls_policy)) {
Dmsg0(100, "Could not read out cleartext configuration\n");
Dmsg0(200, "Could not read out cleartext configuration\n");
return ConnectionHandshakeMode::CloseConnection;
}
if (r_code_str == std::string("R_CLIENT")) {
Expand All @@ -56,10 +60,13 @@ static ConnectionHandshakeMode GetHandshakeMode(BareosSocket *bs,
} else { /* kBnetTlsNone or kBnetTlsEnabled */
return ConnectionHandshakeMode::PerformCleartextHandshake;
}
} else { /* not R_CLIENT */
} else if (r_code_str == std::string("R_CONSOLE") && version < BareosVersionNumber::kRelease_18_2) {
return ConnectionHandshakeMode::PerformCleartextHandshake;
} else {
if (tls_policy == kBnetTlsNone) {
return ConnectionHandshakeMode::PerformCleartextHandshake;
} else {
Dmsg1(200, "Connection to %s will be denied due to configuration mismatch\n", client_name.c_str());
return ConnectionHandshakeMode::CloseConnection;
}
}
Expand Down
58 changes: 44 additions & 14 deletions core/src/lib/util.cc
Expand Up @@ -187,25 +187,27 @@ struct HelloInformation {
std::string hello_string;
std::string resource_type_string;
uint32_t position_of_name;
int32_t position_of_version;
};

using SizeTypeOfHelloList = std::vector<std::string>::size_type;

static std::list<HelloInformation> hello_list {
/* this order is important */
{ "Hello Storage calling Start Job", "R_JOB", 5 },
{ "Hello Start Storage Job", "R_JOB", 4 },
{ "Hello Start Job", "R_JOB", 3 },
{ "Hello Director", "R_DIRECTOR", 2 },
{ "Hello Storage", "R_STORAGE", 2 },
{ "Hello Client", "R_CLIENT", 2 },
{ "Hello", "R_CONSOLE", 1 }
{ "Hello Storage calling Start Job", "R_JOB", 5, -1 },
{ "Hello Start Storage Job", "R_JOB", 4, -1 },
{ "Hello Start Job", "R_JOB", 3, -1 },
{ "Hello Director", "R_DIRECTOR", 2, -1 },
{ "Hello Storage", "R_STORAGE", 2, -1 },
{ "Hello Client", "R_CLIENT", 2, -1 },
{ "Hello", "R_CONSOLE", 1, 4 } /* "Hello %s calling version %s" */
};

bool GetNameAndResourceTypeFromHello(const std::string &input,
bool GetNameAndResourceTypeAndVersionFromHello(const std::string &input,
std::string &name,
std::string &r_type_str)
std::string &r_type_str,
BareosVersionNumber &bareos_version)
{
bool ok = false;

std::list<HelloInformation>::const_iterator hello = hello_list.cbegin();

bool found = false;
Expand All @@ -226,14 +228,42 @@ bool GetNameAndResourceTypeFromHello(const std::string &input,
return false;
}

BStringList args(input, ' '); /* split at blanks */
BStringList arguments_of_hello_string(input, ' '); /* split at blanks */

if (args.size() >= hello->position_of_name) {
name = args[hello->position_of_name];
bool ok = false;
if (arguments_of_hello_string.size() > hello->position_of_name) {
name = arguments_of_hello_string[hello->position_of_name];
std::replace(name.begin(),name.end(), (char)0x1, ' ');
r_type_str = hello->resource_type_string;
ok = true;
} else {
Dmsg0(100, "Failed to retrieve the name from hello message\n");
}

if (ok) {
bareos_version = BareosVersionNumber::kUndefined;
if (hello->position_of_version >= 0) {
if (arguments_of_hello_string.size() > static_cast<SizeTypeOfHelloList>(hello->position_of_version)) {
std::string version_str = arguments_of_hello_string[hello->position_of_version];
if (!version_str.empty()) {
ok = false;
BStringList splittet_version (version_str, '.');
if (splittet_version.size() > 1) {
uint32_t v;
try {
v = std::stoul(splittet_version[0]) * 100;
v += std::stoul(splittet_version[1]);
bareos_version = static_cast<BareosVersionNumber>(v);
ok = true;
} catch (const std::exception &e) {
Dmsg0(100, "Could not read out any version from hello message\n");
}
}
}
}
}
}

return ok;
}

Expand Down
5 changes: 3 additions & 2 deletions core/src/lib/util.h
Expand Up @@ -32,9 +32,10 @@ void BashSpaces(char *str);
void BashSpaces(PoolMem &pm);
void UnbashSpaces(char *str);
void UnbashSpaces(PoolMem &pm);
bool GetNameAndResourceTypeFromHello(const std::string &input,
bool GetNameAndResourceTypeAndVersionFromHello(const std::string &input,
std::string &name,
std::string &r_type_str);
std::string &r_type_str,
BareosVersionNumber &version);
const char* IndentMultilineString(PoolMem &resultbuffer, const char *multilinestring, const char *separator);
char *encode_time(utime_t time, char *buf);
bool ConvertTimeoutToTimespec(timespec &timeout, int timeout_in_seconds);
Expand Down
2 changes: 1 addition & 1 deletion core/src/tests/bsock_test_connection_setup.cc
Expand Up @@ -121,7 +121,7 @@ static PBareosSocket ConnectToDirector()
JobControlRecord jcr;
memset(&jcr, 0, sizeof(jcr));
BStringList args;
uint32_t response_id;
uint32_t response_id = kMessageIdUnknown;

PBareosSocket UA_sock(console::ConnectToDirector(jcr, 0, args, response_id),
[](BareosSocket *p) { delete p; });
Expand Down
46 changes: 34 additions & 12 deletions core/src/tests/lib_tests.cc
Expand Up @@ -41,7 +41,7 @@ TEST(BStringList, ConstructorsTest)
TEST(BStringList, AppendTest)
{
BStringList list1;
std::vector<std::string> list {"T", "est", "123"};
std::vector<std::string> list{"T", "est", "123"};
list1.Append(list);
EXPECT_EQ(0, list1.front().compare(std::string("T")));
list1.erase(list1.begin());
Expand Down Expand Up @@ -161,7 +161,8 @@ enum {

static void do_get_name_from_hello_test(const char *client_string_fmt,
const char *client_name,
std::string r_type_test)
const std::string &r_type_test,
const BareosVersionNumber &version_test)
{
char bashed_client_name[20];
sprintf(bashed_client_name, client_name);
Expand All @@ -172,23 +173,44 @@ static void do_get_name_from_hello_test(const char *client_string_fmt,

std::string name;
std::string r_type_str;
BareosVersionNumber version = BareosVersionNumber::kUndefined;

bool ok = GetNameAndResourceTypeFromHello(output_text, name, r_type_str);
bool ok = GetNameAndResourceTypeAndVersionFromHello(output_text, name, r_type_str, version);

EXPECT_TRUE(ok);
EXPECT_STREQ(name.c_str(), client_name);
EXPECT_STREQ(r_type_str.c_str(), r_type_test.c_str());
EXPECT_EQ(version, version_test);
}

TEST(Util, get_name_from_hello_test)
{
do_get_name_from_hello_test("Hello Client %s calling", "Test Client", "R_CLIENT");
do_get_name_from_hello_test("Hello Storage calling Start Job %s", "Test Client", "R_JOB");
do_get_name_from_hello_test("Hello %s", "Console Name", "R_CONSOLE");
do_get_name_from_hello_test("Hello %s", "*UserAgent*", "R_CONSOLE");
do_get_name_from_hello_test("Hello %s", "*UserAgent*", "R_CONSOLE");
do_get_name_from_hello_test("Hello %s calling", "Console", "R_CONSOLE");
do_get_name_from_hello_test("Hello Director %s calling\n", "bareos dir", "R_DIRECTOR");
do_get_name_from_hello_test("Hello Start Storage Job %s", "Test Job", "R_JOB");
do_get_name_from_hello_test("Hello Client %s FdProtocolVersion=123 calling\n", "Test Client again", "R_CLIENT");
// clang-format off
do_get_name_from_hello_test("Hello Client %s calling",
"Test Client", "R_CLIENT", BareosVersionNumber::kUndefined);
do_get_name_from_hello_test("Hello Storage calling Start Job %s",
"Test Client", "R_JOB", BareosVersionNumber::kUndefined);
do_get_name_from_hello_test("Hello %s",
"Console Name", "R_CONSOLE", BareosVersionNumber::kUndefined);
do_get_name_from_hello_test("Hello %s",
"*UserAgent*", "R_CONSOLE", BareosVersionNumber::kUndefined);
do_get_name_from_hello_test("Hello %s",
"*UserAgent*", "R_CONSOLE", BareosVersionNumber::kUndefined);
do_get_name_from_hello_test("Hello %s calling version 18.2.4rc2",
"Console", "R_CONSOLE", BareosVersionNumber::kRelease_18_2);
do_get_name_from_hello_test("Hello Director %s calling\n",
"bareos dir", "R_DIRECTOR", BareosVersionNumber::kUndefined);
do_get_name_from_hello_test("Hello Start Storage Job %s",
"Test Job", "R_JOB", BareosVersionNumber::kUndefined);
do_get_name_from_hello_test("Hello Client %s FdProtocolVersion=123 calling\n",
"Test Client again", "R_CLIENT", BareosVersionNumber::kUndefined);
// clang-format on
}

TEST(Util, version_number_test)
{
EXPECT_EQ(BareosVersionNumber::kRelease_18_2, static_cast<BareosVersionNumber>(1802));
EXPECT_EQ(BareosVersionNumber::kUndefined, static_cast<BareosVersionNumber>(1));
EXPECT_NE(BareosVersionNumber::kRelease_18_2, static_cast<BareosVersionNumber>(1702));
EXPECT_GT(BareosVersionNumber::kRelease_18_2, BareosVersionNumber::kUndefined);
}

0 comments on commit 6e72314

Please sign in to comment.