Skip to content

Commit

Permalink
Major TLS overhaul.
Browse files Browse the repository at this point in the history
- Make tls verify peer checking more consistent.
   - Implement the TLSVerifyPeer keyword in more places.
   - Added TlsAllowedCn keyword in more places.
- Added the possibility to set a TlsCipherList as an
  explicit cipher list to be used for the TLS connection.
  (Format depends on the TLS library used.)

Fixes #371: "TLSVerifyPeer" not available in Client resource
  • Loading branch information
Marco van Wieringen committed Feb 17, 2015
1 parent e6425a1 commit 4bce107
Show file tree
Hide file tree
Showing 26 changed files with 286 additions and 106 deletions.
7 changes: 6 additions & 1 deletion src/console/console.c
Expand Up @@ -1091,6 +1091,7 @@ int main(int argc, char *argv[])
bool export_config = false;
bool export_config_schema = false;
JCR jcr;
alist *verify_list = NULL;
TLS_CONTEXT *tls_ctx = NULL;
POOL_MEM history_file;
utime_t heart_beat;
Expand Down Expand Up @@ -1275,6 +1276,7 @@ int main(int argc, char *argv[])
tls_pem_callback,
&errmsg,
NULL,
cons->tls_cipherlist,
cons->tls_verify_peer);

if (!cons->tls_ctx) {
Expand Down Expand Up @@ -1308,6 +1310,7 @@ int main(int argc, char *argv[])
tls_pem_callback,
&errmsg,
NULL,
dir->tls_cipherlist,
dir->tls_verify_peer);

if (!dir->tls_ctx) {
Expand Down Expand Up @@ -1344,14 +1347,16 @@ int main(int argc, char *argv[])
ASSERT(cons->password.encoding == p_encoding_md5);
password = cons->password.value;
tls_ctx = cons->tls_ctx;
verify_list = cons->tls_allowed_cns;
} else {
name = "*UserAgent*";
ASSERT(dir->password.encoding == p_encoding_md5);
password = dir->password.value;
tls_ctx = dir->tls_ctx;
verify_list = dir->tls_allowed_cns;
}

