2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Bacula UA authentication. Provides authentication with
24 * Kern Sibbald, June MMI
26 * This routine runs as a thread and must be thread reentrant.
28 * Basic tasks done here:
33 #include "console_conf.h"
36 * Version at end of Hello
37 * prior to 06Aug13 no version
38 * 100 14Feb17 - added comm line compression
40 #define UA_VERSION 100
42 void senditf(const char *fmt, ...);
43 void sendit(const char *buf);
45 /* Commands sent to Director */
46 static char hello[] = "Hello %s calling %d\n";
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";
53 /* Forward referenced functions */
56 * Authenticate Director
58 int authenticate_director(BSOCK *dir, DIRRES *director, CONRES *cons)
60 int tls_local_need = BNET_TLS_NONE;
61 int tls_remote_need = BNET_TLS_NONE;
62 bool tls_authenticate;
63 int compatible = true;
66 char bashed_name[MAX_NAME_LENGTH];
68 TLS_CONTEXT *tls_ctx = NULL;
71 * Send my name to the Director then do authentication
74 bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
75 bash_spaces(bashed_name);
76 password = cons->password;
78 if (cons->tls_enable) {
79 if (cons->tls_require) {
80 tls_local_need = BNET_TLS_REQUIRED;
82 tls_local_need = BNET_TLS_OK;
85 if (cons->tls_authenticate) {
86 tls_local_need = BNET_TLS_REQUIRED;
88 tls_authenticate = cons->tls_authenticate;
89 tls_ctx = cons->tls_ctx;
91 bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
92 password = director->password;
94 if (director->tls_enable) {
95 if (director->tls_require) {
96 tls_local_need = BNET_TLS_REQUIRED;
98 tls_local_need = BNET_TLS_OK;
102 if (director->tls_authenticate) {
103 tls_local_need = BNET_TLS_REQUIRED;
105 tls_authenticate = director->tls_authenticate;
106 tls_ctx = director->tls_ctx;
110 /* Timeout Hello after 15 secs */
111 btimer_t *tid = start_bsock_timer(dir, 15);
112 dir->fsend(hello, bashed_name, UA_VERSION);
114 if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
115 !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
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"));
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"));
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"));
140 if (tls_authenticate) { /* Authenticate only? */
141 dir->free_tls(); /* yes, shutdown tls */
146 * It's possible that the TLS connection will
147 * be dropped here if an invalid client certificate was presented
149 Dmsg1(6, ">dird: %s", dir->msg);
150 if (dir->recv() <= 0) {
151 senditf(_("Bad response to Hello command: ERR=%s\n"),
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);
161 /* Check for hello from FD */
162 } else if (sscanf(dir->msg, FDOKhello, &fd_version) == 1) {
165 sendit(_("Director rejected Hello command\n"));
168 /* Turn on compression for newer Directors */
169 if (dir_version >= 103 && (!cons || cons->comm_compression)) {
172 dir->clear_compress();
174 /* ***FIXME*** should turn on compression for FD if possible */
175 stop_bsock_timer(tid);
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"));