# HG changeset patch # User Sebastien Decugis # Date 1369714287 -28800 # Node ID d00b5914351e83fa90b2ea09f8c51cd82b312157 # Parent 0b95a3afbfc378255628add563a4bb40157b9a90 Allow running freeDiameter without TLS credentials if the following conditions are verified: - The Secure Diameter port is disabled (SecPort = 0;) - The old TLS mechanism is not used (TLS_old_method; not defined) Note that in this context only connections to peers explicitely authorized for 'No_TLS' are permitted. diff -r 0b95a3afbfc3 -r d00b5914351e include/freeDiameter/libfdcore.h --- a/include/freeDiameter/libfdcore.h Mon May 27 17:22:40 2013 +0800 +++ b/include/freeDiameter/libfdcore.h Tue May 28 12:11:27 2013 +0800 @@ -150,6 +150,8 @@ } cnf_flags; struct { + int tls_disabled; + /* Credentials parameters (backup) */ char * cert_file; char * key_file; diff -r 0b95a3afbfc3 -r d00b5914351e libfdcore/config.c --- a/libfdcore/config.c Mon May 27 17:22:40 2013 +0800 +++ b/libfdcore/config.c Tue May 28 12:11:27 2013 +0800 @@ -251,7 +251,7 @@ } if (fddin == NULL) { int ret = errno; - TRACE_ERROR("Unable to open configuration file for reading; tried the following locations: %s%s%s; Error: %s", + LOG_F("Unable to open configuration file for reading; tried the following locations: %s%s%s; Error: %s", orig ?: "", orig? " and " : "", fd_g_config->cnf_file, strerror(ret)); return ret; } @@ -265,12 +265,18 @@ /* Check that TLS private key was given */ if (! fd_g_config->cnf_sec_data.key_file) { - TRACE_ERROR( "Missing private key configuration for TLS. Please provide the TLS_cred configuration directive."); - return EINVAL; + /* If TLS is not enabled, we allow empty TLS configuration */ + if ((fd_g_config->cnf_port_tls == 0) && (fd_g_config->cnf_flags.tls_alg == 0)) { + LOG_N("TLS is disabled, this is *NOT* a recommended practice! Diameter protocol conveys highly sensitive information on your users."); + fd_g_config->cnf_sec_data.tls_disabled = 1; + } else { + LOG_F( "Missing private key configuration for TLS. Please provide the TLS_cred configuration directive."); + return EINVAL; + } } /* If the CA is not provided, let's use the same file (assuming self-signed certificate) */ - if (! fd_g_config->cnf_sec_data.ca_file) { + if ((!fd_g_config->cnf_sec_data.tls_disabled) && (!fd_g_config->cnf_sec_data.ca_file)) { CHECK_MALLOC( fd_g_config->cnf_sec_data.ca_file = strdup(fd_g_config->cnf_sec_data.cert_file) ); CHECK_GNUTLS_DO( fd_g_config->cnf_sec_data.ca_file_nr += gnutls_certificate_set_x509_trust_file( fd_g_config->cnf_sec_data.credentials, @@ -357,7 +363,7 @@ } /* Configure TLS default parameters */ - if (! fd_g_config->cnf_sec_data.prio_string) { + if ((!fd_g_config->cnf_sec_data.tls_disabled) && (!fd_g_config->cnf_sec_data.prio_string)) { const char * err_pos = NULL; CHECK_GNUTLS_DO( gnutls_priority_init( &fd_g_config->cnf_sec_data.prio_cache, @@ -367,7 +373,7 @@ } /* Verify that our certificate is valid -- otherwise remote peers will reject it */ - { + if (!fd_g_config->cnf_sec_data.tls_disabled) { int ret = 0, i; gnutls_datum_t certfile; @@ -534,65 +540,68 @@ GNUTLS_TRACE( gnutls_x509_crt_deinit (certs[i]) ); } free(certs); + + #ifdef GNUTLS_VERSION_300 + /* Use certificate verification during the handshake */ + gnutls_certificate_set_verify_function (fd_g_config->cnf_sec_data.credentials, fd_tls_verify_credentials_2); + #endif /* GNUTLS_VERSION_300 */ + } - /* gnutls_certificate_set_verify_limits -- so far the default values are fine... */ - #ifdef GNUTLS_VERSION_300 - /* Use certificate verification during the handshake */ - gnutls_certificate_set_verify_function (fd_g_config->cnf_sec_data.credentials, fd_tls_verify_credentials_2); - #endif /* GNUTLS_VERSION_300 */ - /* DH */ - if (fd_g_config->cnf_sec_data.dh_file) { - gnutls_datum_t dhparams = { NULL, 0 }; - size_t alloc = 0; - FILE *stream = fopen (fd_g_config->cnf_sec_data.dh_file, "rb"); - if (!stream) { - int err = errno; - TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s", fd_g_config->cnf_sec_data.dh_file, strerror(err)); - return err; - } - do { - uint8_t * realloced = NULL; - size_t read = 0; - - if (alloc < dhparams.size + BUFSIZ + 1) { - alloc += alloc / 2 + BUFSIZ + 1; - CHECK_MALLOC_DO( realloced = realloc(dhparams.data, alloc), - { - free(dhparams.data); - return ENOMEM; - } ) - dhparams.data = realloced; - } - - read = fread( dhparams.data + dhparams.size, 1, alloc - dhparams.size - 1, stream ); - dhparams.size += read; - - if (ferror(stream)) { + if (!fd_g_config->cnf_sec_data.tls_disabled) { + if (fd_g_config->cnf_sec_data.dh_file) { + gnutls_datum_t dhparams = { NULL, 0 }; + size_t alloc = 0; + FILE *stream = fopen (fd_g_config->cnf_sec_data.dh_file, "rb"); + if (!stream) { int err = errno; - TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s", fd_g_config->cnf_sec_data.dh_file, strerror(err)); + TRACE_DEBUG(INFO, "An error occurred while opening '%s': %s", fd_g_config->cnf_sec_data.dh_file, strerror(err)); return err; } - } while (!feof(stream)); - dhparams.data[dhparams.size] = '\0'; - fclose(stream); - CHECK_GNUTLS_DO( gnutls_dh_params_import_pkcs3( - fd_g_config->cnf_sec_data.dh_cache, - &dhparams, - GNUTLS_X509_FMT_PEM), - { TRACE_ERROR("Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } ); - free(dhparams.data); - - } else { - LOG_D( "Generating fresh Diffie-Hellman parameters of size %d (this takes some time)... ", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); - CHECK_GNUTLS_DO( gnutls_dh_params_generate2( - fd_g_config->cnf_sec_data.dh_cache, - fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS), - { TRACE_ERROR("Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } ); - } + do { + uint8_t * realloced = NULL; + size_t read = 0; + + if (alloc < dhparams.size + BUFSIZ + 1) { + alloc += alloc / 2 + BUFSIZ + 1; + CHECK_MALLOC_DO( realloced = realloc(dhparams.data, alloc), + { + free(dhparams.data); + return ENOMEM; + } ) + dhparams.data = realloced; + } + + read = fread( dhparams.data + dhparams.size, 1, alloc - dhparams.size - 1, stream ); + dhparams.size += read; + + if (ferror(stream)) { + int err = errno; + TRACE_DEBUG(INFO, "An error occurred while reading '%s': %s", fd_g_config->cnf_sec_data.dh_file, strerror(err)); + return err; + } + } while (!feof(stream)); + dhparams.data[dhparams.size] = '\0'; + fclose(stream); + CHECK_GNUTLS_DO( gnutls_dh_params_import_pkcs3( + fd_g_config->cnf_sec_data.dh_cache, + &dhparams, + GNUTLS_X509_FMT_PEM), + { TRACE_ERROR("Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } ); + free(dhparams.data); + + } else { + LOG_D( "Generating fresh Diffie-Hellman parameters of size %d (this takes some time)... ", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); + CHECK_GNUTLS_DO( gnutls_dh_params_generate2( + fd_g_config->cnf_sec_data.dh_cache, + fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS), + { TRACE_ERROR("Error in DH bits value : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); return EINVAL; } ); + } + + } return 0; } diff -r 0b95a3afbfc3 -r d00b5914351e libfdcore/p_ce.c --- a/libfdcore/p_ce.c Mon May 27 17:22:40 2013 +0800 +++ b/libfdcore/p_ce.c Tue May 28 12:11:27 2013 +0800 @@ -595,7 +595,14 @@ /* Do we need Inband-Security-Id AVPs ? If we're already using TLS, we don't... */ if (!fd_cnx_getTLS(cnx)) { isi_none = peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE; /* we add it even if the peer does not use the old mechanism, it is impossible to distinguish */ - isi_tls = peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD; + + if (peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD) { + if (fd_g_config->cnf_sec_data.tls_disabled) { + LOG_N("TLS disabled locally, so Inband-Security-Id (TLS) not included for peer %s", peer->p_hdr.info.pi_diamid); + } else { + isi_tls = 1; + } + } } /* Add the information about the local peer */ @@ -770,8 +777,13 @@ /* Ok for clear connection */ TRACE_DEBUG(INFO, "No TLS protection negotiated with peer '%s'.", peer->p_hdr.info.pi_diamid); CHECK_FCT( fd_cnx_start_clear(peer->p_cnxctx, 1) ); + + } else if (fd_g_config->cnf_sec_data.tls_disabled) { + LOG_E("Clear connection with remote peer '%s' is not (explicitly) allowed, and TLS is disabled. Giving up...", peer->p_hdr.info.pi_diamid); + fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS is disabled and peer is not configured for IPsec", NULL); + goto cleanup; + } else { - fd_psm_change_state(peer, STATE_OPEN_HANDSHAKE); CHECK_FCT_DO( fd_cnx_handshake(peer->p_cnxctx, GNUTLS_CLIENT, peer->p_hdr.info.config.pic_priority, NULL), { @@ -899,6 +911,9 @@ if ((peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE) && (peer->p_hdr.info.runtime.pir_isi & PI_SEC_NONE)) { /* We have allowed IPsec */ isi = PI_SEC_NONE; + } else if (fd_g_config->cnf_sec_data.tls_disabled) { + /* We can agree on TLS */ + TRACE_DEBUG(INFO, "Remote peer is not allowed for IPsec and TLS is disabled.");; } else if (peer->p_hdr.info.runtime.pir_isi & PI_SEC_TLS_OLD) { /* We can agree on TLS */ isi = PI_SEC_TLS_OLD; diff -r 0b95a3afbfc3 -r d00b5914351e libfdcore/p_cnx.c --- a/libfdcore/p_cnx.c Mon May 27 17:22:40 2013 +0800 +++ b/libfdcore/p_cnx.c Tue May 28 12:11:27 2013 +0800 @@ -128,6 +128,14 @@ return 0; } + /* Check if we are able to communicate with this peer */ + if (fd_g_config->cnf_sec_data.tls_disabled && ( peer->p_hdr.info.config.pic_flags.sec != PI_SEC_NONE)) { + LOG_E("Peer '%s' not configured for No_TLS and TLS is locally disabled; giving up connection attempts", + peer->p_hdr.info.pi_diamid); + fd_psm_terminate( peer, NULL ); + return 0; + } + /* Cleanup any previous list */ empty_connection_list(peer);