2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2001-2013 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
23 * Bacula UA authentication. Provides authentication with
26 * Kern Sibbald, June MMI adapted to bat, Jan MMVI
34 * Version at end of Hello
35 * prior to 06Aug13 no version
36 * 1 21Oct13 - added comm line compression
41 /* Commands sent to Director */
42 static char hello[] = "Hello %s calling %d\n";
44 /* Response from Director */
45 static char oldOKhello[] = "1000 OK:";
46 static char newOKhello[] = "1000 OK: %d";
48 /* Forward referenced functions */
51 * Authenticate Director
53 bool DirComm::authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons,
54 char *errmsg, int errmsg_len)
56 BSOCK *dir = jcr->dir_bsock;
57 int tls_local_need = BNET_TLS_NONE;
58 int tls_remote_need = BNET_TLS_NONE;
60 bool tls_authenticate;
61 int compatible = true;
62 char bashed_name[MAX_NAME_LENGTH];
64 TLS_CONTEXT *tls_ctx = NULL;
68 * Send my name to the Director then do authentication
71 bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
72 bash_spaces(bashed_name);
73 password = cons->password;
75 if (cons->tls_enable) {
76 if (cons->tls_require) {
77 tls_local_need = BNET_TLS_REQUIRED;
79 tls_local_need = BNET_TLS_OK;
82 tls_authenticate = cons->tls_authenticate;
83 tls_ctx = cons->tls_ctx;
85 bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
86 password = director->password;
88 if (director->tls_enable) {
89 if (director->tls_require) {
90 tls_local_need = BNET_TLS_REQUIRED;
92 tls_local_need = BNET_TLS_OK;
96 tls_authenticate = director->tls_authenticate;
97 tls_ctx = director->tls_ctx;
99 if (tls_authenticate) {
100 tls_local_need = BNET_TLS_REQUIRED;
103 /* Timeout Hello after 15 secs */
104 dir->start_timer(15);
105 dir->fsend(hello, bashed_name, BAT_VERSION);
107 /* respond to Dir challenge */
108 if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
109 /* Now challenge dir */
110 !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
111 bsnprintf(errmsg, errmsg_len, _("Director authorization problem at \"%s:%d\"\n"),
112 dir->host(), dir->port());
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 bsnprintf(errmsg, errmsg_len, _("Authorization problem:"
119 " Remote server at \"%s:%d\" did not advertise required TLS support.\n"),
120 dir->host(), dir->port());
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 bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\":"
127 " Remote server requires TLS.\n"),
128 dir->host(), dir->port());
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 bsnprintf(errmsg, errmsg_len, _("TLS negotiation failed with Director at \"%s:%d\"\n"),
138 dir->host(), dir->port());
141 if (tls_authenticate) { /* authenticate only? */
142 dir->free_tls(); /* Yes, shutdown tls */
146 Dmsg1(6, ">dird: %s", dir->msg);
147 if (dir->recv() <= 0) {
149 bsnprintf(errmsg, errmsg_len, _("Bad response to Hello command: ERR=%s\n"
150 "The Director at \"%s:%d\" is probably not running.\n"),
151 dir->bstrerror(), dir->host(), dir->port());
156 Dmsg1(10, "<dird: %s", dir->msg);
157 if (strncmp(dir->msg, oldOKhello, sizeof(oldOKhello)-1) != 0) {
158 bsnprintf(errmsg, errmsg_len, _("Director at \"%s:%d\" rejected Hello command\n"),
159 dir->host(), dir->port());
162 /* If Dir version exists, get it */
163 sscanf(dir->msg, newOKhello, &dir_version);
167 bsnprintf(errmsg, errmsg_len, "%s", dir->msg);
173 bsnprintf(errmsg, errmsg_len, _("Authorization problem with Director at \"%s:%d\"\n"
174 "Most likely the passwords do not agree.\n"
175 "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n"
176 "For help, please see " MANUAL_AUTH_URL "\n"),
177 dir->host(), dir->port());