]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/bcomm/dircomm_auth.cpp
32ac44cff6c0d7921bcf3d7b6a9ad3d3d964a178
[bacula/bacula] / bacula / src / qt-console / bcomm / dircomm_auth.cpp
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2001-2013 Free Software Foundation Europe e.V.
6
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.
9
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.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20
21 /*
22  *
23  *   Bacula UA authentication. Provides authentication with
24  *     the Director.
25  *
26  *     Kern Sibbald, June MMI   adapted to bat, Jan MMVI
27  *
28  */
29
30
31 #include "bat.h"
32
33 /*
34  * Version at end of Hello
35  *   prior to 06Aug13 no version
36  *   1 21Oct13 - added comm line compression
37  */
38 #define BAT_VERSION 1
39
40
41 /* Commands sent to Director */
42 static char hello[]    = "Hello %s calling %d\n";
43
44 /* Response from Director */
45 static char oldOKhello[]   = "1000 OK:";
46 static char newOKhello[]   = "1000 OK: %d";
47
48 /* Forward referenced functions */
49
50 /*
51  * Authenticate Director
52  */
53 bool DirComm::authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons, 
54                 char *errmsg, int errmsg_len) 
55 {
56    BSOCK *dir = jcr->dir_bsock;
57    int tls_local_need = BNET_TLS_NONE;
58    int tls_remote_need = BNET_TLS_NONE;
59    int dir_version = 0;
60    bool tls_authenticate;
61    int compatible = true;
62    char bashed_name[MAX_NAME_LENGTH];
63    char *password;
64    TLS_CONTEXT *tls_ctx = NULL;
65
66    errmsg[0] = 0;
67    /*
68     * Send my name to the Director then do authentication
69     */
70    if (cons) {
71       bstrncpy(bashed_name, cons->hdr.name, sizeof(bashed_name));
72       bash_spaces(bashed_name);
73       password = cons->password;
74       /* TLS Requirement */
75       if (cons->tls_enable) {
76          if (cons->tls_require) {
77             tls_local_need = BNET_TLS_REQUIRED;
78          } else {
79             tls_local_need = BNET_TLS_OK;
80          }
81       }
82       tls_authenticate = cons->tls_authenticate;
83       tls_ctx = cons->tls_ctx;
84    } else {
85       bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
86       password = director->password;
87       /* TLS Requirement */
88       if (director->tls_enable) {
89          if (director->tls_require) {
90             tls_local_need = BNET_TLS_REQUIRED;
91          } else {
92             tls_local_need = BNET_TLS_OK;
93          }
94       }
95
96       tls_authenticate = director->tls_authenticate;
97       tls_ctx = director->tls_ctx;
98    }
99    if (tls_authenticate) {
100       tls_local_need = BNET_TLS_REQUIRED;
101    }
102
103    /* Timeout Hello after 15 secs */
104    dir->start_timer(15);
105    dir->fsend(hello, bashed_name, BAT_VERSION);
106
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());
113       goto bail_out;
114    }
115
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());
121       goto bail_out;
122    }
123
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());
129
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          bsnprintf(errmsg, errmsg_len, _("TLS negotiation failed with Director at \"%s:%d\"\n"),
138             dir->host(), dir->port());
139          goto bail_out;
140       }
141       if (tls_authenticate) {               /* authenticate only? */
142          dir->free_tls();                   /* Yes, shutdown tls */
143       }
144    }
145
146    Dmsg1(6, ">dird: %s", dir->msg);
147    if (dir->recv() <= 0) {
148       dir->stop_timer();
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());
152       return false;
153    }
154
155    dir->stop_timer();
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());
160       return false;
161    } else {
162       /* If Dir version exists, get it */
163       sscanf(dir->msg, newOKhello, &dir_version); 
164    }
165
166    if (m_conn == 0) { 
167       bsnprintf(errmsg, errmsg_len, "%s", dir->msg);
168    }
169    return true;
170
171 bail_out:
172    dir->stop_timer();
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());
178    return false;
179 }