2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 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.
22 * Bacula UA authentication. Provides authentication with
25 * Kern Sibbald, June MMI adapted to bat, Jan MMVI
33 * Version at end of Hello
34 * prior to 06Aug13 no version
35 * 1 21Oct13 - added comm line compression
40 /* Commands sent to Director */
41 static char hello[] = "Hello %s calling %d\n";
43 /* Response from Director */
44 static char oldOKhello[] = "1000 OK:";
45 static char newOKhello[] = "1000 OK: %d";
47 /* Forward referenced functions */
50 * Authenticate Director
52 bool DirComm::authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons,
53 char *errmsg, int errmsg_len)
55 BSOCK *dir = jcr->dir_bsock;
56 int tls_local_need = BNET_TLS_NONE;
57 int tls_remote_need = BNET_TLS_NONE;
59 bool tls_authenticate;
60 int compatible = true;
61 char bashed_name[MAX_NAME_LENGTH];
63 TLS_CONTEXT *tls_ctx = NULL;
67 * Send my name to the Director then do authentication
70 bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
71 bash_spaces(bashed_name);
72 password = cons->password;
74 if (cons->tls_enable) {
75 if (cons->tls_require) {
76 tls_local_need = BNET_TLS_REQUIRED;
78 tls_local_need = BNET_TLS_OK;
81 tls_authenticate = cons->tls_authenticate;
82 tls_ctx = cons->tls_ctx;
84 bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
85 password = director->password;
87 if (director->tls_enable) {
88 if (director->tls_require) {
89 tls_local_need = BNET_TLS_REQUIRED;
91 tls_local_need = BNET_TLS_OK;
95 tls_authenticate = director->tls_authenticate;
96 tls_ctx = director->tls_ctx;
98 if (tls_authenticate) {
99 tls_local_need = BNET_TLS_REQUIRED;
102 /* Timeout Hello after 15 secs */
103 dir->start_timer(15);
104 dir->fsend(hello, bashed_name, BAT_VERSION);
106 /* respond to Dir challenge */
107 if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
108 /* Now challenge dir */
109 !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
110 bsnprintf(errmsg, errmsg_len, _("Director authorization problem at \"%s:%d\"\n"),
111 dir->host(), dir->port());
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 bsnprintf(errmsg, errmsg_len, _("Authorization problem:"
118 " Remote server at \"%s:%d\" did not advertise required TLS support.\n"),
119 dir->host(), dir->port());
123 /* Verify that we are willing to meet the remote host's requirements */
124 if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK && tls_remote_need != BNET_TLS_OK) {
125 bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\":"
126 " Remote server requires TLS.\n"),
127 dir->host(), dir->port());
132 /* Is TLS Enabled? */
133 if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
134 /* Engage TLS! Full Speed Ahead! */
135 if (!bnet_tls_client(tls_ctx, dir, NULL)) {
136 bsnprintf(errmsg, errmsg_len, _("TLS negotiation failed with Director at \"%s:%d\"\n"),
137 dir->host(), dir->port());
140 if (tls_authenticate) { /* authenticate only? */
141 dir->free_tls(); /* Yes, shutdown tls */
145 Dmsg1(6, ">dird: %s", dir->msg);
146 if (dir->recv() <= 0) {
148 bsnprintf(errmsg, errmsg_len, _("Bad response to Hello command: ERR=%s\n"
149 "The Director at \"%s:%d\" is probably not running.\n"),
150 dir->bstrerror(), dir->host(), dir->port());
155 Dmsg1(10, "<dird: %s", dir->msg);
156 if (strncmp(dir->msg, oldOKhello, sizeof(oldOKhello)-1) != 0) {
157 bsnprintf(errmsg, errmsg_len, _("Director at \"%s:%d\" rejected Hello command\n"),
158 dir->host(), dir->port());
161 /* If Dir version exists, get it */
162 sscanf(dir->msg, newOKhello, &dir_version);
166 bsnprintf(errmsg, errmsg_len, "%s", dir->msg);
172 bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\"\n"
173 "Most likely the passwords do not agree.\n"
174 "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n"
175 "For help, please see " MANUAL_AUTH_URL "\n"),
176 dir->host(), dir->port());