]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/console/authenticate.c
Update year to 2016
[bacula/bacula] / bacula / src / console / authenticate.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 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  */
39 #define UA_VERSION 100
40
41 void senditf(const char *fmt, ...);
42 void sendit(const char *buf);
43
44 /* Commands sent to Director */
45 static char hello[]    = "Hello %s calling %d\n";
46
47 /* Response from Director */
48 static char oldOKhello[]   = "1000 OK:";
49 static char newOKhello[]   = "1000 OK: %d";
50
51 /* Forward referenced functions */
52
53 /*
54  * Authenticate Director
55  */
56 int authenticate_director(BSOCK *dir, DIRRES *director, CONRES *cons)
57 {
58    int tls_local_need = BNET_TLS_NONE;
59    int tls_remote_need = BNET_TLS_NONE;
60    bool tls_authenticate;
61    int compatible = true;
62    int dir_version = 0;
63    char bashed_name[MAX_NAME_LENGTH];
64    char *password;
65    TLS_CONTEXT *tls_ctx = NULL;
66
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       if (cons->tls_authenticate) {
83          tls_local_need = BNET_TLS_REQUIRED;
84       }
85       tls_authenticate = cons->tls_authenticate;
86       tls_ctx = cons->tls_ctx;
87    } else {
88       bstrncpy(bashed_name, "*UserAgent*", sizeof(bashed_name));
89       password = director->password;
90       /* TLS Requirement */
91       if (director->tls_enable) {
92          if (director->tls_require) {
93             tls_local_need = BNET_TLS_REQUIRED;
94          } else {
95             tls_local_need = BNET_TLS_OK;
96          }
97       }
98
99       if (director->tls_authenticate) {
100          tls_local_need = BNET_TLS_REQUIRED;
101       }
102       tls_authenticate = director->tls_authenticate;
103       tls_ctx = director->tls_ctx;
104    }
105
106
107    /* Timeout Hello after 15 secs */
108    btimer_t *tid = start_bsock_timer(dir, 15);
109    dir->fsend(hello, bashed_name, UA_VERSION);
110
111    if (!cram_md5_respond(dir, password, &tls_remote_need, &compatible) ||
112        !cram_md5_challenge(dir, password, tls_local_need, compatible)) {
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       sendit(_("Authorization problem:"
119              " Remote server did not advertise required TLS support.\n"));
120       goto bail_out;
121    }
122
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       sendit(_("Authorization problem:"
126              " Remote server requires TLS.\n"));
127       goto bail_out;
128    }
129
130    /* Is TLS Enabled? */
131    if (tls_local_need >= BNET_TLS_OK && tls_remote_need >= BNET_TLS_OK) {
132       /* Engage TLS! Full Speed Ahead! */
133       if (!bnet_tls_client(tls_ctx, dir, NULL)) {
134          sendit(_("TLS negotiation failed\n"));
135          goto bail_out;
136       }
137       if (tls_authenticate) {           /* Authenticate only? */
138          dir->free_tls();               /* yes, shutdown tls */
139       }
140    }
141
142    /*
143     * It's possible that the TLS connection will
144     * be dropped here if an invalid client certificate was presented
145     */
146    Dmsg1(6, ">dird: %s", dir->msg);
147    if (dir->recv() <= 0) {
148       senditf(_("Bad response to Hello command: ERR=%s\n"),
149          dir->bstrerror());
150       goto bail_out;
151    }
152
153    Dmsg1(10, "<dird: %s", dir->msg);
154    if (strncmp(dir->msg, oldOKhello, sizeof(oldOKhello)-1) != 0) {
155       sendit(_("Director rejected Hello command\n"));
156       goto bail_out;
157    } else {
158       /* If Dir version exists, get it */
159       sscanf(dir->msg, newOKhello, &dir_version);
160       sendit(dir->msg);
161    }
162    stop_bsock_timer(tid);
163    return 1;
164
165 bail_out:
166    stop_bsock_timer(tid);
167    sendit( _("Director authorization problem.\n"
168              "Most likely the passwords do not agree.\n"
169              "If you are using TLS, there may have been a certificate validation error during the TLS handshake.\n"
170              "For help, please see " MANUAL_AUTH_URL "\n"));
171    return 0;
172 }