]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/console/authenticate.c
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / console / authenticate.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many 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    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *
21  *   Bacula UA authentication. Provides authentication with
22  *     the Director.
23  *
24  *     Kern Sibbald, June MMI
25  *
26  *    This routine runs as a thread and must be thread reentrant.
27  *
28  *  Basic tasks done here:
29  *
30  */
31
32 #include "bacula.h"
33 #include "console_conf.h"
34
35 /*
36  * Version at end of Hello
37  *   prior to 06Aug13 no version
38  *   100  14Feb17 - added comm line compression
39  */
40 #define UA_VERSION 100
41
42 void senditf(const char *fmt, ...);
43 void sendit(const char *buf);
44
45 /* Commands sent to Director */
46 static char hello[]    = "Hello %s calling %d\n";
47
48 /* Response from Director */
49 static char oldOKhello[]   = "1000 OK:";
50 static char newOKhello[]   = "1000 OK: %d";
51 static char FDOKhello[]    = "2000 OK Hello %d";
52
53 /* Forward referenced functions */
54
55 /*
56  * Authenticate Director
57  */
58 int authenticate_director(BSOCK *dir, DIRRES *director, CONRES *cons)
59 {
60    int tls_local_need = BNET_TLS_NONE;
61    int tls_remote_need = BNET_TLS_NONE;
62    bool tls_authenticate;
63    int compatible = true;
64    int dir_version = 0;
65    int fd_version = 0;
66    char bashed_name[MAX_NAME_LENGTH];
67    char *password;
68    TLS_CONTEXT *tls_ctx = NULL;
69             
70    /*
71     * Send my name to the Director then do authentication
72     */
73    if (cons) {
74       bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
75       bash_spaces(bashed_name);
76       password = cons->password;
77       /* TLS Requirement */
78       if (cons->tls_enable) {
79          if (cons->tls_require) {
80             tls_local_need = BNET_TLS_REQUIRED;
81          } else {
82             tls_local_need = BNET_TLS_OK;
83          }
84       }
85       if (cons->tls_authenticate) {
86          tls_local_need = BNET_TLS_REQUIRED;
87       }
88       tls_authenticate = cons->tls_authenticate;
89       tls_ctx = cons->tls_ctx;
90    } else {
91       bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
92       password = director->password;
93       /* TLS Requirement */
94       if (director->tls_enable) {
95          if (director->tls_require) {
96             tls_local_need = BNET_TLS_REQUIRED;
97          } else {
98             tls_local_need = BNET_TLS_OK;
99          }
100       }
101
102       if (director->tls_authenticate) {
103          tls_local_need = BNET_TLS_REQUIRED;
104       }
105       tls_authenticate = director->tls_authenticate;
106       tls_ctx = director->tls_ctx;
107    }
108
109
110    /* Timeout Hello after 15 secs */
111    btimer_t *tid = start_bsock_timer(dir, 15);
112    dir->fsend(hello, bashed_name, UA_VERSION);
113
114    if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
115        !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
116       goto bail_out;
117    }
118
119    /* Verify that the remote host is willing to meet our TLS requirements */
120    if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
121       sendit(_("Authorization problem:"
122              " Remote server did not advertise required TLS support.\n"));
123       goto bail_out;
124    }
125
126    /* Verify that we are willing to meet the remote host's requirements */
127    if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
128       sendit(_("Authorization problem:"
129              " Remote server requires TLS.\n"));
130       goto bail_out;
131    }
132
133    /* Is TLS Enabled? */
134    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
135       /* Engage TLS! Full Speed Ahead! */
136       if (!bnet_tls_client(tls_ctx, dir, NULL)) {
137          sendit(_("TLS negotiation failed\n"));
138          goto bail_out;
139       }
140       if (tls_authenticate) {           /* Authenticate only? */
141          dir->free_tls();               /* yes, shutdown tls */
142       }
143    }
144
145    /*
146     * It's possible that the TLS connection will
147     * be dropped here if an invalid client certificate was presented
148     */
149    Dmsg1(6, ">dird: %s", dir->msg);
150    if (dir->recv() <= 0) {
151       senditf(_("Bad response to Hello command: ERR=%s\n"),
152          dir->bstrerror());
153       goto bail_out;
154    }
155
156    Dmsg1(10, "<dird: %s", dir->msg);
157    if (strncmp(dir->msg, oldOKhello, sizeof(oldOKhello)-1) == 0) {
158       /* If Dir version exists, get it */
159       sscanf(dir->msg, newOKhello, &dir_version);
160       sendit(dir->msg);
161    /* Check for hello from FD */
162    } else if (sscanf(dir->msg, FDOKhello, &fd_version) == 1) {
163       sendit(dir->msg);
164    } else {
165       sendit(_("Director rejected Hello command\n"));
166       goto bail_out;
167    }
168    /* Turn on compression for newer Directors */
169    if (dir_version >= 103 && (!cons || cons->comm_compression)) {
170       dir->set_compress();
171    } else {
172       dir->clear_compress();
173    }
174    /* ***FIXME*** should turn on compression for FD if possible */
175    stop_bsock_timer(tid);
176    return 1;
177
178 bail_out:
179    stop_bsock_timer(tid);
180    sendit( _("Director authorization problem.\n"
181              "Most likely the passwords do not agree.\n"
182              "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n"
183              "For help, please see " MANUAL_AUTH_URL "\n"));
184    return 0;
185 }