From: Nikos Mavrogiannopoulos Date: Sat, 7 May 2011 19:28:23 +0000 (+0200) Subject: Added gnutls_global_set_audit_log_function() that allows associating TLS session... X-Git-Tag: gnutls_2_99_2~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fdbf94bdd69ade7db79f7c6142055d0fafe163ec;p=thirdparty%2Fgnutls.git Added gnutls_global_set_audit_log_function() that allows associating TLS session with several important issues. --- diff --git a/NEWS b/NEWS index 02110690e1..f5bdcfe417 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ See the end for copying conditions. ** certtool: Can now load private keys and public keys from PKCS #11 tokens via URLs. +** libgnutls: Added gnutls_global_set_audit_log_function() that allows +to get important auditing information including the corresponding session. +That might be useful to block DoS or other attacker from specific IPs. + ** libgnutls: gnutls_pkcs11_privkey_import_url() will now correctly read the public key algorithm of the key. @@ -27,7 +31,7 @@ the self signature of the request. gnutls_certificate_get_issuer: ADDED gnutls_x509_trust_list_get_issuer: ADDED gnutls_x509_crq_verify: ADDED - +gnutls_global_set_audit_log_function: ADDED * Version 2.99.1 (released 2011-04-23) diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi index 90545493d1..935ea40d3b 100644 --- a/doc/cha-gtls-app.texi +++ b/doc/cha-gtls-app.texi @@ -24,7 +24,7 @@ the following subsections. * Headers:: * Initialization:: * Version check:: -* Debugging:: +* Debugging and auditing:: * Building the source:: @end menu @@ -66,15 +66,23 @@ with the dynamic linker an old version is actually used. So you may want to check that the version is okay right after program startup. See the function @ref{gnutls_check_version}. -@node Debugging -@subsection Debugging +@node Debugging and auditing +@subsection Debugging and auditing In many cases things may not go as expected and further information, -to assist debugging, from @acronym{GnuTLS} is desired. Those are the -case where the @ref{gnutls_global_set_log_level} and +to assist debugging, from @acronym{GnuTLS} is desired. +Those are the cases where the @ref{gnutls_global_set_log_level} and @ref{gnutls_global_set_log_function} are to be used. Those will print verbose information on the @acronym{GnuTLS} functions internal flow. + +When debugging is not required, important issues, such as detected +attacks on the protocol still need to be logged. This is provided +by @ref{gnutls_global_set_audit_log_function}, that uses a logging +function that accepts the detected error message and the corresponding +TLS session. The session information might be used to derive IP addresses +or other information about the peer involved. + @node Building the source @subsection Building the Source diff --git a/lib/accelerated/intel/aes-x86.c b/lib/accelerated/intel/aes-x86.c index 101569554b..daffccd760 100644 --- a/lib/accelerated/intel/aes-x86.c +++ b/lib/accelerated/intel/aes-x86.c @@ -184,7 +184,7 @@ register_x86_crypto (void) if (check_optimized_aes ()) { - fprintf (stderr, "Intel AES accelerator was detected\n"); + _gnutls_debug_log ("Intel AES accelerator was detected\n"); ret = gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_128_CBC, 80, &cipher_struct); diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c index 2e5b7f548d..f20a375cfb 100644 --- a/lib/auth/rsa.c +++ b/lib/auth/rsa.c @@ -195,7 +195,7 @@ proc_rsa_client_kx (gnutls_session_t session, opaque * data, * attack against pkcs-1 formating). */ gnutls_assert (); - _gnutls_audit_log ("auth_rsa: Possible PKCS #1 format attack\n"); + _gnutls_audit_log (session, "auth_rsa: Possible PKCS #1 format attack\n"); randomize_key = 1; } else @@ -214,7 +214,7 @@ proc_rsa_client_kx (gnutls_session_t session, opaque * data, */ gnutls_assert (); _gnutls_audit_log - ("auth_rsa: Possible PKCS #1 version check format attack\n"); + (session, "auth_rsa: Possible PKCS #1 version check format attack\n"); } } diff --git a/lib/auth/rsa_export.c b/lib/auth/rsa_export.c index 7829a1a63b..4f10f55a31 100644 --- a/lib/auth/rsa_export.c +++ b/lib/auth/rsa_export.c @@ -173,7 +173,7 @@ proc_rsa_export_client_kx (gnutls_session_t session, opaque * data, * attack against pkcs-1 formating). */ gnutls_assert (); - _gnutls_audit_log ("auth_rsa: Possible PKCS #1 format attack\n"); + _gnutls_audit_log (session, "auth_rsa: Possible PKCS #1 format attack\n"); randomize_key = 1; } else @@ -192,7 +192,7 @@ proc_rsa_export_client_kx (gnutls_session_t session, opaque * data, */ gnutls_assert (); _gnutls_audit_log - ("auth_rsa: Possible PKCS #1 version check format attack\n"); + (session, "auth_rsa: Possible PKCS #1 version check format attack\n"); } } diff --git a/lib/auth/srp.c b/lib/auth/srp.c index f46ec1a267..17b2c0ff6c 100644 --- a/lib/auth/srp.c +++ b/lib/auth/srp.c @@ -814,7 +814,7 @@ _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data, */ if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0) { - _gnutls_audit_log ("SRP group parameters are not in the white list. Checking validity.\n"); + _gnutls_audit_log (session, "SRP group parameters are not in the white list. Checking validity.\n"); if ((ret = group_check_g_n (session, G, N)) < 0) { gnutls_assert (); diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c index 510c4e6131..3a7cca2682 100644 --- a/lib/gnutls_buffers.c +++ b/lib/gnutls_buffers.c @@ -1071,7 +1071,7 @@ parse_record_buffered_msgs (gnutls_session_t session, if (ret < 0) { gnutls_assert(); - _gnutls_audit_log("Invalid handshake packet headers. Discarding.\n"); + _gnutls_audit_log(session, "Invalid handshake packet headers. Discarding.\n"); break; } @@ -1111,7 +1111,7 @@ next: while(session->internals.handshake_recv_buffer_size > 0 && recv_buf[LAST_ELEMENT].sequence < session->internals.dtls.hsk_read_seq) { - _gnutls_audit_log("Discarded replayed handshake packet with sequence %d\n", recv_buf[LAST_ELEMENT].sequence); + _gnutls_audit_log(session, "Discarded replayed handshake packet with sequence %d\n", recv_buf[LAST_ELEMENT].sequence); _gnutls_handshake_buffer_clear(&recv_buf[LAST_ELEMENT]); session->internals.handshake_recv_buffer_size--; } diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c index a77b65f63f..b00b3e83e9 100644 --- a/lib/gnutls_dtls.c +++ b/lib/gnutls_dtls.c @@ -652,7 +652,7 @@ uint8_t digest[C_HASH_SIZE]; cookie.data = &msg[pos]; if (cookie.size != COOKIE_SIZE) { - if (cookie.size > 0) _gnutls_audit_log("Received cookie with illegal size %d. Expected %d\n", (int)cookie.size, COOKIE_SIZE); + if (cookie.size > 0) _gnutls_audit_log(NULL, "Received cookie with illegal size %d. Expected %d\n", (int)cookie.size, COOKIE_SIZE); return gnutls_assert_val(GNUTLS_E_BAD_COOKIE); } diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 8096c2e424..c5405694d1 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -574,6 +574,30 @@ _gnutls_log (int level, const char *fmt, ...) } } +void +_gnutls_audit_log (gnutls_session_t session, const char *fmt, ...) +{ + va_list args; + char *str; + int ret; + + if (_gnutls_audit_log_func == NULL && _gnutls_log_func == NULL) + return; + + va_start (args, fmt); + ret = vasprintf (&str, fmt, args); + va_end (args); + + if (ret >= 0) + { + if (_gnutls_audit_log_func) + _gnutls_audit_log_func (session, str); + else + _gnutls_log_func(1, str); + free (str); + } +} + #ifndef DEBUG #ifndef C99_MACROS diff --git a/lib/gnutls_errors.h b/lib/gnutls_errors.h index 43f3c49008..df27958677 100644 --- a/lib/gnutls_errors.h +++ b/lib/gnutls_errors.h @@ -50,6 +50,14 @@ _gnutls_log (int, const char *fmt, ...) ; #endif +void +_gnutls_audit_log (gnutls_session_t, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 2, 3))); +#else + ; +#endif + void _gnutls_mpi_log (const char *prefix, bigint_t a); #ifdef C99_MACROS @@ -68,7 +76,6 @@ void _gnutls_mpi_log (const char *prefix, bigint_t a); #define _gnutls_dtls_log(...) LEVEL(6, __VA_ARGS__) #define _gnutls_read_log(...) LEVEL_EQ(7, __VA_ARGS__) #define _gnutls_write_log(...) LEVEL_EQ(7, __VA_ARGS__) -#define _gnutls_audit_log(...) LEVEL(1, __VA_ARGS__) #else #define _gnutls_debug_log _gnutls_null_log #define _gnutls_handshake_log _gnutls_null_log @@ -79,7 +86,6 @@ void _gnutls_mpi_log (const char *prefix, bigint_t a); #define _gnutls_dtls_log _gnutls_null_log #define _gnutls_read_log _gnutls_null_log #define _gnutls_write_log _gnutls_null_log -#define _gnutls_audit_log _gnutls_null_log void _gnutls_null_log (void *, ...); diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c index 7a424cc5fc..c69adcf74d 100644 --- a/lib/gnutls_global.c +++ b/lib/gnutls_global.c @@ -49,6 +49,7 @@ ASN1_TYPE _gnutls_pkix1_asn; ASN1_TYPE _gnutls_gnutls_asn; gnutls_log_func _gnutls_log_func; +gnutls_audit_log_func _gnutls_audit_log_func; int _gnutls_log_level = 0; /* default log level */ /** @@ -69,6 +70,24 @@ gnutls_global_set_log_function (gnutls_log_func log_func) _gnutls_log_func = log_func; } +/** + * gnutls_global_set_audit_log_function: + * @log_func: it is the audit log function + * + * This is the function where you set the logging function gnutls is + * going to use. This is different from gnutls_global_set_log_function() + * because it will report the session of the event if any. Note that + * that session might be null if there is no corresponding TLS session. + * + * gnutls_audit_log_func is of the form, + * void (*gnutls_audit_log_func)( gnutls_session_t, int level, const char*); + **/ +void +gnutls_global_set_audit_log_function (gnutls_audit_log_func log_func) +{ + _gnutls_audit_log_func = log_func; +} + /** * gnutls_global_set_log_level: * @level: it's an integer from 0 to 9. diff --git a/lib/gnutls_global.h b/lib/gnutls_global.h index db2b1b1c2c..affd1faecf 100644 --- a/lib/gnutls_global.h +++ b/lib/gnutls_global.h @@ -42,6 +42,7 @@ extern ASN1_TYPE _gnutls_gnutls_asn; #define _gnutls_get_pkix() ((ASN1_TYPE) _gnutls_pkix1_asn) extern gnutls_log_func _gnutls_log_func; +extern gnutls_audit_log_func _gnutls_audit_log_func; extern int _gnutls_log_level; extern int gnutls_crypto_init (void); diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 7aa53a30fb..0e11c2fcd1 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -1336,7 +1336,7 @@ _gnutls_recv_handshake (gnutls_session_t session, } if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET) - _gnutls_audit_log("Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n", + _gnutls_audit_log(session, "Received unexpected handshake message '%s' (%d). Expected '%s' (%d)\n", _gnutls_handshake2str(hsk.htype), (int)hsk.htype, _gnutls_handshake2str(type), (int)type); return gnutls_assert_val_fatal(ret); diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index ba8310956b..4afac7edfa 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -500,7 +500,7 @@ _gnutls_send_int (gnutls_session_t session, content_type_t type, } inline static int -check_recv_type (content_type_t recv_type) +check_recv_type (gnutls_session_t session, content_type_t recv_type) { switch (recv_type) { @@ -511,7 +511,7 @@ check_recv_type (content_type_t recv_type) return 0; default: gnutls_assert (); - _gnutls_audit_log("Received record packet of unknown type %u\n", (unsigned int)recv_type); + _gnutls_audit_log(session, "Received record packet of unknown type %u\n", (unsigned int)recv_type); return GNUTLS_E_UNEXPECTED_PACKET; } @@ -876,7 +876,7 @@ gnutls_datum_t raw; /* raw headers */ { if (_gnutls_epoch_is_valid(session, record->epoch) == 0) { - _gnutls_audit_log("Discarded message[%u] with invalid epoch 0x%.2x%.2x.\n", + _gnutls_audit_log(session, "Discarded message[%u] with invalid epoch 0x%.2x%.2x.\n", (unsigned int)_gnutls_uint64touint32 (&record->sequence), (int)record->sequence.i[0], (int)record->sequence.i[1]); gnutls_assert(); @@ -888,7 +888,7 @@ gnutls_datum_t raw; /* raw headers */ /* Here we check if the Type of the received packet is * ok. */ - if ((ret = check_recv_type (record->type)) < 0) + if ((ret = check_recv_type (session, record->type)) < 0) return gnutls_assert_val(ret); /* Here we check if the advertized version is the one we @@ -900,7 +900,7 @@ gnutls_datum_t raw; /* raw headers */ if (record->length > MAX_RECV_SIZE(session)) { _gnutls_audit_log - ("Received packet with illegal length: %u\n", (unsigned int)record->length); + (session, "Received packet with illegal length: %u\n", (unsigned int)record->length); return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); } @@ -1030,7 +1030,7 @@ begin: ret = _dtls_record_check(session, packet_sequence); if (ret < 0) { - _gnutls_audit_log("Discarded duplicate message[%u]\n", + _gnutls_audit_log(session, "Discarded duplicate message[%u]\n", (unsigned int) _gnutls_uint64touint32 (packet_sequence)); goto sanity_check_error; } @@ -1096,7 +1096,7 @@ discard: sanity_check_error: if (IS_DTLS(session)) { - _gnutls_audit_log("Discarded message[%u] due to invalid decryption\n", + _gnutls_audit_log(session, "Discarded message[%u] due to invalid decryption\n", (unsigned int)_gnutls_uint64touint32 (packet_sequence)); ret = gnutls_assert_val(GNUTLS_E_AGAIN); goto cleanup; diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 46ea4a86f0..f85b6b397b 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1119,7 +1119,9 @@ extern "C" extern char *(*gnutls_strdup) (const char *); typedef void (*gnutls_log_func) (int, const char *); + typedef void (*gnutls_audit_log_func) (gnutls_session_t, const char *); void gnutls_global_set_log_function (gnutls_log_func log_func); + void gnutls_global_set_audit_log_function (gnutls_audit_log_func log_func); void gnutls_global_set_log_level (int level); /* Diffie-Hellman parameter handling. diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 63bacd2104..ccae4576a0 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -712,6 +712,7 @@ GNUTLS_3_0_0 { gnutls_pubkey_get_openpgp_key_id; gnutls_certificate_set_retrieve_function2; gnutls_x509_trust_list_get_issuer; + gnutls_global_set_audit_log_function; } GNUTLS_2_12; GNUTLS_PRIVATE { diff --git a/src/cli.c b/src/cli.c index 88aa645999..cfe047052a 100644 --- a/src/cli.c +++ b/src/cli.c @@ -720,6 +720,9 @@ main (int argc, char **argv) set_program_name (argv[0]); + gnutls_global_set_log_function (tls_log_func); + gnutls_global_set_log_level (info.debug); + if ((ret = gnutls_global_init ()) < 0) { fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret)); @@ -734,9 +737,6 @@ main (int argc, char **argv) exit (1); } - gnutls_global_set_log_function (tls_log_func); - gnutls_global_set_log_level (info.debug); - sockets_init (); #ifndef _WIN32 diff --git a/src/serv.c b/src/serv.c index 405e5560aa..32eb9da2e5 100644 --- a/src/serv.c +++ b/src/serv.c @@ -881,6 +881,12 @@ tls_log_func (int level, const char *str) fprintf (stderr, "|<%d>| %s", level, str); } +static void +tls_audit_log_func (gnutls_session_t session, const char *str) +{ + fprintf (stderr, "|<%p>| %s", session, str); +} + static void gaa_parser (int argc, char **argv); int @@ -915,6 +921,10 @@ main (int argc, char **argv) strcpy (name, "Echo Server"); } + gnutls_global_set_log_function (tls_log_func); + gnutls_global_set_audit_log_function (tls_audit_log_func); + gnutls_global_set_log_level (debug); + if ((ret = gnutls_global_init ()) < 0) { fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret)); @@ -928,8 +938,6 @@ main (int argc, char **argv) } pkcs11_common (); - gnutls_global_set_log_function (tls_log_func); - gnutls_global_set_log_level (debug); /* Note that servers must generate parameters for * Diffie-Hellman. See gnutls_dh_params_generate(), and