From 1da419c2b254ef0fcd2774ef101eaa36e6e3a417 Mon Sep 17 00:00:00 2001 From: Frank Ueberschar Date: Mon, 14 Jan 2019 15:16:20 +0100 Subject: [PATCH] dir: send the tls_policy to passive client --- core/src/dird/backup.cc | 2 +- core/src/dird/fd_cmds.cc | 28 ++++++++- core/src/dird/fd_cmds.h | 2 +- core/src/dird/restore.cc | 2 +- core/src/dird/ua_cmds.cc | 2 +- core/src/dird/verify.cc | 4 +- core/src/filed/CMakeLists.txt | 7 ++- core/src/filed/dir_cmd.cc | 32 +++++++---- core/src/filed/dir_cmd.h | 4 +- core/src/filed/evaluate_job_command.cc | 78 ++++++++++---------------- core/src/filed/evaluate_job_command.h | 58 +++++++++++++++++++ core/src/lib/bsock.cc | 3 + core/src/tests/CMakeLists.txt | 1 + core/src/tests/lib_tests.cc | 45 +++++++++++++++ 14 files changed, 194 insertions(+), 74 deletions(-) create mode 100644 core/src/filed/evaluate_job_command.h diff --git a/core/src/dird/backup.cc b/core/src/dird/backup.cc index 5b0450ff284..e6c647065eb 100644 --- a/core/src/dird/backup.cc +++ b/core/src/dird/backup.cc @@ -491,7 +491,7 @@ bool DoNativeBackup(JobControlRecord *jcr) goto bail_out; } Dmsg1(120, "jobid: %d: connected\n", jcr->JobId); - SendJobInfo(jcr); + SendJobInfoToFileDaemon(jcr); fd = jcr->file_bsock; /* diff --git a/core/src/dird/fd_cmds.cc b/core/src/dird/fd_cmds.cc index bf3a41655dd..1aa3d4edad0 100644 --- a/core/src/dird/fd_cmds.cc +++ b/core/src/dird/fd_cmds.cc @@ -55,6 +55,8 @@ static char filesetcmd[] = "fileset%s\n"; /* set full fileset */ static char jobcmd[] = "JobId=%s Job=%s SDid=%u SDtime=%u Authorization=%s\n"; +static char jobcmdssl[] = + "JobId=%s Job=%s SDid=%u SDtime=%u Authorization=%s ssl=%d\n"; /* Note, mtime_only is not used here -- implemented as file option */ static char levelcmd[] = "level = %s%s%s mtime_only=%d %s%s\n"; @@ -308,7 +310,7 @@ bool ConnectToFileDaemon(JobControlRecord *jcr, int retry_interval, int max_retr return success; } -int SendJobInfo(JobControlRecord *jcr) +int SendJobInfoToFileDaemon(JobControlRecord *jcr) { BareosSocket *fd = jcr->file_bsock; char ed1[30]; @@ -320,8 +322,28 @@ int SendJobInfo(JobControlRecord *jcr) jcr->sd_auth_key = bstrdup("dummy"); } - fd->fsend(jobcmd, edit_int64(jcr->JobId, ed1), jcr->Job, jcr->VolSessionId, - jcr->VolSessionTime, jcr->sd_auth_key); + StorageResource *storage; + if (jcr->res.write_storage) { + storage = jcr->res.write_storage; + } else if (jcr->res.read_storage) { + storage = jcr->res.read_storage; + } else { + Jmsg(jcr, M_FATAL, 0, _("No read or write storage defined\n")); + jcr->setJobStatus(JS_ErrorTerminated); + return 0; + } + + if (jcr->res.client->connection_successful_handshake_ != ClientConnectionHandshakeMode::kTlsFirst) { + /* client before Bareos 18.2 */ + fd->fsend(jobcmd, edit_int64(jcr->JobId, ed1), jcr->Job, jcr->VolSessionId, + jcr->VolSessionTime, jcr->sd_auth_key); + } else { + /* client onwards Bareos 18.2 */ + TlsPolicy tls_policy; + tls_policy = storage->IsTlsConfigured() ? TlsPolicy::kBnetTlsAuto : TlsPolicy::kBnetTlsNone; + fd->fsend(jobcmdssl, edit_int64(jcr->JobId, ed1), jcr->Job, jcr->VolSessionId, + jcr->VolSessionTime, jcr->sd_auth_key, tls_policy); + } if (!jcr->keep_sd_auth_key && !bstrcmp(jcr->sd_auth_key, "dummy")) { memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key)); diff --git a/core/src/dird/fd_cmds.h b/core/src/dird/fd_cmds.h index 9901654eda0..198f79a3ed4 100644 --- a/core/src/dird/fd_cmds.h +++ b/core/src/dird/fd_cmds.h @@ -26,7 +26,7 @@ namespace directordaemon { bool ConnectToFileDaemon(JobControlRecord *jcr, int retry_interval, int max_retry_time, bool verbose, UaContext *ua = nullptr); -int SendJobInfo(JobControlRecord *jcr); +int SendJobInfoToFileDaemon(JobControlRecord *jcr); bool SendIncludeList(JobControlRecord *jcr); bool SendExcludeList(JobControlRecord *jcr); bool SendLevelCommand(JobControlRecord *jcr); diff --git a/core/src/dird/restore.cc b/core/src/dird/restore.cc index ed1c1a53793..b1e4b560827 100644 --- a/core/src/dird/restore.cc +++ b/core/src/dird/restore.cc @@ -199,7 +199,7 @@ static inline bool DoNativeRestoreBootstrap(JobControlRecord *jcr) if (!ConnectToFileDaemon(jcr, 10, me->FDConnectTimeout, true)) { goto bail_out; } - SendJobInfo(jcr); + SendJobInfoToFileDaemon(jcr); fd = jcr->file_bsock; if (!SendSecureEraseReqToFd(jcr)) { diff --git a/core/src/dird/ua_cmds.cc b/core/src/dird/ua_cmds.cc index 5cc07c766e7..a9ba1a957d6 100644 --- a/core/src/dird/ua_cmds.cc +++ b/core/src/dird/ua_cmds.cc @@ -1768,7 +1768,7 @@ static bool EstimateCmd(UaContext *ua, const char *cmd) return false; } - if (!SendJobInfo(jcr)) { + if (!SendJobInfoToFileDaemon(jcr)) { ua->ErrorMsg(_("Failed to connect to Client.\n")); return false; } diff --git a/core/src/dird/verify.cc b/core/src/dird/verify.cc index 733ab878b3d..fbdeaaacfa4 100644 --- a/core/src/dird/verify.cc +++ b/core/src/dird/verify.cc @@ -280,7 +280,7 @@ bool DoVerify(JobControlRecord *jcr) if (!ConnectToFileDaemon(jcr, 10, me->FDConnectTimeout, true)) { goto bail_out; } - SendJobInfo(jcr); + SendJobInfoToFileDaemon(jcr); fd = jcr->file_bsock; /* @@ -302,7 +302,7 @@ bool DoVerify(JobControlRecord *jcr) if (!ConnectToFileDaemon(jcr, 10, me->FDConnectTimeout, true)) { goto bail_out; } - SendJobInfo(jcr); + SendJobInfoToFileDaemon(jcr); fd = jcr->file_bsock; break; } diff --git a/core/src/filed/CMakeLists.txt b/core/src/filed/CMakeLists.txt index 403ee5ecc73..f1c6824aa05 100644 --- a/core/src/filed/CMakeLists.txt +++ b/core/src/filed/CMakeLists.txt @@ -26,9 +26,10 @@ IF(HAVE_WIN32) ) ENDIF() -set(FDSRCS accurate.cc authenticate.cc crypto.cc fd_plugins.cc fileset.cc sd_cmds.cc verify.cc - accurate_htable.cc backup.cc dir_cmd.cc filed.cc filed_globals.cc heartbeat.cc socket_server.cc - verify_vol.cc accurate_lmdb.cc compression.cc estimate.cc filed_conf.cc restore.cc status.cc) +set(FDSRCS accurate.cc authenticate.cc crypto.cc evaluate_job_command.cc fd_plugins.cc fileset.cc + sd_cmds.cc verify.cc accurate_htable.cc backup.cc dir_cmd.cc filed.cc filed_globals.cc heartbeat.cc + socket_server.cc verify_vol.cc accurate_lmdb.cc compression.cc estimate.cc filed_conf.cc + restore.cc status.cc) IF(HAVE_WIN32) LIST(APPEND FDSRCS diff --git a/core/src/filed/dir_cmd.cc b/core/src/filed/dir_cmd.cc index 80571796306..858ac7e39df 100644 --- a/core/src/filed/dir_cmd.cc +++ b/core/src/filed/dir_cmd.cc @@ -35,6 +35,7 @@ #include "filed/authenticate.h" #include "filed/dir_cmd.h" #include "filed/estimate.h" +#include "filed/evaluate_job_command.h" #include "filed/heartbeat.h" #include "filed/fileset.h" #include "filed/socket_server.h" @@ -191,7 +192,6 @@ static char setbandwidthcmd[] = "setbandwidth=%lld Job=%127s"; static char setdebugv0cmd[] = "setdebug=%d trace=%d"; static char setdebugv1cmd[] = "setdebug=%d trace=%d hangup=%d"; static char setdebugv2cmd[] = "setdebug=%d trace=%d hangup=%d timestamp=%d"; -static char jobcmd[] = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s"; static char storaddrv0cmd[] = "storage address=%s port=%d ssl=%d"; static char storaddrv1cmd[] = "storage address=%s port=%d ssl=%d Authorization=%100s"; static char sessioncmd[] = "session %127s %ld %ld %ld %ld %ld %ld\n"; @@ -917,23 +917,31 @@ static bool EstimateCmd(JobControlRecord *jcr) static bool job_cmd(JobControlRecord *jcr) { BareosSocket *dir = jcr->dir_bsock; - PoolMem sd_auth_key(PM_MESSAGE); - sd_auth_key.check_size(dir->message_length); - const char *os_version; - if (sscanf(dir->msg, jobcmd, &jcr->JobId, jcr->Job, &jcr->VolSessionId, &jcr->VolSessionTime, - sd_auth_key.c_str()) != 5) { - PmStrcpy(jcr->errmsg, dir->msg); - Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg); - dir->fsend(BADjob); - return false; + JobCommand command(dir->msg); + + if (!command.EvaluationSuccesful()) { + PmStrcpy(jcr->errmsg, dir->msg); + Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg); + dir->fsend(BADjob); + return false; } - SetStorageAuthKeyAndTlsPolicy(jcr, sd_auth_key.c_str(), jcr->sd_tls_policy); - Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key); + + jcr->JobId = command.job_id_; + strncpy(jcr->Job, command.job_, sizeof(jcr->Job)); + jcr->VolSessionId = command.vol_session_id_; + jcr->VolSessionTime = command.vol_session_time_; + + TlsPolicy tls_policy = command.protocol_version_ == JobCommand::ProtocolVersion::KVersionBefore_18_2 ? + TlsPolicy::kBnetTlsNone : command.tls_policy_; + + SetStorageAuthKeyAndTlsPolicy(jcr, command.sd_auth_key_, tls_policy); + Dmsg3(120, "JobId=%d Auth=%s TlsPolicy=%d\n", jcr->JobId, jcr->sd_auth_key, tls_policy); Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job); NewPlugins(jcr); /* instantiate plugins for this jcr */ GeneratePluginEvent(jcr, bEventJobStart, (void *)jcr->errmsg); + const char *os_version; #ifdef HAVE_WIN32 os_version = win_os; #else diff --git a/core/src/filed/dir_cmd.h b/core/src/filed/dir_cmd.h index d9ffc4c5313..87ebb10dd61 100644 --- a/core/src/filed/dir_cmd.h +++ b/core/src/filed/dir_cmd.h @@ -22,6 +22,9 @@ #ifndef BAREOS_FILED_DIR_CMD_H_ #define BAREOS_FILED_DIR_CMD_H_ 1 +class JobControlRecord; +class BareosSocket; + namespace filedaemon { JobControlRecord *create_new_director_session(BareosSocket *dir); @@ -29,7 +32,6 @@ void *process_director_commands(JobControlRecord *jcr, BareosSocket *dir); void *handle_director_connection(BareosSocket *dir); bool StartConnectToDirectorThreads(); bool StopConnectToDirectorThreads(bool wait=false); - } /* namespace filedaemon */ #endif /* BAREOS_FILED_DIR_CMD_H_ */ diff --git a/core/src/filed/evaluate_job_command.cc b/core/src/filed/evaluate_job_command.cc index b794c9682f9..b1811fbbcb9 100644 --- a/core/src/filed/evaluate_job_command.cc +++ b/core/src/filed/evaluate_job_command.cc @@ -19,68 +19,48 @@ 02110-1301, USA. */ -#include "filed/dir_cmd.h" +#include "filed/evaluate_job_command.h" #include "include/bareos.h" -const std::string EvaluateJobcommand::jobcmd { "JobId=%d Job=%127s SDid=%u SDtime=%u Authorization=%100s" }; -const std::string EvaluateJobcommand::jobcmdssl { "JobId=%d Job=%127s SDid=%u SDtime=%u Authorization=%100s ssl=%d\n" }; - namespace filedaemon { -class EvaluateJobcommand -{ - public: - EvaluateJobcommand(); - : uint32_t JobId(0) - , Job[24] - , VolSessionId(0) - , VolSessionTime(0) - PoolMem sd_auth_key; - , tls_policy(TlsPolicy::kBnetTlsUnknown) - - - uint32_t JobId; - char Job[24]; - uint32_t VolSessionId; - uint32_t VolSessionTime; - PoolMem sd_auth_key; - TlsPolicy tls_policy = TlsPolicy::kBnetTlsUnknown; - - private: - std::string jobcmd { "JobId=%d Job=%127s SDid=%u SDtime=%u Authorization=%100s" }; - std::string jobcmdssl { "JobId=%d Job=%127s SDid=%u SDtime=%u Authorization=%100s ssl=%d\n" }; -}; +const std::string JobCommand::jobcmd_{"JobId=%d Job=%127s SDid=%u SDtime=%u Authorization=%100s"}; +const std::string JobCommand::jobcmdssl_{ + "JobId=%d Job=%127s SDid=%u SDtime=%u Authorization=%100s ssl=%d\n"}; -JobMessageProtocolVersion EvaluateJobcommand(const POOLMEM *msg, - uint32_t &JobId, - char *Job, - uint32_t &VolSessionId, - uint32_t &VolSessionTime, - PoolMem &sd_auth_key, - TlsPolicy &tls_policy) +JobCommand::JobCommand(const char *msg) : job_{0}, sd_auth_key_{0} { - int tries = 2; - JobMessageProtocolVersion successful_protocol = JobMessageProtocolVersion::kVersionUndefinded; + ProtocolVersion protocol = ProtocolVersion::kVersionUndefinded; - for (int protocol_try = 1; !successful_protocol && protocol_try <= tries; protocol_try++) { + std::vector implemented_protocols{ProtocolVersion::kVersionFrom_18_2, + ProtocolVersion::KVersionBefore_18_2}; + + for (auto protocol_try : implemented_protocols) { switch (protocol_try) { - case JobMessageProtocolVersion::kVersionFrom_18_2: - if (sscanf(msg, jobcmdssl, &JobId, Job, &VolSessionId, &VolSessionTime, - sd_auth_key.c_str(), &tls_policy) == 6) { - successful_protocol = static_cast(protocol_try); + case ProtocolVersion::kVersionFrom_18_2: + if (sscanf(msg, jobcmdssl_.c_str(), &job_id_, job_, &vol_session_id_, &vol_session_time_, sd_auth_key_, + &tls_policy_) == 6) { + protocol = protocol_try; } break; - case JobMessageProtocolVersion::KVersionBefore_18_2: - if (sscanf(msg, jobcmd, &JobId, Job, &VolSessionId, &VolSessionTime, - sd_auth_key.c_str()) == 5) { - successful_protocol = static_cast(protocol_try); + case ProtocolVersion::KVersionBefore_18_2: + if (sscanf(msg, jobcmd_.c_str(), &job_id_, job_, &vol_session_id_, &vol_session_time_, sd_auth_key_) == + 5) { + protocol = protocol_try; } break; default: + /* never */ break; - } - } - return successful_protocol; + } /* switch () */ + if (protocol != ProtocolVersion::kVersionUndefinded) { break; } + } /* for ( auto.. */ + protocol_version_ = protocol; +} + +bool JobCommand::EvaluationSuccesful() const +{ + return protocol_version_ != ProtocolVersion::kVersionUndefinded; } -} /* namespace filedamon */ +} // namespace filedaemon diff --git a/core/src/filed/evaluate_job_command.h b/core/src/filed/evaluate_job_command.h new file mode 100644 index 00000000000..2db07af735b --- /dev/null +++ b/core/src/filed/evaluate_job_command.h @@ -0,0 +1,58 @@ +/** + BAREOSĀ® - Backup Archiving REcovery Open Sourced + + Copyright (C) 2019-2019 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_FILED_EVALUATE_JOB_COMMAND_H_ +#define BAREOS_FILED_EVALUATE_JOB_COMMAND_H_ + +#include "include/bareos.h" + +namespace filedaemon { + +class JobCommand { + public: + enum class ProtocolVersion + { + kVersionUndefinded, + kVersionFrom_18_2, + KVersionBefore_18_2 + }; + + public: + JobCommand(const char *msg); + JobCommand(const JobCommand &) = delete; + bool EvaluationSuccesful() const; + + uint32_t job_id_ = 0; + char job_[MAX_NAME_LENGTH]; + uint32_t vol_session_id_ = 0; + uint32_t vol_session_time_ = 0; + char sd_auth_key_[MAX_NAME_LENGTH]; + TlsPolicy tls_policy_ = TlsPolicy::kBnetTlsUnknown; + + ProtocolVersion protocol_version_ = ProtocolVersion::kVersionUndefinded; + + private: + static const std::string jobcmd_; + static const std::string jobcmdssl_; +}; +} /* namespace filedaemon */ + +#endif /* BAREOS_FILED_EVALUATE_JOB_COMMAND_H_ */ diff --git a/core/src/lib/bsock.cc b/core/src/lib/bsock.cc index 912084a9fe7..106e0a61aa4 100644 --- a/core/src/lib/bsock.cc +++ b/core/src/lib/bsock.cc @@ -34,6 +34,8 @@ #include "lib/util.h" #include "lib/bstringlist.h" +#include + static constexpr int debuglevel = 50; BareosSocket::BareosSocket() @@ -606,6 +608,7 @@ bool BareosSocket::EvaluateCleartextBareosHello(bool &cleartext_hello, std::string code; BareosVersionNumber version = BareosVersionNumber::kUndefined; if (GetNameAndResourceTypeAndVersionFromHello(received, name, code, version)) { + name.erase(std::remove(name.begin(), name.end(), '\n'), name.end()); if (version > BareosVersionNumber::kUndefined) { BareosVersionToMajorMinor v(version); Dmsg4(200, "Identified from Bareos handshake: %s-%s recognized version: %d.%d\n", diff --git a/core/src/tests/CMakeLists.txt b/core/src/tests/CMakeLists.txt index c59c3c50afc..1fe216d9f92 100644 --- a/core/src/tests/CMakeLists.txt +++ b/core/src/tests/CMakeLists.txt @@ -60,6 +60,7 @@ add_executable(test_lib htable_test.cc qualified_resource_name_type_converter_test.cc lib_tests.cc + ${PROJECT_SOURCE_DIR}/src/filed/evaluate_job_command.cc ) target_link_libraries(test_lib diff --git a/core/src/tests/lib_tests.cc b/core/src/tests/lib_tests.cc index 19a9a0238b6..a03e3143b0b 100644 --- a/core/src/tests/lib_tests.cc +++ b/core/src/tests/lib_tests.cc @@ -223,3 +223,48 @@ TEST(Util, version_number_major_minor) EXPECT_EQ(v.minor, 2); } +#include "filed/evaluate_job_command.h" + +TEST(Filed, evaluate_jobcommand_from_18_2_test) +{ + /* command with ssl argument */ + static const char jobcmd_kVersionFrom_18_2[] = "JobId=111 Job=FirstJob SDid=222 SDtime=333 Authorization=SecretOne ssl=4\n"; + + filedaemon::JobCommand eval(jobcmd_kVersionFrom_18_2); + + EXPECT_TRUE(eval.EvaluationSuccesful()); + EXPECT_EQ(eval.protocol_version_, filedaemon::JobCommand::ProtocolVersion::kVersionFrom_18_2); + EXPECT_EQ(eval.job_id_, 111); + EXPECT_STREQ(eval.job_, "FirstJob"); + EXPECT_EQ(eval.vol_session_id_, 222); + EXPECT_EQ(eval.vol_session_time_, 333); + EXPECT_STREQ(eval.sd_auth_key_, "SecretOne"); + EXPECT_EQ(eval.tls_policy_, 4); +} + +TEST(Filed, evaluate_jobcommand_before_18_2_test) +{ + /* command without ssl argument */ + static char jobcmdssl_KVersionBefore_18_2[] = "JobId=123 Job=SecondJob SDid=456 SDtime=789 Authorization=SecretTwo"; + + filedaemon::JobCommand eval(jobcmdssl_KVersionBefore_18_2); + + EXPECT_TRUE(eval.EvaluationSuccesful()); + EXPECT_EQ(eval.protocol_version_, filedaemon::JobCommand::ProtocolVersion::KVersionBefore_18_2); + EXPECT_EQ(eval.job_id_, 123); + EXPECT_STREQ(eval.job_, "SecondJob"); + EXPECT_EQ(eval.vol_session_id_, 456); + EXPECT_EQ(eval.vol_session_time_, 789); + EXPECT_STREQ(eval.sd_auth_key_, "SecretTwo"); +} + +TEST(Filed, evaluate_jobcommand_wrong_format_test) +{ + /* malformed command */ + static char jobcmdssl_KVersionBefore_18_2[] = "JobId=123 Job=Foo"; + + filedaemon::JobCommand eval(jobcmdssl_KVersionBefore_18_2); + + EXPECT_FALSE(eval.EvaluationSuccesful()); + EXPECT_EQ(eval.protocol_version_, filedaemon::JobCommand::ProtocolVersion::kVersionUndefinded); +}