Skip to content

Commit

Permalink
Allow for relaxed TLS configuration.
Browse files Browse the repository at this point in the history
Current the verify_peer flag is hardcoded to true for the console
programs. It would be nice if we would allow a somewhat relaxed
TLS mode that allows to establish a TLS connection without the
need for very strict certificate checking which is done now. The
default setting is the same as before but the administrator can
relax this setting by setting the "TLS Verify Peer" option to
false in a definition of the client connection.

This doesn't have severe security implications as the authorization
with challenge response (md5 hashes) is done before the TLS handshake.
So this means you can have the same security as a non TLS connection
but with a relaxed config which means you get a encrypted datastream
even when you haven't put the whole certificate enrollment in place
e.g. CA certificate and potentially client certificates. Protocols
like LDAPS and ESMTP also allow this.

This is also the first version of the GNUTLS code that allows an
TLS encrypted session with the GNUTLS library as a replacement for
the openssl code. This currently is only tested with the relaxed
TLS configuration options set e.g. TLS Verify Peer = no

Fixes #122: Allow for relaxed TLS configuration.
  • Loading branch information
Marco van Wieringen committed May 5, 2013
1 parent dff7954 commit 26ae999
Show file tree
Hide file tree
Showing 15 changed files with 190 additions and 65 deletions.
4 changes: 1 addition & 3 deletions autoconf/configure.in
Expand Up @@ -1127,16 +1127,14 @@ AC_SUBST(OPENSSL_INC)
dnl -----------------------------------------------------------
dnl Check whether GNUTLS is available
dnl -----------------------------------------------------------
with_gnutls_directory=no
AC_ARG_WITH(gnutls,
AC_HELP_STRING([--with-gnutls@<:@=DIR@:>@], [Include GNUTLS support. DIR is the GNUTLS base]),
[
with_gnutls_directory=${withval}
]
)

dnl FIXME: Explictly set GNUTLS to no until we get things working.
with_gnutls_directory=no

dnl See if crypto or tls support is wanted
if test "x$support_crypto" != "xno" -o "x$support_tls" != "xno"; then
dnl When openssl was alread found and enabled use that.
Expand Down
4 changes: 2 additions & 2 deletions src/console/console.c
Expand Up @@ -1173,7 +1173,7 @@ int main(int argc, char *argv[])
tls_pem_callback,
&errmsg,
NULL,
true);
cons->tls_verify_peer);

if (!cons->tls_ctx) {
senditf(_("Failed to initialize TLS context for Console \"%s\".\n"), cons->hdr.name);
Expand Down Expand Up @@ -1206,7 +1206,7 @@ int main(int argc, char *argv[])
tls_pem_callback,
&errmsg,
NULL,
true);
dir->tls_verify_peer);