if (!UA_sock->authenticate_with_director(name, password, tls_ctx, errmsg, errmsg_len)) {
if (!UA_sock->authenticate_with_director(name, password, tls_ctx, verify_list, errmsg, errmsg_len)) {
sendit(errmsg);
terminate_console(0);
return 1;
Expand Down
16 changes: 16 additions & 0 deletions src/console/console_conf.c
Expand Up @@ -85,6 +85,8 @@ static RES_ITEM cons_items[] = {
{ "TlsCertificateRevocationList", CFG_TYPE_DIR, ITEM(res_cons.tls_crlfile), 0, 0, NULL, NULL, NULL },
{ "TlsCertificate", CFG_TYPE_DIR, ITEM(res_cons.tls_certfile), 0, 0, NULL, NULL, NULL },
{ "TlsKey", CFG_TYPE_DIR, ITEM(res_cons.tls_keyfile), 0, 0, NULL, NULL, NULL },
{ "TlsCipherList", CFG_TYPE_STR, ITEM(res_cons.tls_cipherlist), 0, 0, NULL, NULL, NULL },
{ "TlsAllowedCn", CFG_TYPE_ALIST_STR, ITEM(res_cons.tls_allowed_cns), 0, 0, NULL, NULL, NULL },
{ "Director", CFG_TYPE_STR, ITEM(res_cons.director), 0, 0, NULL, NULL, NULL },
{ "HeartbeatInterval", CFG_TYPE_TIME, ITEM(res_cons.heartbeat_interval), 0, CFG_ITEM_DEFAULT, "0", NULL, NULL },
{ NULL, 0, { 0 }, 0, 0, NULL, NULL, NULL }
Expand All @@ -106,6 +108,8 @@ static RES_ITEM dir_items[] = {
{ "TlsCertificateRevocationList", CFG_TYPE_DIR, ITEM(res_dir.tls_crlfile), 0, 0, NULL, NULL, NULL },
{ "TlsCertificate", CFG_TYPE_DIR, ITEM(res_dir.tls_certfile), 0, 0, NULL, NULL, NULL },
{ "TlsKey", CFG_TYPE_DIR, ITEM(res_dir.tls_keyfile), 0, 0, NULL, NULL, NULL },
{ "TlsCipherList", CFG_TYPE_STR, ITEM(res_dir.tls_cipherlist), 0, 0, NULL, NULL, NULL },
{ "TlsAllowedCn", CFG_TYPE_ALIST_STR, ITEM(res_dir.tls_allowed_cns), 0, 0, NULL, NULL, NULL },
{ "HeartbeatInterval", CFG_TYPE_TIME, ITEM(res_dir.heartbeat_interval), 0, CFG_ITEM_DEFAULT, "0", NULL, NULL },
{ NULL, 0, { 0 }, 0, 0, NULL, NULL, NULL }
};
Expand Down Expand Up @@ -204,6 +208,12 @@ void free_resource(RES *sres, int type)
if (res->res_cons.tls_keyfile) {
free(res->res_cons.tls_keyfile);
}
if (res->res_cons.tls_cipherlist) {
free(res->res_cons.tls_cipherlist);
}
if (res->res_cons.tls_allowed_cns) {
delete res->res_cons.tls_allowed_cns;
}
break;
case R_DIRECTOR:
if (res->res_dir.address) {
Expand All @@ -227,6 +237,12 @@ void free_resource(RES *sres, int type)
if (res->res_dir.tls_keyfile) {
free(res->res_dir.tls_keyfile);
}
if (res->res_dir.tls_cipherlist) {
free(res->res_dir.tls_cipherlist);
}
if (res->res_dir.tls_allowed_cns) {
delete res->res_dir.tls_allowed_cns;
}
break;
default:
printf(_("Unknown resource type %d\n"), type);
Expand Down
4 changes: 4 additions & 0 deletions src/console/console_conf.h
Expand Up @@ -67,6 +67,8 @@ struct CONRES {
char *tls_crlfile; /* TLS CA Certificate Revocation List File */
char *tls_certfile; /* TLS Client Certificate File */
char *tls_keyfile; /* TLS Client Key File */
char *tls_cipherlist; /* TLS Cipher List */
alist *tls_allowed_cns; /* TLS Allowed Common Names */
char *director; /* bind to director */
utime_t heartbeat_interval; /* Interval to send heartbeats to Dir */

Expand All @@ -89,6 +91,8 @@ struct DIRRES {
char *tls_crlfile; /* TLS CA Certificate Revocation List File */
char *tls_certfile; /* TLS Client Certificate File */
char *tls_keyfile; /* TLS Client Key File */
char *tls_cipherlist; /* TLS Cipher List */
alist *tls_allowed_cns; /* TLS Allowed Common Names */
utime_t heartbeat_interval; /* Interval to send heartbeats to Dir */

TLS_CONTEXT *tls_ctx; /* Shared TLS Context */
Expand Down
20 changes: 13 additions & 7 deletions src/dird/authenticate.c
Expand Up @@ -64,7 +64,8 @@ static char Dir_sorry[] =
*/
static inline bool two_way_authenticate(BSOCK *bs, JCR *jcr, const char *passwd, bool initiate,
bool tls_enable, bool tls_require, bool tls_authenticate,
alist *verify_list, TLS_CONTEXT *tls_ctx, const char *what)
bool tls_verify_peer, alist *verify_list,
TLS_CONTEXT *tls_ctx, const char *what)
{
int tls_local_need = BNET_TLS_NONE;
int tls_remote_need = BNET_TLS_NONE;
Expand Down Expand Up @@ -180,7 +181,7 @@ static inline bool two_way_authenticate(BSOCK *bs, JCR *jcr, const char *passwd,
goto auth_fatal;
}
} else {
if (!bnet_tls_client(tls_ctx, bs, verify_list)) {
if (!bnet_tls_client(tls_ctx, bs, tls_verify_peer, verify_list)) {
if (jcr) {
Jmsg(jcr, M_FATAL, 0, _("TLS negotiation failed with %s at \"%s:%d\"\n"),
what, bs->host(), bs->port());
Expand Down Expand Up @@ -231,7 +232,7 @@ bool authenticate_with_storage_daemon(JCR *jcr, STORERES *store)
ASSERT(store->password.encoding == p_encoding_md5);
auth_success = two_way_authenticate(sd, jcr, store->password.value, false,
store->tls_enable, store->tls_require, store->tls_authenticate,
NULL, store->tls_ctx, "Storage daemon");
store->tls_verify_peer, NULL, store->tls_ctx, "Storage daemon");
if (!auth_success) {
Dmsg0(dbglvl, _("Director and Storage daemon passwords or names not the same.\n"));
Jmsg(jcr, M_FATAL, 0,
Expand Down Expand Up @@ -271,6 +272,7 @@ bool authenticate_with_file_daemon(JCR *jcr)
CLIENTRES *client = jcr->res.client;
char dirname[MAX_NAME_LENGTH];
bool auth_success = false;
alist *verify_list = NULL;

/*
* Send my name to the File daemon then do authentication
Expand All @@ -285,10 +287,14 @@ bool authenticate_with_file_daemon(JCR *jcr)
}
Dmsg1(dbglvl, "Sent: %s", fd->msg);

if (client->tls_verify_peer) {
verify_list = client->tls_allowed_cns;
}

ASSERT(client->password.encoding == p_encoding_md5);
auth_success = two_way_authenticate(fd, jcr, client->password.value, false,
client->tls_enable, client->tls_require, client->tls_authenticate,
client->tls_allowed_cns, client->tls_ctx, "File daemon");
client->tls_verify_peer, verify_list, client->tls_ctx, "File daemon");
if (!auth_success) {
Dmsg0(dbglvl, _("Director and File daemon passwords or names not the same.\n"));
Jmsg(jcr, M_FATAL, 0,
Expand Down Expand Up @@ -339,7 +345,7 @@ bool authenticate_file_daemon(JCR *jcr, char *client_name)
ASSERT(client->password.encoding == p_encoding_md5);
auth_success = two_way_authenticate(fd, NULL, client->password.value, true,
client->tls_enable, client->tls_require, client->tls_authenticate,
client->tls_allowed_cns, client->tls_ctx, "File daemon");
client->tls_verify_peer, client->tls_allowed_cns, client->tls_ctx, "File daemon");
}
}

Expand Down Expand Up @@ -404,15 +410,15 @@ bool authenticate_user_agent(UAContext *uac)
ASSERT(me->password.encoding == p_encoding_md5);
auth_success = two_way_authenticate(ua, NULL, me->password.value, true,
me->tls_enable, me->tls_require, me->tls_authenticate,
(me->tls_verify_peer) ? me->tls_allowed_cns : NULL, me->tls_ctx, "Console");
me->tls_verify_peer, me->tls_allowed_cns, me->tls_ctx, "Console");
} else {
unbash_spaces(name);
cons = (CONRES *)GetResWithName(R_CONSOLE, name);
if (cons) {
ASSERT(cons->password.encoding == p_encoding_md5);
auth_success = two_way_authenticate(ua, NULL, cons->password.value, true,
cons->tls_enable, cons->tls_require, cons->tls_authenticate,
(cons->tls_verify_peer) ? cons->tls_allowed_cns : NULL, cons->tls_ctx, "Console");
cons->tls_verify_peer, cons->tls_allowed_cns, cons->tls_ctx, "Console");

if (auth_success) {
uac->cons = cons; /* save console resource pointer */
Expand Down
65 changes: 42 additions & 23 deletions src/dird/dird.c
Expand Up @@ -749,14 +749,18 @@ static bool check_resources()
*/
if (OK && (need_tls || me->tls_require)) {
/*
* Initialize TLS context:
* Args: CA certfile, CA certdir, Certfile, Keyfile,
* Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer
* Initialize TLS context.
*/
me->tls_ctx = new_tls_context(me->tls_ca_certfile,
me->tls_ca_certdir, me->tls_crlfile, me->tls_certfile,
me->tls_keyfile, NULL, NULL, me->tls_dhfile,
me->tls_verify_peer);
me->tls_ca_certdir,
me->tls_crlfile,
me->tls_certfile,
me->tls_keyfile,
NULL,
NULL,
me->tls_dhfile,
me->tls_cipherlist,
me->tls_verify_peer);

if (!me->tls_ctx) {
Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Director \"%s\" in %s.\n"),
Expand Down Expand Up @@ -828,14 +832,18 @@ static bool check_resources()
*/
if (OK && (need_tls || cons->tls_require)) {
/*
* Initialize TLS context:
* Args: CA certfile, CA certdir, Certfile, Keyfile,
* Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer
* Initialize TLS context.
*/
cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
cons->tls_ca_certdir, cons->tls_crlfile, cons->tls_certfile,
cons->tls_keyfile, NULL, NULL,
cons->tls_dhfile, cons->tls_verify_peer);
cons->tls_ca_certdir,
cons->tls_crlfile,
cons->tls_certfile,
cons->tls_keyfile,
NULL,
NULL,
cons->tls_dhfile,
cons->tls_cipherlist,
cons->tls_verify_peer);
if (!cons->tls_ctx) {
Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
cons->name(), configfile);
Expand Down Expand Up @@ -885,14 +893,19 @@ static bool check_resources()
*/
if (OK && (need_tls || client->tls_require)) {
/*
* Initialize TLS context:
* Args: CA certfile, CA certdir, Certfile, Keyfile,
* Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer
* Initialize TLS context.
*/
client->tls_ctx = new_tls_context(client->tls_ca_certfile,
client->tls_ca_certdir, client->tls_crlfile, client->tls_certfile,
client->tls_keyfile, NULL, NULL, NULL,
true);
client->tls_ca_certdir,
client->tls_crlfile,
client->tls_certfile,
client->tls_keyfile,
NULL,
NULL,
NULL,
client->tls_cipherlist,
client->tls_verify_peer);

if (!client->tls_ctx) {
Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
client->name(), configfile);
Expand Down Expand Up @@ -935,13 +948,19 @@ static bool check_resources()
*/
if (OK && (need_tls || store->tls_require)) {
/*
* Initialize TLS context:
* Args: CA certfile, CA certdir, Certfile, Keyfile,
* Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer
* Initialize TLS context.
*/
store->tls_ctx = new_tls_context(store->tls_ca_certfile,
store->tls_ca_certdir, store->tls_crlfile, store->tls_certfile,
store->tls_keyfile, NULL, NULL, NULL, true);
store->tls_ca_certdir,
store->tls_crlfile,
store->tls_certfile,
store->tls_keyfile,
NULL,
NULL,
NULL,
store->tls_cipherlist,
store->tls_verify_peer);

if (!store->tls_ctx) {
Jmsg(NULL, M_FATAL, 0, _("Failed to initialize TLS context for Storage \"%s\" in %s.\n"),
store->name(), configfile);
Expand Down

0 comments on commit 4bce107

Please sign in to comment.