]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/authenticate.c
- Integrate the majority of the Mingw cross-tools submission
[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        char addr[64];
52        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
53       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
54              who, bs->msglen);
55       return 0;
56    }
57    dirname = get_pool_memory(PM_MESSAGE);
58    dirname = check_pool_memory_size(dirname, bs->msglen);
59
60    if (sscanf(bs->msg, "Hello Director %s calling\n", dirname) != 1) {
61        char addr[64];
62        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
63       free_pool_memory(dirname);
64       bs->msg[100] = 0;
65       Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
66             bs->who, bs->msg);
67       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
68             who, bs->msg);
69       return 0;
70    }
71    unbash_spaces(dirname);
72    LockRes();
73    foreach_res(director, R_DIRECTOR) {
74       if (strcmp(director->hdr.name, dirname) == 0)
75          break;
76    }
77    UnlockRes();
78    if (!director) {
79        char addr[64];
80        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
81       Emsg2(M_FATAL, 0, _("Connection from unknown Director %s at %s rejected.\n"), 
82             dirname, who);
83       free_pool_memory(dirname);
84       return 0;
85    }
86
87    if (have_tls) {
88       /* TLS Requirement */
89       if (director->tls_enable) {
90          if (director->tls_require) {
91             tls_local_need = BNET_TLS_REQUIRED;
92          } else {
93             tls_local_need = BNET_TLS_OK;
94          }
95       }
96
97       if (director->tls_verify_peer) {
98          verify_list = director->tls_allowed_cns;
99       }
100    }
101
102    btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
103    auth_success = cram_md5_auth(bs, director->password, tls_local_need);  
104    if (auth_success) {
105       auth_success = cram_md5_get_auth(bs, director->password, &tls_remote_need);
106       if (!auth_success) {
107           char addr[64];
108           char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
109           Dmsg1(50, "cram_get_auth failed for %s\n", who);
110       }
111    } else {
112        char addr[64];
113        char *who = bnet_get_peer(bs, addr, sizeof(addr)) ? bs->who : addr;
114        Dmsg1(50, "cram_auth failed for %s\n", who);
115    }
116    if (!auth_success) {
117        Emsg1(M_FATAL, 0, _("Incorrect password given by Director at %s.\n"),
118              bs->who);
119        director = NULL;
120        goto auth_fatal;
121    }
122
123    /* Verify that the remote host is willing to meet our TLS requirements */
124    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
125       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not"
126            " advertise required TLS support.\n"));
127       director = NULL;
128       goto auth_fatal;
129    }
130
131    /* Verify that we are willing to meet the remote host's requirements */
132    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
133       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
134       director = NULL;
135       goto auth_fatal;
136    }
137
138    if (have_tls) {
139       if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
140          /* Engage TLS! Full Speed Ahead! */
141          if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
142             Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
143             director = NULL;
144             goto auth_fatal;
145          }
146       }
147    }
148
149 auth_fatal:
150    stop_bsock_timer(tid);
151    free_pool_memory(dirname);
152    jcr->director = director;
153    return (director != NULL);
154 }
155
156 /*
157  * Inititiate the communications with the Director.
158  * He has made a connection to our server.
159  *
160  * Basic tasks done here:
161  *   We read Director's initial message and authorize him.
162  *
163  */
164 int authenticate_director(JCR *jcr)
165 {
166    BSOCK *dir = jcr->dir_bsock;
167
168    if (!authenticate(R_DIRECTOR, dir, jcr)) {
169       bnet_fsend(dir, "%s", Dir_sorry);
170       Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
171       bmicrosleep(5, 0);
172       return 0;
173    }
174    return bnet_fsend(dir, "%s", OK_hello);
175 }
176
177 /*
178  * First prove our identity to the Storage daemon, then
179  * make him prove his identity.
180  */
181 int authenticate_storagedaemon(JCR *jcr)
182 {
183    BSOCK *sd = jcr->store_bsock;
184    int tls_local_need = BNET_TLS_NONE;
185    int tls_remote_need = BNET_TLS_NONE;
186    bool auth_success = false;
187
188 #ifdef HAVE_TLS
189    /* TLS Requirement */
190    if (me->tls_enable) {
191       if (me->tls_require) {
192          tls_local_need = BNET_TLS_REQUIRED;
193       } else {
194          tls_local_need = BNET_TLS_OK;
195       }
196    }
197 #endif /* HAVE_TLS */
198
199    btimer_t *tid = start_bsock_timer(sd, AUTH_TIMEOUT);
200    auth_success = cram_md5_get_auth(sd, jcr->sd_auth_key, &tls_remote_need);
201    if (!auth_success) {
202       Dmsg1(50, "cram_get_auth failed for %s\n", sd->who);
203    } else {
204       auth_success = cram_md5_auth(sd, jcr->sd_auth_key, tls_local_need);
205       if (!auth_success) {
206          Dmsg1(50, "cram_auth failed for %s\n", sd->who);
207       }
208    }
209
210    /* Destroy session key */
211    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
212
213    if (!auth_success) {
214       Jmsg(jcr, M_FATAL, 0, _("Authorization key rejected by Storage daemon.\n"
215        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
216       goto auth_fatal;
217    }
218
219    /* Verify that the remote host is willing to meet our TLS requirements */
220    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
221       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
222            " advertise required TLS support.\n"));
223       auth_success = false;
224       goto auth_fatal;
225    }
226
227    /* Verify that we are willing to meet the remote host's requirements */
228    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
229       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
230       auth_success = false;
231       goto auth_fatal;
232    }
233
234 #ifdef HAVE_TLS
235    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
236       /* Engage TLS! Full Speed Ahead! */
237       if (!bnet_tls_client(me->tls_ctx, sd)) {
238          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
239          auth_success = false;
240          goto auth_fatal;
241       }
242    }
243 #endif /* HAVE_TLS */
244
245 auth_fatal:
246    stop_bsock_timer(tid);
247    return auth_success;
248 }