if (!dir->tls_ctx) {
senditf(_("Failed to initialize TLS context for Director \"%s\".\n"), dir->hdr.name);
Expand Down
2 changes: 2 additions & 0 deletions src/console/console_conf.c
Expand Up @@ -85,6 +85,7 @@ static RES_ITEM cons_items[] = {
{ "tlsauthenticate",store_bool, ITEM(res_cons.tls_authenticate), 0, 0, NULL },
{ "tlsenable", store_bool, ITEM(res_cons.tls_enable), 0, 0, NULL },
{ "tlsrequire", store_bool, ITEM(res_cons.tls_require), 0, 0, NULL },
{ "tlsverifypeer", store_bool, ITEM(res_cons.tls_verify_peer), 0, ITEM_DEFAULT, "true" },
{ "tlscacertificatefile", store_dir, ITEM(res_cons.tls_ca_certfile), 0, 0, NULL },
{ "tlscacertificatedir", store_dir, ITEM(res_cons.tls_ca_certdir), 0, 0, NULL },
{ "tlscertificaterevocationlist", store_dir, ITEM(res_cons.tls_crlfile), 0, 0, NULL },
Expand All @@ -105,6 +106,7 @@ static RES_ITEM dir_items[] = {
{ "tlsauthenticate",store_bool, ITEM(res_dir.tls_enable), 0, 0, NULL },
{ "tlsenable", store_bool, ITEM(res_dir.tls_enable), 0, 0, NULL },
{ "tlsrequire", store_bool, ITEM(res_dir.tls_require), 0, 0, NULL },
{ "tlsverifypeer", store_bool, ITEM(res_dir.tls_verify_peer), 0, ITEM_DEFAULT, "true" },
{ "tlscacertificatefile", store_dir, ITEM(res_dir.tls_ca_certfile), 0, 0, NULL },
{ "tlscacertificatedir", store_dir, ITEM(res_dir.tls_ca_certdir), 0, 0, NULL },
{ "tlscertificaterevocationlist", store_dir, ITEM(res_dir.tls_crlfile), 0, 0, NULL },
Expand Down
2 changes: 2 additions & 0 deletions src/console/console_conf.h
Expand Up @@ -60,6 +60,7 @@ struct CONRES {
bool tls_authenticate; /* Authenticate with TLS */
bool tls_enable; /* Enable TLS on all connections */
bool tls_require; /* Require TLS on all connections */
bool tls_verify_peer; /* TLS Verify Peer Certificate */
char *tls_ca_certfile; /* TLS CA Certificate File */
char *tls_ca_certdir; /* TLS CA Certificate Directory */
char *tls_crlfile; /* TLS CA Certificate Revocation List File */
Expand All @@ -81,6 +82,7 @@ struct DIRRES {
bool tls_authenticate; /* Authenticate with TLS */
bool tls_enable; /* Enable TLS */
bool tls_require; /* Require TLS */
bool tls_verify_peer; /* TLS Verify Peer Certificate */
char *tls_ca_certfile; /* TLS CA Certificate File */
char *tls_ca_certdir; /* TLS CA Certificate Directory */
char *tls_crlfile; /* TLS CA Certificate Revocation List File */
Expand Down
4 changes: 2 additions & 2 deletions src/dird/dird_conf.h
Expand Up @@ -124,7 +124,7 @@ class DIRRES {
bool tls_authenticate; /* Authenticated with TLS */
bool tls_enable; /* Enable TLS */
bool tls_require; /* Require TLS */
bool tls_verify_peer; /* TLS Verify Client Certificate */
bool tls_verify_peer; /* TLS Verify Peer Certificate */
bool optimize_for_size; /* Optimize daemon for minimum memory size */
bool optimize_for_speed; /* Optimize daemon for speed which may need more memory */
bool ndmp_snooping; /* NDMP Protocol specific snooping enabled */
Expand Down Expand Up @@ -210,7 +210,7 @@ class CONRES {
bool tls_authenticate; /* Authenticated with TLS */
bool tls_enable; /* Enable TLS */
bool tls_require; /* Require TLS */
bool tls_verify_peer; /* TLS Verify Client Certificate */
bool tls_verify_peer; /* TLS Verify Peer Certificate */

/* Methods */
char *name() const;
Expand Down
2 changes: 1 addition & 1 deletion src/filed/filed.c
Expand Up @@ -373,7 +373,7 @@ static bool check_resources()
NULL,
NULL,
NULL,
true);
me->tls_verify_peer);

if (!me->tls_ctx) {
Emsg2(M_FATAL, 0, _("Failed to initialize TLS context for File daemon \"%s\" in %s.\n"),
Expand Down
1 change: 1 addition & 0 deletions src/filed/filed_conf.c
Expand Up @@ -111,6 +111,7 @@ static RES_ITEM cli_items[] = {
{ "tlsauthenticate", store_bool, ITEM(res_client.tls_authenticate), 0, 0, NULL },
{ "tlsenable", store_bool, ITEM(res_client.tls_enable), 0, 0, NULL },
{ "tlsrequire", store_bool, ITEM(res_client.tls_require), 0, 0, NULL },
{ "tlsverifypeer", store_bool, ITEM(res_client.tls_verify_peer), 0, ITEM_DEFAULT, "true" },
{ "tlscacertificatefile", store_dir, ITEM(res_client.tls_ca_certfile), 0, 0, NULL },
{ "tlscacertificatedir", store_dir, ITEM(res_client.tls_ca_certdir), 0, 0, NULL },
{ "tlscertificaterevocationlist", store_dir, ITEM(res_client.tls_crlfile), 0, 0, NULL },
Expand Down
3 changes: 2 additions & 1 deletion src/filed/filed_conf.h
Expand Up @@ -63,7 +63,7 @@ struct DIRRES {
bool tls_authenticate; /* Authenticate with TSL */
bool tls_enable; /* Enable TLS */
bool tls_require; /* Require TLS */
bool tls_verify_peer; /* TLS Verify Client Certificate */
bool tls_verify_peer; /* TLS Verify Peer Certificate */
char *tls_ca_certfile; /* TLS CA Certificate File */
char *tls_ca_certdir; /* TLS CA Certificate Directory */
char *tls_crlfile; /* TLS CA Certificate Revocation List File */
Expand Down Expand Up @@ -103,6 +103,7 @@ struct CLIENTRES {
bool tls_authenticate; /* Authenticate with TLS */
bool tls_enable; /* Enable TLS */
bool tls_require; /* Require TLS */
bool tls_verify_peer; /* TLS Verify Peer Certificate */
char *tls_ca_certfile; /* TLS CA Certificate File */
char *tls_ca_certdir; /* TLS CA Certificate Directory */
char *tls_crlfile; /* TLS CA Certificate Revocation List File */
Expand Down
113 changes: 87 additions & 26 deletions src/lib/tls_gnutls.c
Expand Up @@ -141,13 +141,16 @@ TLS_CONTEXT *new_tls_context(const char *ca_certfile,
*/
if (ca_certfile) {
error = gnutls_certificate_set_x509_trust_file(ctx->gnutls_cred,
ca_certfile,
GNUTLS_X509_FMT_PEM);
if (error != GNUTLS_E_SUCCESS) {
ca_certfile,
GNUTLS_X509_FMT_PEM);
if (error < GNUTLS_E_SUCCESS) {
error = gnutls_certificate_set_x509_trust_file(ctx->gnutls_cred,
ca_certfile,
GNUTLS_X509_FMT_DER);
if (error != GNUTLS_E_SUCCESS) {
ca_certfile,
GNUTLS_X509_FMT_DER);
if (error < GNUTLS_E_SUCCESS) {
Jmsg1(NULL, M_ERROR, 0,
_("Error loading CA certificates from %s\n"),
ca_certfile);
goto bail_out;
}
}
Expand All @@ -165,13 +168,16 @@ TLS_CONTEXT *new_tls_context(const char *ca_certfile,
*/
if (crlfile) {
error = gnutls_certificate_set_x509_crl_file(ctx->gnutls_cred,
crlfile,
GNUTLS_X509_FMT_PEM);
if (error != GNUTLS_E_SUCCESS) {
crlfile,
GNUTLS_X509_FMT_PEM);
if (error < GNUTLS_E_SUCCESS) {
error = gnutls_certificate_set_x509_crl_file(ctx->gnutls_cred,
crlfile,
GNUTLS_X509_FMT_DER);
if (error != GNUTLS_E_SUCCESS) {
crlfile,
GNUTLS_X509_FMT_DER);
if (error < GNUTLS_E_SUCCESS) {
Jmsg1(NULL, M_ERROR, 0,
_("Error loading certificate revocation list from %s\n"),
crlfile);
goto bail_out;
}
}
Expand All @@ -191,6 +197,9 @@ TLS_CONTEXT *new_tls_context(const char *ca_certfile,
keyfile,
GNUTLS_X509_FMT_DER);
if (error != GNUTLS_E_SUCCESS) {
Jmsg2(NULL, M_ERROR, 0,
_("Error loading key from %s or certificate from %s\n"),
keyfile, certfile);
goto bail_out;
}
}
Expand All @@ -203,11 +212,16 @@ TLS_CONTEXT *new_tls_context(const char *ca_certfile,

if (dhfile) {
if (!load_dhfile_data(ctx, dhfile)) {
Jmsg1(NULL, M_ERROR, 0,
_("Failed to load DH file %s\n"),
dhfile);
goto bail_out;
}
} else {
error = gnutls_dh_params_generate2(ctx->dh_params, DH_BITS);
if (error != GNUTLS_E_SUCCESS) {
Jmsg0(NULL, M_ERROR, 0,
_("Failed to generate new DH parameters\n"));
goto bail_out;
}
}
Expand Down Expand Up @@ -237,22 +251,37 @@ void free_tls_context(TLS_CONTEXT *ctx)

bool get_tls_require(TLS_CONTEXT *ctx)
{
return ctx->tls_require;
return (ctx) ? ctx->tls_require : false;
}

void set_tls_require(TLS_CONTEXT *ctx, bool value)
{
if (ctx) {
ctx->tls_require = value;
}
}

bool get_tls_enable(TLS_CONTEXT *ctx)
{
return ctx->tls_enable;
return (ctx) ? ctx->tls_enable : false;
}

void set_tls_enable(TLS_CONTEXT *ctx, bool value)
{
if (ctx) {
ctx->tls_enable = value;
}
}

/*
* Certs are not automatically verified during the handshake.
*/
static bool tls_cert_verify(TLS_CONNECTION *tls)
static inline bool tls_cert_verify(TLS_CONNECTION *tls)
{
unsigned int status = 0;
int error;
time_t now = time(NULL);
time_t peertime;

error = gnutls_certificate_verify_peers2(tls->gnutls_state, &status);
if (error != GNUTLS_E_SUCCESS) {
Expand All @@ -269,12 +298,22 @@ static bool tls_cert_verify(TLS_CONNECTION *tls)
return false;
}

if (gnutls_certificate_expiration_time_peers(tls->gnutls_state) < now) {
peertime = gnutls_certificate_expiration_time_peers(tls->gnutls_state);
if (peertime == -1) {
Jmsg0(NULL, M_ERROR, 0, _("gnutls_certificate_expiration_time_peers failed\n"));
return false;
}
if (peertime < now) {
Jmsg0(NULL, M_ERROR, 0, _("peer certificate is expired\n"));
return false;
}

if (gnutls_certificate_activation_time_peers(tls->gnutls_state) > now) {
peertime = gnutls_certificate_activation_time_peers(tls->gnutls_state);
if (peertime == -1) {
Jmsg0(NULL, M_ERROR, 0, _("gnutls_certificate_activation_time_peers failed\n"));
return false;
}
if (peertime > now) {
Jmsg0(NULL, M_ERROR, 0, _("peer certificate not yet active\n"));
return false;
}
Expand All @@ -299,6 +338,13 @@ bool tls_postconnect_verify_cn(JCR *jcr, TLS_CONNECTION *tls, alist *verify_list
gnutls_x509_crt_t cert;
const gnutls_datum_t *peer_cert_list;

/*
* See if we verify the peer certificate.
*/
if (!tls->ctx->verify_peer) {
return true;
}

peer_cert_list = gnutls_certificate_get_peers(tls->gnutls_state, &list_size);
if (!peer_cert_list) {
return false;
Expand Down Expand Up @@ -365,6 +411,13 @@ bool tls_postconnect_verify_host(JCR *jcr, TLS_CONNECTION *tls, const char *host
gnutls_x509_crt_t cert;
const gnutls_datum_t *peer_cert_list;

/*
* See if we verify the peer certificate.
*/
if (!tls->ctx->verify_peer) {
return true;
}

peer_cert_list = gnutls_certificate_get_peers(tls->gnutls_state, &list_size);
if (!peer_cert_list) {
return false;
Expand All @@ -375,7 +428,7 @@ bool tls_postconnect_verify_host(JCR *jcr, TLS_CONNECTION *tls, const char *host
return false;
}

gnutls_x509_crt_import(cert, peer_cert_list, GNUTLS_X509_FMT_DER);
error = gnutls_x509_crt_import(cert, peer_cert_list, GNUTLS_X509_FMT_DER);
if (error != GNUTLS_E_SUCCESS) {
gnutls_x509_crt_deinit(cert);
return false;
Expand All @@ -387,7 +440,6 @@ bool tls_postconnect_verify_host(JCR *jcr, TLS_CONNECTION *tls, const char *host
}

gnutls_x509_crt_deinit(cert);

return true;
}

Expand Down Expand Up @@ -472,9 +524,12 @@ void free_tls_connection(TLS_CONNECTION *tls)

static inline bool gnutls_bsock_session_start(BSOCK *bsock, bool server)
{
TLS_CONNECTION *tls = bsock->tls;
int flags, error;
bool status = true;
bool done = false;
unsigned int list_size;
TLS_CONNECTION *tls = bsock->tls;
const gnutls_datum_t *peer_cert_list;

/* Ensure that socket is non-blocking */
flags = bsock->set_nonblocking();
Expand All @@ -484,12 +539,13 @@ static inline bool gnutls_bsock_session_start(BSOCK *bsock, bool server)
bsock->clear_timed_out();
bsock->set_killable(false);

for (;;) {
while (!done) {
error = gnutls_handshake(tls->gnutls_state);

switch (error) {
case GNUTLS_E_SUCCESS:
status = true;
done = true;
break;
case GNUTLS_E_AGAIN:
case GNUTLS_E_INTERRUPTED:
Expand All @@ -505,19 +561,24 @@ static inline bool gnutls_bsock_session_start(BSOCK *bsock, bool server)
goto cleanup;
}

if (bsock->is_timed_out()) {
goto cleanup;
}

/*
* See if we need to verify the peer.
*/
peer_cert_list = gnutls_certificate_get_peers(tls->gnutls_state, &list_size);
if (!peer_cert_list && !tls->ctx->tls_require) {
goto cleanup;
}

if (tls->ctx->verify_peer) {
if (!tls_cert_verify(tls)) {
status = false;
goto cleanup;
}
}

if (bsock->is_timed_out()) {
goto cleanup;
}
}

cleanup:
Expand Down Expand Up @@ -585,7 +646,7 @@ static inline int gnutls_bsock_readwrite(BSOCK *bsock, char *ptr, int nbytes, bo
}

/* Handle errors */
if (nwritten >= 0) {
if (nwritten > 0) {
nleft -= nwritten;
if (nleft) {
ptr += nwritten;
Expand Down
18 changes: 16 additions & 2 deletions src/lib/tls_nss.c
Expand Up @@ -62,12 +62,26 @@ void free_tls_context(TLS_CONTEXT *ctx)

bool get_tls_require(TLS_CONTEXT *ctx)
{
return ctx->tls_require;
return (ctx) ? ctx->tls_require : false;
}

void set_tls_require(TLS_CONTEXT *ctx, bool value)
{
if (ctx) {
ctx->tls_require = value;
}
}

bool get_tls_enable(TLS_CONTEXT *ctx)
{
return ctx->tls_enable;
return (ctx) ? ctx->tls_enable : false;
}

void set_tls_enable(TLS_CONTEXT *ctx, bool value)
{
if (ctx) {
ctx->tls_enable = value;
}
}

/*
Expand Down

0 comments on commit 26ae999

Please sign in to comment.