]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/console/authenticate.c
Backport from BEE
[bacula/bacula] / bacula / src / console / authenticate.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  *
18  *   Bacula UA authentication. Provides authentication with
19  *     the Director.
20  *
21  *     Kern Sibbald, June MMI
22  *
23  *    This routine runs as a thread and must be thread reentrant.
24  *
25  *  Basic tasks done here:
26  *
27  */
28
29 #include "bacula.h"
30 #include "console_conf.h"
31 #include "jcr.h"
32
33 /*
34  * Version at end of Hello
35  *   prior to 06Aug13 no version
36  */
37 #define UA_VERSION 1
38
39 void senditf(const char *fmt, ...);
40 void sendit(const char *buf);
41
42 /* Commands sent to Director */
43 static char hello[]    = "Hello %s calling %d\n";
44
45 /* Response from Director */
46 static char oldOKhello[]   = "1000 OK:";
47 static char newOKhello[]   = "1000 OK: %d";
48
49 /* Forward referenced functions */
50
51 /*
52  * Authenticate Director
53  */
54 int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons)
55 {
56    BSOCK *dir = jcr->dir_bsock;
57    int tls_local_need = BNET_TLS_NONE;
58    int tls_remote_need = BNET_TLS_NONE;
59    bool tls_authenticate;
60    int compatible = true;
61    int dir_version = 0;
62    char bashed_name[MAX_NAME_LENGTH];
63    char *password;
64    TLS_CONTEXT *tls_ctx = NULL;
65
66    /*
67     * Send my name to the Director then do authentication
68     */
69    if (cons) {
70       bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
71       bash_spaces(bashed_name);
72       password = cons->password;
73       /* TLS Requirement */
74       if (cons->tls_enable) {
75          if (cons->tls_require) {
76             tls_local_need = BNET_TLS_REQUIRED;
77          } else {
78             tls_local_need = BNET_TLS_OK;
79          }
80       }
81       if (cons->tls_authenticate) {
82          tls_local_need = BNET_TLS_REQUIRED;
83       }
84       tls_authenticate = cons->tls_authenticate;
85       tls_ctx = cons->tls_ctx;
86    } else {
87       bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
88       password = director->password;
89       /* TLS Requirement */
90       if (director->tls_enable) {
91          if (director->tls_require) {
92             tls_local_need = BNET_TLS_REQUIRED;
93          } else {
94             tls_local_need = BNET_TLS_OK;
95          }
96       }
97
98       if (director->tls_authenticate) {
99          tls_local_need = BNET_TLS_REQUIRED;
100       }
101       tls_authenticate = director->tls_authenticate;
102       tls_ctx = director->tls_ctx;
103    }
104
105
106    /* Timeout Hello after 15 secs */
107    btimer_t *tid = start_bsock_timer(dir, 15);
108    dir->fsend(hello, bashed_name, UA_VERSION);
109
110    if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
111        !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
112       goto bail_out;
113    }
114
115    /* Verify that the remote host is willing to meet our TLS requirements */
116    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
117       sendit(_("Authorization problem:"
118              " Remote server did not advertise required TLS support.\n"));
119       goto bail_out;
120    }
121
122    /* Verify that we are willing to meet the remote host's requirements */
123    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
124       sendit(_("Authorization problem:"
125              " Remote server requires TLS.\n"));
126       goto bail_out;
127    }
128
129    /* Is TLS Enabled? */
130    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
131       /* Engage TLS! Full Speed Ahead! */
132       if (!bnet_tls_client(tls_ctx, dir, NULL)) {
133          sendit(_("TLS negotiation failed\n"));
134          goto bail_out;
135       }
136       if (tls_authenticate) {           /* Authenticate only? */
137          dir->free_tls();               /* yes, shutdown tls */
138       }
139    }
140
141    /*
142     * It's possible that the TLS connection will
143     * be dropped here if an invalid client certificate was presented
144     */
145    Dmsg1(6, ">dird: %s", dir->msg);
146    if (dir->recv() <= 0) {
147       senditf(_("Bad response to Hello command: ERR=%s\n"),
148          dir->bstrerror());
149       goto bail_out;
150    }
151
152    Dmsg1(10, "<dird: %s", dir->msg);
153    if (strncmp(dir->msg, oldOKhello, sizeof(oldOKhello)-1) != 0) {
154       sendit(_("Director rejected Hello command\n"));
155       goto bail_out;
156    } else {
157       /* If Dir version exists, get it */
158       sscanf(dir->msg, newOKhello, &dir_version);
159       sendit(dir->msg);
160    }
161    stop_bsock_timer(tid);
162    return 1;
163
164 bail_out:
165    stop_bsock_timer(tid);
166    sendit( _("Director authorization problem.\n"
167              "Most likely the passwords do not agree.\n"
168              "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n"
169              "Please see " MANUAL_AUTH_URL " for help.\n"));
170    return 0;
171 }