1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 * Authenticate caller
21 *
22 * Written by Kern Sibbald, October 2000
23 */
24
25
26 #include "bacula.h"
27 #include "stored.h"
28
29 extern STORES *me; /* our Global resource */
30
31 const int dbglvl = 50;
32
33 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
34
35 /* Version at end of Hello
36 * prior to 06Aug13 no version
37 * 1 06Aug13 - added comm line compression
38 * 2 13Dec13 - added api version to status command
39 */
40 #define SD_VERSION 2
41
42
43 /*
44 * Authenticate the Director
45 */
authenticate_director(JCR * jcr)46 bool authenticate_director(JCR* jcr)
47 {
48 DIRRES *director = jcr->director;
49 int tls_local_need = BNET_TLS_NONE;
50 int tls_remote_need = BNET_TLS_NONE;
51 int compatible = true; /* require md5 compatible DIR */
52 bool auth_success = false;
53 alist *verify_list = NULL;
54 BSOCK *dir = jcr->dir_bsock;
55
56 /* TLS Requirement */
57 if (director->tls_enable) {
58 if (director->tls_require) {
59 tls_local_need = BNET_TLS_REQUIRED;
60 } else {
61 tls_local_need = BNET_TLS_OK;
62 }
63 }
64
65 if (director->tls_authenticate) {
66 tls_local_need = BNET_TLS_REQUIRED;
67 }
68
69 if (director->tls_verify_peer) {
70 verify_list = director->tls_allowed_cns;
71 }
72
73 /* Timeout authentication after 10 mins */
74 btimer_t *tid = start_bsock_timer(dir, AUTH_TIMEOUT);
75 auth_success = cram_md5_challenge(dir, director->password, tls_local_need, compatible);
76 if (auth_success) {
77 auth_success = cram_md5_respond(dir, director->password, &tls_remote_need, &compatible);
78 if (!auth_success) {
79 Dmsg1(dbglvl, "cram_get_auth respond failed with Director %s\n", dir->who());
80 }
81 } else {
82 Dmsg1(dbglvl, "cram_auth challenge failed with Director %s\n", dir->who());
83 }
84
85 if (!auth_success) {
86 Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n"
87 "For help, please see: " MANUAL_AUTH_URL "\n"));
88 auth_success = false;
89 goto auth_fatal;
90 }
91
92 /* Verify that the remote host is willing to meet our TLS requirements */
93 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
94 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
95 " advertize required TLS support.\n"));
96 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
97 auth_success = false;
98 goto auth_fatal;
99 }
100
101 /* Verify that we are willing to meet the remote host's requirements */
102 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
103 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
104 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
105 auth_success = false;
106 goto auth_fatal;
107 }
108
109 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
110 /* Engage TLS! Full Speed Ahead! */
111 if (!bnet_tls_server(director->tls_ctx, dir, verify_list)) {
112 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"),
113 dir->host(), dir->port());
114 auth_success = false;
115 goto auth_fatal;
116 }
117 if (director->tls_authenticate) { /* authenticate with tls only? */
118 dir->free_tls(); /* yes, shut it down */
119 }
120 }
121
122 auth_fatal:
123 stop_bsock_timer(tid);
124 jcr->director = director;
125 if (auth_success) {
126 return send_hello_ok(dir);
127 }
128 send_sorry(dir);
129 Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
130 Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
131 bmicrosleep(5, 0);
132 return false;
133 }
134
135
authenticate_filed(JCR * jcr,BSOCK * fd,int FDVersion)136 int authenticate_filed(JCR *jcr, BSOCK *fd, int FDVersion)
137 {
138 int tls_local_need = BNET_TLS_NONE;
139 int tls_remote_need = BNET_TLS_NONE;
140 int compatible = true; /* require md5 compatible FD */
141 bool auth_success = false;
142 alist *verify_list = NULL;
143
144 /* TLS Requirement */
145 if (me->tls_enable) {
146 if (me->tls_require) {
147 tls_local_need = BNET_TLS_REQUIRED;
148 } else {
149 tls_local_need = BNET_TLS_OK;
150 }
151 }
152
153 if (me->tls_authenticate) {
154 tls_local_need = BNET_TLS_REQUIRED;
155 }
156
157 if (me->tls_verify_peer) {
158 verify_list = me->tls_allowed_cns;
159 }
160
161 /* Timeout authentication after 5 mins */
162 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
163 /* Challenge FD */
164 Dmsg0(050, "Challenge FD\n");
165 auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
166 if (auth_success) {
167 /* Respond to his challenge */
168 Dmsg0(050, "Respond to FD challenge\n");
169 auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
170 if (!auth_success) {
171 Dmsg1(dbglvl, "Respond cram-get-auth respond failed with FD: %s\n", fd->who());
172 }
173 } else {
174 Dmsg1(dbglvl, "Challenge cram-auth failed with FD: %s\n", fd->who());
175 }
176
177 if (!auth_success) {
178 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
179 "For help, please see: " MANUAL_AUTH_URL "\n"),
180 fd->who());
181 auth_success = false;
182 goto auth_fatal;
183 }
184
185 /* Verify that the remote host is willing to meet our TLS requirements */
186 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
187 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
188 " advertize required TLS support.\n"));
189 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
190 auth_success = false;
191 goto auth_fatal;
192 }
193
194 /* Verify that we are willing to meet the remote host's requirements */
195 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
196 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
197 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
198 auth_success = false;
199 goto auth_fatal;
200 }
201
202 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
203 /* Engage TLS! Full Speed Ahead! */
204 if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
205 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"),
206 fd->host(), fd->port());
207 auth_success = false;
208 goto auth_fatal;
209 }
210 if (me->tls_authenticate) { /* tls authenticate only? */
211 fd->free_tls(); /* yes, shut it down */
212 }
213 }
214
215 auth_fatal:
216 stop_bsock_timer(tid);
217 if (!auth_success) {
218 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
219 "For help, please see: " MANUAL_AUTH_URL "\n"),
220 fd->who());
221 }
222
223 /* Version 5 of the protocol is a bit special, it is used by both 6.0.0
224 * Enterprise version and 7.0.x Community version, but do not support the
225 * same level of features. As nobody is using the 6.0.0 release, we can
226 * be pretty sure that the FD in version 5 is a community FD.
227 */
228 if (auth_success && (FDVersion >= 9 || FDVersion == 5)) {
229 send_hello_ok(fd);
230 }
231 return auth_success;
232 }
233
234 /*
235 * First prove our identity to the Storage daemon, then
236 * make him prove his identity.
237 */
authenticate_storagedaemon(JCR * jcr)238 bool authenticate_storagedaemon(JCR *jcr)
239 {
240 BSOCK *sd = jcr->store_bsock;
241 int tls_local_need = BNET_TLS_NONE;
242 int tls_remote_need = BNET_TLS_NONE;
243 int compatible = true;
244 bool auth_success = false;
245 int sd_version = 0;
246
247 btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
248
249 /* TLS Requirement */
250 if (have_tls && me->tls_enable) {
251 if (me->tls_require) {
252 tls_local_need = BNET_TLS_REQUIRED;
253 } else {
254 tls_local_need = BNET_TLS_OK;
255 }
256 }
257
258 if (me->tls_authenticate) {
259 tls_local_need = BNET_TLS_REQUIRED;
260 }
261
262 if (job_canceled(jcr)) {
263 auth_success = false; /* force quick exit */
264 goto auth_fatal;
265 }
266
267 /* Respond to SD challenge */
268 Dmsg0(050, "Respond to SD challenge\n");
269 auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
270 if (job_canceled(jcr)) {
271 auth_success = false; /* force quick exit */
272 goto auth_fatal;
273 }
274 if (!auth_success) {
275 Dmsg1(dbglvl, "cram_respond failed for SD: %s\n", sd->who());
276 } else {
277 /* Now challenge him */
278 Dmsg0(050, "Challenge SD\n");
279 auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
280 if (!auth_success) {
281 Dmsg1(dbglvl, "cram_challenge failed for SD: %s\n", sd->who());
282 }
283 }
284
285 if (!auth_success) {
286 Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
287 "Please see " MANUAL_AUTH_URL " for help.\n"));
288 goto auth_fatal;
289 } else {
290 Dmsg0(050, "Authorization with SD is OK\n");
291 }
292
293 /* Verify that the remote host is willing to meet our TLS requirements */
294 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
295 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
296 " advertize required TLS support.\n"));
297 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
298 auth_success = false;
299 goto auth_fatal;
300 }
301
302 /* Verify that we are willing to meet the remote host's requirements */
303 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
304 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
305 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
306 auth_success = false;
307 goto auth_fatal;
308 }
309
310 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
311 /* Engage TLS! Full Speed Ahead! */
312 if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
313 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
314 auth_success = false;
315 goto auth_fatal;
316 }
317 if (me->tls_authenticate) { /* tls authentication only? */
318 sd->free_tls(); /* yes, shutdown tls */
319 }
320 }
321 if (sd->recv() <= 0) {
322 auth_success = false;
323 goto auth_fatal;
324 }
325 sscanf(sd->msg, "3000 OK Hello %d", &sd_version);
326 if (sd_version >= 1 && me->comm_compression) {
327 sd->set_compress();
328 } else {
329 sd->clear_compress();
330 Dmsg0(050, "*** No FD compression with SD\n");
331 }
332
333 /* At this point, we have successfully connected */
334
335 auth_fatal:
336 /* Destroy session key */
337 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
338 stop_bsock_timer(tid);
339 /* Single thread all failures to avoid DOS */
340 if (!auth_success) {
341 P(mutex);
342 bmicrosleep(6, 0);
343 V(mutex);
344 }
345 return auth_success;
346 }
347