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 Director who is attempting to connect.
21  *
22  *   Kern Sibbald, October 2000
23  *
24  */
25 
26 #include "bacula.h"
27 #include "filed.h"
28 
29 extern CLIENT *me;                 /* my resource */
30 
31 const int dbglvl = 50;
32 
33 /* Version at end of Hello
34  *   prior to 10Mar08 no version
35  *   1 10Mar08
36  *   2 13Mar09 - added the ability to restore from multiple storages
37  *   3 03Sep10 - added the restore object command for vss plugin 4.0
38  *   4 25Nov10 - added bandwidth command 5.1
39  *   5 24Nov11 - added new restore object command format (pluginname) 6.0
40  *   6 15Feb12 - added Component selection information list
41  *   7 19Feb12 - added Expected files to restore
42  *   8 22Mar13 - added restore options + version for SD
43  *   9 06Aug13 - added comm line compression
44  *  10 01Jan14 - added SD Calls Client and api version to status command
45  */
46 #define FD_VERSION 10
47 
48 /* For compatibility with old Community SDs */
49 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
50 
51 /*
52  * Authenticated the Director
53  */
authenticate_director(JCR * jcr)54 bool authenticate_director(JCR *jcr)
55 {
56    DIRRES *director = jcr->director;
57    int tls_local_need = BNET_TLS_NONE;
58    int tls_remote_need = BNET_TLS_NONE;
59    int compatible = true;                 /* Want md5 compatible DIR */
60    bool auth_success = false;
61    alist *verify_list = NULL;
62    btimer_t *tid = NULL;
63    BSOCK *dir = jcr->dir_bsock;
64 
65    if (have_tls) {
66       /* TLS Requirement */
67       if (director->tls_enable) {
68          if (director->tls_require) {
69             tls_local_need = BNET_TLS_REQUIRED;
70          } else {
71             tls_local_need = BNET_TLS_OK;
72          }
73       }
74 
75       if (director->tls_authenticate) {
76          tls_local_need = BNET_TLS_REQUIRED;
77       }
78 
79       if (director->tls_verify_peer) {
80          verify_list = director->tls_allowed_cns;
81       }
82    }
83 
84    tid = start_bsock_timer(dir, AUTH_TIMEOUT);
85    /* Challenge the director */
86    auth_success = cram_md5_challenge(dir, director->password, tls_local_need, compatible);
87    if (job_canceled(jcr)) {
88       auth_success = false;
89       goto auth_fatal;                   /* quick exit */
90    }
91    if (auth_success) {
92       auth_success = cram_md5_respond(dir, director->password, &tls_remote_need, &compatible);
93       if (!auth_success) {
94           char addr[64];
95           char *who = dir->get_peer(addr, sizeof(addr)) ? dir->who() : addr;
96           Dmsg1(dbglvl, "cram_get_auth respond failed for Director: %s\n", who);
97       }
98    } else {
99        char addr[64];
100        char *who = dir->get_peer(addr, sizeof(addr)) ? dir->who() : addr;
101        Dmsg1(dbglvl, "cram_auth challenge failed for Director %s\n", who);
102    }
103    if (!auth_success) {
104        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
105              dir->who());
106        goto auth_fatal;
107    }
108 
109    /* Verify that the remote host is willing to meet our TLS requirements */
110    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
111       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
112            " advertize required TLS support.\n"));
113       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
114       auth_success = false;
115       goto auth_fatal;
116    }
117 
118    /* Verify that we are willing to meet the remote host's requirements */
119    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
120       Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
121       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
122       auth_success = false;
123       goto auth_fatal;
124    }
125 
126    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
127       /* Engage TLS! Full Speed Ahead! */
128       if (!bnet_tls_server(director->tls_ctx, dir, verify_list)) {
129          Jmsg0(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
130          auth_success = false;
131          goto auth_fatal;
132       }
133       if (director->tls_authenticate) {         /* authentication only? */
134          dir->free_tls();                        /* shutodown tls */
135       }
136    }
137    auth_success = true;
138 
139 auth_fatal:
140    if (tid) {
141       stop_bsock_timer(tid);
142       tid = NULL;
143    }
144    if (auth_success) {
145       return send_hello_ok(dir);
146    }
147    send_sorry(dir);
148    /* Single thread all failures to avoid DOS */
149    P(mutex);
150    bmicrosleep(6, 0);
151    V(mutex);
152    return false;
153 }
154 
155 
156 /*
157  * First prove our identity to the Storage daemon, then
158  * make him prove his identity.
159  */
authenticate_storagedaemon(JCR * jcr)160 bool authenticate_storagedaemon(JCR *jcr)
161 {
162    BSOCK *sd = jcr->store_bsock;
163    int tls_local_need = BNET_TLS_NONE;
164    int tls_remote_need = BNET_TLS_NONE;
165    int compatible = true;
166    bool auth_success = false;
167    int sd_version = 0;
168 
169    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
170 
171    /* TLS Requirement */
172    if (have_tls && me->tls_enable) {
173       if (me->tls_require) {
174          tls_local_need = BNET_TLS_REQUIRED;
175       } else {
176          tls_local_need = BNET_TLS_OK;
177       }
178    }
179 
180    if (me->tls_authenticate) {
181       tls_local_need = BNET_TLS_REQUIRED;
182    }
183 
184    if (job_canceled(jcr)) {
185       auth_success = false;     /* force quick exit */
186       goto auth_fatal;
187    }
188 
189    /* Respond to SD challenge */
190    Dmsg0(050, "==== respond to SD challenge\n");
191    auth_success = cram_md5_respond(sd, jcr->sd_auth_key, &tls_remote_need, &compatible);
192    if (job_canceled(jcr)) {
193       auth_success = false;     /* force quick exit */
194       goto auth_fatal;
195    }
196    if (!auth_success) {
197       Dmsg1(dbglvl, "cram_respond failed for SD: %s\n", sd->who());
198    } else {
199       /* Now challenge him */
200       Dmsg0(050, "==== Challenge SD\n");
201       auth_success = cram_md5_challenge(sd, jcr->sd_auth_key, tls_local_need, compatible);
202       if (!auth_success) {
203          Dmsg1(dbglvl, "cram_challenge failed for SD: %s\n", sd->who());
204       }
205    }
206 
207    if (!auth_success) {
208       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
209        "For help, please see " MANUAL_AUTH_URL "\n"));
210       goto auth_fatal;
211    } else {
212       Dmsg0(050, "Authorization with SD is OK\n");
213    }
214 
215    /* Verify that the remote host is willing to meet our TLS requirements */
216    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
217       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
218            " advertize required TLS support.\n"));
219       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
220       auth_success = false;
221       goto auth_fatal;
222    }
223 
224    /* Verify that we are willing to meet the remote host's requirements */
225    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
226       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
227       Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
228       auth_success = false;
229       goto auth_fatal;
230    }
231 
232    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
233       /* Engage TLS! Full Speed Ahead! */
234       if (!bnet_tls_client(me->tls_ctx, sd, NULL)) {
235          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
236          auth_success = false;
237          goto auth_fatal;
238       }
239       if (me->tls_authenticate) {           /* tls authentication only? */
240          sd->free_tls();                    /* yes, shutdown tls */
241       }
242    }
243    if (sd->recv() <= 0) {
244       auth_success = false;
245       goto auth_fatal;
246    }
247    sscanf(sd->msg, "3000 OK Hello %d", &sd_version);
248    if (sd_version >= 1 && me->comm_compression) {
249       sd->set_compress();
250    } else {
251       sd->clear_compress();
252       Dmsg0(050, "*** No FD compression with SD\n");
253    }
254 
255    /* At this point, we have successfully connected */
256 
257 auth_fatal:
258    /* Destroy session key */
259    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
260    stop_bsock_timer(tid);
261    /* Single thread all failures to avoid DOS */
262    if (!auth_success) {
263       P(mutex);
264       bmicrosleep(6, 0);
265       V(mutex);
266    }
267    return auth_success;
268 }
269