]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/authenticate.c
kes Make sure valid argument passed to str_to_utime() where Arno
[bacula/bacula] / bacula / src / stored / authenticate.c
1 /*
2  * Authenticate caller
3  *
4  *   Kern Sibbald, October 2000
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2006 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 "stored.h"
26
27 static char Dir_sorry[] = "3999 No go\n";
28 static char OK_hello[]  = "3000 OK Hello\n";
29
30
31 /*********************************************************************
32  *
33  *
34  */
35 static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
36 {
37    POOLMEM *dirname;
38    DIRRES *director = NULL;
39    int tls_local_need = BNET_TLS_NONE;
40    int tls_remote_need = BNET_TLS_NONE;
41    int compatible = true;                  /* require md5 compatible DIR */
42    bool auth_success = false;
43    alist *verify_list = NULL;
44
45    if (rcode != R_DIRECTOR) {
46       Dmsg1(50, "I only authenticate Directors, not %d\n", rcode);
47       Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode);
48       return 0;
49    }
50    if (bs->msglen < 25 || bs->msglen > 500) {
51       Dmsg2(50, "Bad Hello command from Director at %s. Len=%d.\n",
52             bs->who, bs->msglen);
53       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s. Len=%d.\n"),
54             bs->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 %127s calling", dirname) != 1) {
61       bs->msg[100] = 0;
62       Dmsg2(50, "Bad Hello command from Director at %s: %s\n",
63             bs->who, bs->msg);
64       Emsg2(M_FATAL, 0, _("Bad Hello command from Director at %s: %s\n"),
65             bs->who, bs->msg);
66       return 0;
67    }
68    director = NULL;
69    unbash_spaces(dirname);
70    foreach_res(director, rcode) {
71       if (strcmp(director->hdr.name, dirname) == 0)
72          break;
73    }
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    /* TLS Requirement */
85    if (director->tls_enable) {
86       if (director->tls_require) {
87          tls_local_need = BNET_TLS_REQUIRED;
88       } else {
89          tls_local_need = BNET_TLS_OK;
90       }
91    }
92
93    if (director->tls_verify_peer) {
94       verify_list = director->tls_allowed_cns;
95    }
96
97    /* Timeout Hello after 10 mins */
98    btimer_t *tid = start_bsock_timer(bs, AUTH_TIMEOUT);
99    auth_success = cram_md5_challenge(bs, director->password, tls_local_need, compatible);
100    if (auth_success) {
101       auth_success = cram_md5_respond(bs, director->password, &tls_remote_need, &compatible);
102       if (!auth_success) {
103          Dmsg1(50, "cram_get_auth failed with %s\n", bs->who);
104       }
105    } else {
106       Dmsg1(50, "cram_auth failed with %s\n", bs->who);
107    }
108
109    if (!auth_success) {
110       Emsg0(M_FATAL, 0, _("Incorrect password given by Director.\n"
111        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"));
112       auth_success = false;
113       goto auth_fatal;
114    }
115
116    /* Verify that the remote host is willing to meet our TLS requirements */
117    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
118       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server did not" 
119            " advertise required TLS support.\n"));
120       auth_success = false;
121       goto auth_fatal;
122    }
123
124    /* Verify that we are willing to meet the remote host's requirements */
125    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
126       Emsg0(M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
127       auth_success = false;
128       goto auth_fatal;
129    }
130
131    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
132       /* Engage TLS! Full Speed Ahead! */
133       if (!bnet_tls_server(director->tls_ctx, bs, verify_list)) {
134          Emsg0(M_FATAL, 0, _("TLS negotiation failed.\n"));
135          auth_success = false;
136          goto auth_fatal;
137       }
138    }
139
140 auth_fatal:
141    stop_bsock_timer(tid);
142    free_pool_memory(dirname);
143    jcr->director = director;
144    return auth_success;
145 }
146
147 /*
148  * Inititiate the message channel with the Director.
149  * He has made a connection to our server.
150  *
151  * Basic tasks done here:
152  *   Assume the Hello message is already in the input
153  *     buffer.  We then authenticate him.
154  *   Get device, media, and pool information from Director
155  *
156  *   This is the channel across which we will send error
157  *     messages and job status information.
158  */
159 int authenticate_director(JCR *jcr)
160 {
161    BSOCK *dir = jcr->dir_bsock;
162
163    if (!authenticate(R_DIRECTOR, dir, jcr)) {
164       bnet_fsend(dir, "%s", Dir_sorry);
165       Dmsg1(50, "Unable to authenticate Director at %s.\n", dir->who);
166       Emsg1(M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who);
167       bmicrosleep(5, 0);
168       return 0;
169    }
170    return bnet_fsend(dir, "%s", OK_hello);
171 }
172
173 int authenticate_filed(JCR *jcr)
174 {
175    BSOCK *fd = jcr->file_bsock;
176    int tls_local_need = BNET_TLS_NONE;
177    int tls_remote_need = BNET_TLS_NONE;
178    int compatible = true;                 /* require md5 compatible FD */
179    bool auth_success = false;
180    alist *verify_list = NULL;
181
182    /* TLS Requirement */
183    if (me->tls_enable) {
184       if (me->tls_require) {
185          tls_local_need = BNET_TLS_REQUIRED;
186       } else {
187          tls_local_need = BNET_TLS_OK;
188       }
189    }
190
191    if (me->tls_verify_peer) {
192       verify_list = me->tls_allowed_cns;
193    }
194
195    /* Timeout Hello after 5 mins */
196    btimer_t *tid = start_bsock_timer(fd, AUTH_TIMEOUT);
197    /* Challenge FD */
198    auth_success = cram_md5_challenge(fd, jcr->sd_auth_key, tls_local_need, compatible);
199    if (auth_success) {
200        /* Respond to his challenge */
201        auth_success = cram_md5_respond(fd, jcr->sd_auth_key, &tls_remote_need, &compatible);
202        if (!auth_success) {
203           Dmsg1(50, "cram-get-auth failed with %s\n", fd->who);
204        }
205    } else {
206       Dmsg1(50, "cram-auth failed with %s\n", fd->who);
207    }
208
209    if (!auth_success) {
210       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
211        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
212            fd->who);
213       auth_success = false;
214       goto auth_fatal;
215    }
216
217    /* Verify that the remote host is willing to meet our TLS requirements */
218    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
219       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server did not" 
220            " advertise required TLS support.\n"));
221       auth_success = false;
222       goto auth_fatal;
223    }
224
225    /* Verify that we are willing to meet the remote host's requirements */
226    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
227       Jmsg(jcr, M_FATAL, 0, _("Authorization problem: Remote server requires TLS.\n"));
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_server(me->tls_ctx, fd, verify_list)) {
235          Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed.\n"));
236          auth_success = false;
237          goto auth_fatal;
238       }
239    }
240
241 auth_fatal:
242    stop_bsock_timer(tid);
243    if (!auth_success) {
244       Jmsg(jcr, M_FATAL, 0, _("Incorrect authorization key from File daemon at %s rejected.\n"
245        "Please see http://www.bacula.org/rel-manual/faq.html#AuthorizationErrors for help.\n"),
246            fd->who);
247    }
248    jcr->authenticated = auth_success;
249    return auth_success;
250 }