2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
31 * Kern Sibbald, October 2000
41 const int dbglvl = 50;
43 static char Dir_sorry[] = "3999 No go\n";
44 static char OK_hello[] = "3000 OK Hello\n";
47 /*********************************************************************
51 static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
54 DIRRES *director = NULL;
55 int tls_local_need = BNET_TLS_NONE;
56 int tls_remote_need = BNET_TLS_NONE;
57 int compatible = true; /* require md5 compatible DIR */
58 bool auth_success = false;
59 alist *verify_list = NULL;
61 if (rcode != R_DIRECTOR) {
62 Dmsg1(dbglvl, "I only authenticate Directors, not %d\n", rcode);
63 Jmsg1(jcr, M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode);
66 if (bs->msglen < 25 || bs->msglen > 500) {
67 Dmsg2(dbglvl, "Bad Hello command from Director at %s. Len=%d.\n",
68 bs->who(), bs->msglen);
69 Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
70 bs->who(), bs->msglen);
73 dirname = get_pool_memory(PM_MESSAGE);
74 dirname = check_pool_memory_size(dirname, bs->msglen);
76 if (sscanf(bs->msg, "Hello Director %127s calling", dirname) != 1) {
78 Dmsg2(dbglvl, "Bad Hello command from Director at %s: %s\n",
80 Jmsg2(jcr, M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
85 unbash_spaces(dirname);
86 foreach_res(director, rcode) {
87 if (strcmp(director->hdr.name, dirname) == 0)
91 Dmsg2(dbglvl, "Connection from unknown Director %s at %s rejected.\n",
93 Jmsg2(jcr, M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
94 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
96 free_pool_memory(dirname);
100 /* TLS Requirement */
101 if (director->tls_enable) {
102 if (director->tls_require) {
103 tls_local_need = BNET_TLS_REQUIRED;
105 tls_local_need = BNET_TLS_OK;
109 if (director->tls_authenticate) {
110 tls_local_need = BNET_TLS_REQUIRED;
113 if (director->tls_verify_peer) {
114 verify_list = director->tls_allowed_cns;
117 /* Timeout Hello after 10 mins */
118 btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
119 auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
121 auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
123 Dmsg1(dbglvl, "cram_get_auth failed with %s\n", bs->who());
126 Dmsg1(dbglvl, "cram_auth failed with %s\n", bs->who());
130 Jmsg0(jcr, M_FATAL, 0, _("Incorrect password given by Director.\n"
131 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
132 auth_success = false;
136 /* Verify that the remote host is willing to meet our TLS requirements */
137 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
138 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
139 " advertize required TLS support.\n"));
140 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
141 auth_success = false;
145 /* Verify that we are willing to meet the remote host's requirements */
146 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
147 Jmsg0(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
148 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
149 auth_success = false;
153 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
154 /* Engage TLS! Full Speed Ahead! */
155 if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
156 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with DIR at \"%s:%d\"\n"),
157 bs->host(), bs->port());
158 auth_success = false;
161 if (director->tls_authenticate) { /* authenticate with tls only? */
162 bs->free_tls(); /* yes, shut it down */
167 stop_bsock_timer(tid);
168 free_pool_memory(dirname);
169 jcr->director = director;
174 * Inititiate the message channel with the Director.
175 * He has made a connection to our server.
177 * Basic tasks done here:
178 * Assume the Hello message is already in the input
179 * buffer. We then authenticate him.
180 * Get device, media, and pool information from Director
182 * This is the channel across which we will send error
183 * messages and job status information.
185 int authenticate_director(JCR *jcr)
187 BSOCK *dir = jcr->dir_bsock;
189 if (!authenticate(R_DIRECTOR, dir, jcr)) {
190 dir->fsend("%s", Dir_sorry);
191 Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
192 Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
196 return dir->fsend("%s", OK_hello);
199 int authenticate_filed(JCR *jcr)
201 BSOCK *fd = jcr->file_bsock;
202 int tls_local_need = BNET_TLS_NONE;
203 int tls_remote_need = BNET_TLS_NONE;
204 int compatible = true; /* require md5 compatible FD */
205 bool auth_success = false;
206 alist *verify_list = NULL;
208 /* TLS Requirement */
209 if (me->tls_enable) {
210 if (me->tls_require) {
211 tls_local_need = BNET_TLS_REQUIRED;
213 tls_local_need = BNET_TLS_OK;
217 if (me->tls_authenticate) {
218 tls_local_need = BNET_TLS_REQUIRED;
221 if (me->tls_verify_peer) {
222 verify_list = me->tls_allowed_cns;
225 /* Timeout Hello after 5 mins */
226 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
228 auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
230 /* Respond to his challenge */
231 auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
233 Dmsg1(dbglvl, "cram-get-auth failed with %s\n", fd->who());
236 Dmsg1(dbglvl, "cram-auth failed with %s\n", fd->who());
240 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
241 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
243 auth_success = false;
247 /* Verify that the remote host is willing to meet our TLS requirements */
248 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
249 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
250 " advertize required TLS support.\n"));
251 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
252 auth_success = false;
256 /* Verify that we are willing to meet the remote host's requirements */
257 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
258 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
259 Dmsg2(dbglvl, "remote_need=%d local_need=%d\n", tls_remote_need, tls_local_need);
260 auth_success = false;
264 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
265 /* Engage TLS! Full Speed Ahead! */
266 if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
267 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with FD at \"%s:%d\"\n"),
268 fd->host(), fd->port());
269 auth_success = false;
272 if (me->tls_authenticate) { /* tls authenticate only? */
273 fd->free_tls(); /* yes, shut it down */
278 stop_bsock_timer(tid);
280 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
281 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
284 jcr->authenticated = auth_success;