Mercurial > hg > freeDiameter-dtls
diff libfdcore/cnxctx.c @ 1223:33ad82ffbdde
Make GNU TLS 3.x mandatory since we want to support DTLS. Removed the old compatibility code.
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Wed, 19 Jun 2013 14:38:57 +0800 |
parents | 1e8267ad057c |
children |
line wrap: on
line diff
--- a/libfdcore/cnxctx.c Tue Jun 18 17:05:44 2013 +0800 +++ b/libfdcore/cnxctx.c Wed Jun 19 14:38:57 2013 +0800 @@ -631,7 +631,6 @@ } -#ifdef GNUTLS_VERSION_300 /* The pull_timeout function for gnutls */ static int fd_cnx_s_select (struct cnxctx * conn, unsigned int ms) { @@ -646,7 +645,6 @@ return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv); } -#endif /* GNUTLS_VERSION_300 */ /* A recv-like function, taking a cnxctx object instead of socket as entry. We use it to quickly react to timeouts without traversing GNUTLS wrapper each time */ ssize_t fd_cnx_s_recv(struct cnxctx * conn, void *buffer, size_t length) @@ -709,17 +707,6 @@ return ret; } -/* Send, for older GNUTLS */ -#ifndef GNUTLS_VERSION_212 -static ssize_t fd_cnx_s_send(struct cnxctx * conn, const void *buffer, size_t length) -{ - struct iovec iov; - iov.iov_base = (void *)buffer; - iov.iov_len = length; - return fd_cnx_s_sendv(conn, &iov, 1); -} -#endif /* GNUTLS_VERSION_212 */ - #define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0) /* Could use __alignof__(t) on some systems but this is more portable probably */ #define PMDL_PADDED(len) ( ((len) + ALIGNOF(struct fd_msg_pmdl) - 1) & ~(ALIGNOF(struct fd_msg_pmdl) - 1) ) @@ -1176,232 +1163,6 @@ return 0; } -#ifndef GNUTLS_VERSION_300 - -/* Verify remote credentials after successful handshake (return 0 if OK, EINVAL otherwise) */ -int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, int verbose) -{ - int i, ret = 0; - unsigned int gtret; - const gnutls_datum_t *cert_list; - unsigned int cert_list_size; - gnutls_x509_crt_t cert; - time_t now; - - TRACE_ENTRY("%p %d", conn, verbose); - CHECK_PARAMS(conn); - - /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ - #ifdef DEBUG - if (verbose) { - const char *tmp; - gnutls_kx_algorithm_t kx; - gnutls_credentials_type_t cred; - - LOG_A("TLS Session information for connection '%s':", conn->cc_id); - - /* print the key exchange's algorithm name */ - GNUTLS_TRACE( kx = gnutls_kx_get (session) ); - GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); - LOG_A("\t - Key Exchange: %s", tmp); - - /* Check the authentication type used and switch - * to the appropriate. */ - GNUTLS_TRACE( cred = gnutls_auth_get_type (session) ); - switch (cred) - { - case GNUTLS_CRD_IA: - LOG_A("\t - TLS/IA session"); - break; - - case GNUTLS_CRD_PSK: - /* This returns NULL in server side. */ - if (gnutls_psk_client_get_hint (session) != NULL) - LOG_A("\t - PSK authentication. PSK hint '%s'", - gnutls_psk_client_get_hint (session)); - /* This returns NULL in client side. */ - if (gnutls_psk_server_get_username (session) != NULL) - LOG_A("\t - PSK authentication. Connected as '%s'", - gnutls_psk_server_get_username (session)); - break; - - case GNUTLS_CRD_ANON: /* anonymous authentication */ - LOG_A("\t - Anonymous DH using prime of %d bits", - gnutls_dh_get_prime_bits (session)); - break; - - case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */ - /* Check if we have been using ephemeral Diffie-Hellman. */ - if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) { - LOG_A("\t - Ephemeral DH using prime of %d bits", - gnutls_dh_get_prime_bits (session)); - } - break; -#ifdef ENABLE_SRP - case GNUTLS_CRD_SRP: - LOG_A("\t - SRP session with username %s", - gnutls_srp_server_get_username (session)); - break; -#endif /* ENABLE_SRP */ - - default: - fd_log_debug("\t - Different type of credentials for the session (%d).", cred); - break; - - } - - /* print the protocol's name (ie TLS 1.0) */ - tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); - LOG_A("\t - Protocol: %s", tmp); - - /* print the certificate type of the peer. ie X.509 */ - tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session)); - LOG_A("\t - Certificate Type: %s", tmp); - - /* print the compression algorithm (if any) */ - tmp = gnutls_compression_get_name (gnutls_compression_get (session)); - LOG_A("\t - Compression: %s", tmp); - - /* print the name of the cipher used. ie 3DES. */ - tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); - LOG_A("\t - Cipher: %s", tmp); - - /* Print the MAC algorithms name. ie SHA1 */ - tmp = gnutls_mac_get_name (gnutls_mac_get (session)); - LOG_A("\t - MAC: %s", tmp); - } - #endif /* DEBUG */ - - /* First, use built-in verification */ - CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, >ret), return EINVAL ); - if (gtret) { - if (TRACE_BOOL(INFO)) { - fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); - if (gtret & GNUTLS_CERT_INVALID) - fd_log_debug(" - The certificate is not trusted (unknown CA? expired?)"); - if (gtret & GNUTLS_CERT_REVOKED) - fd_log_debug(" - The certificate has been revoked."); - if (gtret & GNUTLS_CERT_SIGNER_NOT_FOUND) - fd_log_debug(" - The certificate hasn't got a known issuer."); - if (gtret & GNUTLS_CERT_SIGNER_NOT_CA) - fd_log_debug(" - The certificate signer is not a CA, or uses version 1, or 3 without basic constraints."); - if (gtret & GNUTLS_CERT_INSECURE_ALGORITHM) - fd_log_debug(" - The certificate signature uses a weak algorithm."); - } - return EINVAL; - } - - /* Code from http://www.gnu.org/software/gnutls/manual/gnutls.html#Verifying-peer_0027s-certificate */ - if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) - return EINVAL; - - GNUTLS_TRACE( cert_list = gnutls_certificate_get_peers (session, &cert_list_size) ); - if (cert_list == NULL) - return EINVAL; - - now = time(NULL); - - #ifdef DEBUG - char serial[40]; - char dn[128]; - size_t size; - unsigned int algo, bits; - time_t expiration_time, activation_time; - - LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size); - for (i = 0; i < cert_list_size; i++) - { - - CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); - CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); - - LOG_A(" Certificate %d info:", i); - - GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) ); - GNUTLS_TRACE( activation_time = gnutls_x509_crt_get_activation_time (cert) ); - - LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate is valid since: %.24s", ctime (&activation_time)); - LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate expires: %.24s", ctime (&expiration_time)); - - /* Print the serial number of the certificate. */ - size = sizeof (serial); - gnutls_x509_crt_get_serial (cert, serial, &size); - - { - int j; - char buf[1024]; - snprintf(buf, sizeof(buf), "\t - Certificate serial number: "); - for (j = 0; j < size; j++) { - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02hhx", serial[j]); - } - LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "%s", buf); - } - - /* Extract some of the public key algorithm's parameters */ - GNUTLS_TRACE( algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits) ); - LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate public key: %s", - gnutls_pk_algorithm_get_name (algo)); - - /* Print the version of the X.509 certificate. */ - LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate version: #%d", - gnutls_x509_crt_get_version (cert)); - - size = sizeof (dn); - GNUTLS_TRACE( gnutls_x509_crt_get_dn (cert, dn, &size) ); - LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - DN: %s", dn); - - size = sizeof (dn); - GNUTLS_TRACE( gnutls_x509_crt_get_issuer_dn (cert, dn, &size) ); - LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Issuer's DN: %s", dn); - - GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); - } - #endif /* DEBUG */ - - /* Check validity of all the certificates */ - for (i = 0; i < cert_list_size; i++) - { - time_t deadline; - - CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); - CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); - - GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) ); - if ((deadline != (time_t)-1) && (deadline < now)) { - if (TRACE_BOOL(INFO)) { - fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); - fd_log_debug(" - The certificate %d in the chain is expired", i); - } - ret = EINVAL; - } - - GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) ); - if ((deadline != (time_t)-1) && (deadline > now)) { - if (TRACE_BOOL(INFO)) { - fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); - fd_log_debug(" - The certificate %d in the chain is not yet activated", i); - } - ret = EINVAL; - } - - if ((i == 0) && (conn->cc_tls_para.cn)) { - if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { - if (TRACE_BOOL(INFO)) { - fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :", conn->cc_socket, conn->cc_remid, conn->cc_id); - fd_log_debug(" - The certificate hostname does not match '%s'", conn->cc_tls_para.cn); - } - ret = EINVAL; - } - } - - GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); - } - - return ret; -} - -#else /* GNUTLS_VERSION_300 */ - /* Verify remote credentials DURING handshake (return gnutls status) */ int fd_tls_verify_credentials_2(gnutls_session_t session) { @@ -1635,8 +1396,6 @@ return 0; } -#endif /* GNUTLS_VERSION_300 */ - static int fd_cnx_may_dtls(struct cnxctx * conn) { #ifndef DISABLE_SCTP if ((conn->cc_proto == IPPROTO_SCTP) && (conn->cc_tls_para.algo == ALGO_HANDSHAKE_DEFAULT)) @@ -1689,24 +1448,14 @@ /* Set the transport pointer passed to push & pull callbacks */ GNUTLS_TRACE( gnutls_transport_set_ptr( conn->cc_tls_para.session, (gnutls_transport_ptr_t) conn ) ); - #ifdef GNUTLS_VERSION_300 GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( conn->cc_tls_para.session, (void *)fd_cnx_s_select ) ); - #endif /* GNUTLS_VERSION_300 */ GNUTLS_TRACE( gnutls_transport_set_pull_function(conn->cc_tls_para.session, (void *)fd_cnx_s_recv) ); - #ifndef GNUTLS_VERSION_212 - GNUTLS_TRACE( gnutls_transport_set_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_send) ); - #else /* GNUTLS_VERSION_212 */ GNUTLS_TRACE( gnutls_transport_set_vec_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_sendv) ); - #endif /* GNUTLS_VERSION_212 */ } else { CHECK_FCT( fd_sctp_dtls_settransport(conn->cc_tls_para.session, conn) ); } } - /* additional initialization for gnutls 3.x */ - #ifdef GNUTLS_VERSION_300 - /* the verify function has already been set in the global initialization in config.c */ - /* fd_tls_verify_credentials_2 uses the connection */ gnutls_session_set_ptr (conn->cc_tls_para.session, (void *) conn); @@ -1715,8 +1464,6 @@ CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_tls_para.session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */); } - #endif /* GNUTLS_VERSION_300 */ - #ifdef GNUTLS_VERSION_310 GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); #endif /* GNUTLS_VERSION_310 */ @@ -1737,15 +1484,6 @@ return EINVAL; } ); - #ifndef GNUTLS_VERSION_300 - /* Now verify the remote credentials are valid -- only simple tests here */ - CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), - { - CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), ); - fd_cnx_markerror(conn); - return EINVAL; - }); - #endif /* GNUTLS_VERSION_300 */ } /* Multi-stream TLS: handshake other streams as well */