1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2018-2020 Bareos GmbH & Co. KG
5 
6    This program is Free Software; you can redistribute it and/or
7    modify it under the terms of version three of the GNU Affero General Public
8    License as published by the Free Software Foundation and included
9    in the file LICENSE.
10 
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14    Affero General Public License for more details.
15 
16    You should have received a copy of the GNU Affero General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19    02110-1301, USA.
20 */
21 
22 #include "include/bareos.h"
23 #include "try_tls_handshake_as_a_server.h"
24 
25 #include "lib/bsock_tcp.h"
26 #include "lib/configured_tls_policy_getter.h"
27 #include "lib/parse_conf.h"
28 
29 enum class ConnectionHandshakeMode
30 {
31   PerformTlsHandshake,
32   PerformCleartextHandshake,
33   CloseConnection
34 };
35 
GetHandshakeMode(BareosSocket * bs,const ConfigurationParser & config)36 static ConnectionHandshakeMode GetHandshakeMode(
37     BareosSocket* bs,
38     const ConfigurationParser& config)
39 {
40   bool cleartext_hello;
41   std::string client_name;
42   std::string r_code_str;
43   BareosVersionNumber version = BareosVersionNumber::kUndefined;
44 
45   if (!bs->EvaluateCleartextBareosHello(cleartext_hello, client_name,
46                                         r_code_str, version)) {
47     Dmsg0(100, "Error occured when trying to peek cleartext hello\n");
48     return ConnectionHandshakeMode::CloseConnection;
49   }
50 
51   bs->connected_daemon_version_ = static_cast<BareosVersionNumber>(version);
52 
53   if (cleartext_hello) {
54     ConfiguredTlsPolicyGetter tls_policy_getter(config);
55     TlsPolicy tls_policy;
56     if (!tls_policy_getter.GetConfiguredTlsPolicyFromCleartextHello(
57             r_code_str, client_name, tls_policy)) {
58       Dmsg0(200, "Could not read out cleartext configuration\n");
59       return ConnectionHandshakeMode::CloseConnection;
60     }
61     Dmsg0(200, "TlsPolicy for %s is %u\n", client_name.c_str(), tls_policy);
62     if (r_code_str == std::string("R_CLIENT")) {
63       if (tls_policy == kBnetTlsRequired) {
64         return ConnectionHandshakeMode::CloseConnection;
65       } else { /* kBnetTlsNone or kBnetTlsEnabled */
66         return ConnectionHandshakeMode::PerformCleartextHandshake;
67       }
68     } else if (r_code_str == std::string("R_CONSOLE")
69                && version < BareosVersionNumber::kRelease_18_2) {
70       return ConnectionHandshakeMode::PerformCleartextHandshake;
71     } else {
72       if (tls_policy == kBnetTlsNone) {
73         return ConnectionHandshakeMode::PerformCleartextHandshake;
74       } else {
75         Dmsg1(200,
76               "Connection to %s will be denied due to configuration mismatch\n",
77               client_name.c_str());
78         return ConnectionHandshakeMode::CloseConnection;
79       }
80     }
81   } else { /* not cleartext */
82     return ConnectionHandshakeMode::PerformTlsHandshake;
83   } /* if (cleartext_hello) */
84 }
85 
TryTlsHandshakeAsAServer(BareosSocket * bs,ConfigurationParser * config)86 bool TryTlsHandshakeAsAServer(BareosSocket* bs, ConfigurationParser* config)
87 {
88   ASSERT(config);
89   ConnectionHandshakeMode mode = GetHandshakeMode(bs, *config);
90 
91   bool success = false;
92 
93   switch (mode) {
94     case ConnectionHandshakeMode::PerformTlsHandshake:
95       if (bs->DoTlsHandshakeAsAServer(config)) { success = true; }
96       break;
97     case ConnectionHandshakeMode::PerformCleartextHandshake:
98       /* do tls handshake later */
99       success = true;
100       break;
101     default:
102     case ConnectionHandshakeMode::CloseConnection:
103       success = false;
104       break;
105   }
106 
107   return success;
108 }
109