]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
Apply fix from Martin Simmons to clear structure before
[bacula/bacula] / bacula / src / filed / authenticate.c
1 /*
2  * Authenticate Director who is attempting to connect.
3  *
4  *   Kern Sibbald, October 2000
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2005 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "filed.h"
26
27 static char OK_hello[]  = "2000 OK Hello\n";
28 static char Dir_sorry[] = "2999 No go\n";
29
30
31 /*********************************************************************
32  *
33  */
34 static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
35 {
36    POOLMEM *dirname;
37    DIRRES *director;
38    int tls_local_need = BNET_TLS_NONE;
39    int tls_remote_need = BNET_TLS_NONE;
40    bool auth_success = false;
41    alist *verify_list = NULL;
42
43    if (rcode != R_DIRECTOR) {
44       Dmsg1(50, "I only authenticate directors, not %d\n", rcode);
45       Emsg1(M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode);
46       return 0;
47    }
48    if (bs->msglen < 25 || bs->msglen > 200) {
49       Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n",
50             bs->who, bs->msglen);
51       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
52             bs->who, bs->msglen);
53       return 0;
54    }
55    dirname = get_pool_memory(PM_MESSAGE);
56    dirname = check_pool_memory_size(dirname, bs->msglen);
57
58    if (sscanf(bs->msg, "Hello Director %s calling\n", dirname) != 1) {
59       free_pool_memory(dirname);
60       bs->msg[100] = 0;
61       Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
62             bs->who, bs->msg);
63       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
64             bs->who, bs->msg);
65       return 0;
66    }
67    unbash_spaces(dirname);
68    LockRes();
69    foreach_res(director, R_DIRECTOR) {
70       if (strcmp(director->hdr.name, dirname) == 0)
71          break;
72    }
73    UnlockRes();
74    if (!director) {
75       Dmsg2(50, "Connection from unknown Director %s at %s rejected.\n",
76             dirname, bs->who);
77       Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"
78        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
79             dirname, bs->who);
80       free_pool_memory(dirname);
81       return 0;
82    }
83
84    if (have_tls) {
85       /* TLS Requirement */
86       if (director->tls_enable) {
87          if (director->tls_require) {
88             tls_local_need = BNET_TLS_REQUIRED;
89          } else {
90             tls_local_need = BNET_TLS_OK;
91          }
92       }
93
94       if (director->tls_verify_peer) {
95          verify_list = director->tls_allowed_cns;
96       }
97    }
98
99    btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
100    auth_success = cram_md5_auth(bs, director->password, tls_local_need);
101    if (auth_success) {
102       auth_success = cram_md5_get_auth(bs, director->password, &tls_remote_need);
103       if (!auth_success) {
104          Dmsg1(50, "cram_get_auth failed for %s\n", bs->who);
105       }
106    } else {
107       Dmsg1(50, "cram_auth failed for %s\n", bs->who);
108    }
109    if (!auth_success) {
110       Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"
111        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
112             bs->who);
113       director = NULL;
114       goto auth_fatal;
115    }
116
117    /* Verify that the remote host is willing to meet our TLS requirements */
118    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
119       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not"
120            " advertise required TLS support.\n"));
121       director = NULL;
122       goto auth_fatal;
123    }
124
125    /* Verify that we are willing to meet the remote host's requirements */
126    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
127       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
128       director = NULL;
129       goto auth_fatal;
130    }
131
132    if (have_tls) {
133       if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
134          /* Engage TLS! Full Speed Ahead! */
135          if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
136             Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
137             director = NULL;
138             goto auth_fatal;
139          }
140       }
141    }
142
143 auth_fatal:
144    stop_bsock_timer(tid);
145    free_pool_memory(dirname);
146    jcr->director = director;
147    return (director != NULL);
148 }
149
150 /*
151  * Inititiate the communications with the Director.
152  * He has made a connection to our server.
153  *
154  * Basic tasks done here:
155  *   We read Director's initial message and authorize him.
156  *
157  */
158 int authenticate_director(JCR *jcr)
159 {
160    BSOCK *dir = jcr->dir_bsock;
161
162    if (!authenticate(R_DIRECTOR, dir, jcr)) {
163       bnet_fsend(dir, "%s", Dir_sorry);
164       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
165       bmicrosleep(5, 0);
166       return 0;
167    }
168    return bnet_fsend(dir, "%s", OK_hello);
169 }
170
171 /*
172  * First prove our identity to the Storage daemon, then
173  * make him prove his identity.
174  */
175 int authenticate_storagedaemon(JCR *jcr)
176 {
177    BSOCK *sd = jcr->store_bsock;
178    int tls_local_need = BNET_TLS_NONE;
179    int tls_remote_need = BNET_TLS_NONE;
180    bool auth_success = false;
181
182 #ifdef HAVE_TLS
183    /* TLS Requirement */
184    if (me->tls_enable) {
185       if (me->tls_require) {
186          tls_local_need = BNET_TLS_REQUIRED;
187       } else {
188          tls_local_need = BNET_TLS_OK;
189       }
190    }
191 #endif /* HAVE_TLS */
192
193    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
194    auth_success = cram_md5_get_auth(sd, jcr->sd_auth_key, &tls_remote_need);
195    if (!auth_success) {
196       Dmsg1(50, "cram_get_auth failed for %s\n", sd->who);
197    } else {
198       auth_success = cram_md5_auth(sd, jcr->sd_auth_key, tls_local_need);
199       if (!auth_success) {
200          Dmsg1(50, "cram_auth failed for %s\n", sd->who);
201       }
202    }
203
204    /* Destroy session key */
205    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
206
207    if (!auth_success) {
208       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
209        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
210       goto auth_fatal;
211    }
212
213    /* Verify that the remote host is willing to meet our TLS requirements */
214    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
215       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
216            " advertise required TLS support.\n"));
217       auth_success = false;
218       goto auth_fatal;
219    }
220
221    /* Verify that we are willing to meet the remote host's requirements */
222    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
223       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
224       auth_success = false;
225       goto auth_fatal;
226    }
227
228 #ifdef HAVE_TLS
229    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
230       /* Engage TLS! Full Speed Ahead! */
231       if (!bnet_tls_client(me->tls_ctx, sd)) {
232          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
233          auth_success = false;
234          goto auth_fatal;
235       }
236    }
237 #endif /* HAVE_TLS */
238
239 auth_fatal:
240    stop_bsock_timer(tid);
241    return auth_success;
242 }