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 Emsg1(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 Emsg2(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 Emsg2(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 Emsg2(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_verify_peer) {
110 verify_list = director->tls_allowed_cns;
113 /* Timeout Hello after 10 mins */
114 btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
115 auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
117 auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
119 Dmsg1(dbglvl, "cram_get_auth failed with %s\n", bs->who());
122 Dmsg1(dbglvl, "cram_auth failed with %s\n", bs->who());
126 Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n"
127 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
128 auth_success = false;
132 /* Verify that the remote host is willing to meet our TLS requirements */
133 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
134 Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not"
135 " advertise required TLS support.\n"));
136 auth_success = false;
140 /* Verify that we are willing to meet the remote host's requirements */
141 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
142 Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
143 auth_success = false;
147 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
148 /* Engage TLS! Full Speed Ahead! */
149 if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
150 Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
151 auth_success = false;
157 stop_bsock_timer(tid);
158 free_pool_memory(dirname);
159 jcr->director = director;
164 * Inititiate the message channel with the Director.
165 * He has made a connection to our server.
167 * Basic tasks done here:
168 * Assume the Hello message is already in the input
169 * buffer. We then authenticate him.
170 * Get device, media, and pool information from Director
172 * This is the channel across which we will send error
173 * messages and job status information.
175 int authenticate_director(JCR *jcr)
177 BSOCK *dir = jcr->dir_bsock;
179 if (!authenticate(R_DIRECTOR, dir, jcr)) {
180 dir->fsend("%s", Dir_sorry);
181 Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who());
182 Emsg1(M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who());
186 return dir->fsend("%s", OK_hello);
189 int authenticate_filed(JCR *jcr)
191 BSOCK *fd = jcr->file_bsock;
192 int tls_local_need = BNET_TLS_NONE;
193 int tls_remote_need = BNET_TLS_NONE;
194 int compatible = true; /* require md5 compatible FD */
195 bool auth_success = false;
196 alist *verify_list = NULL;
198 /* TLS Requirement */
199 if (me->tls_enable) {
200 if (me->tls_require) {
201 tls_local_need = BNET_TLS_REQUIRED;
203 tls_local_need = BNET_TLS_OK;
207 if (me->tls_verify_peer) {
208 verify_list = me->tls_allowed_cns;
211 /* Timeout Hello after 5 mins */
212 btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
214 auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
216 /* Respond to his challenge */
217 auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
219 Dmsg1(dbglvl, "cram-get-auth failed with %s\n", fd->who());
222 Dmsg1(dbglvl, "cram-auth failed with %s\n", fd->who());
226 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
227 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
229 auth_success = false;
233 /* Verify that the remote host is willing to meet our TLS requirements */
234 if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
235 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not"
236 " advertise required TLS support.\n"));
237 auth_success = false;
241 /* Verify that we are willing to meet the remote host's requirements */
242 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
243 Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
244 auth_success = false;
248 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
249 /* Engage TLS! Full Speed Ahead! */
250 if (!bnet_tls_server(me->tls_ctx, fd, verify_list)) {
251 Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
252 auth_success = false;
258 stop_bsock_timer(tid);
260 Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
261 "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
264 jcr->authenticated = auth_success;