** 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.
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)
* Headers::
* Initialization::
* Version check::
-* Debugging::
+* Debugging and auditing::
* Building the source::
@end menu
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
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);
* 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
*/
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");
}
}
* 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
*/
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");
}
}
*/
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 ();
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;
}
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--;
}
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);
}
}
}
+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
;
#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
#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
#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 *, ...);
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 */
/**
_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.
#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);
}
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);
}
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)
{
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;
}
{
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();
/* 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
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);
}
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;
}
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;
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.
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 {
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));
exit (1);
}
- gnutls_global_set_log_function (tls_log_func);
- gnutls_global_set_log_level (info.debug);
-
sockets_init ();
#ifndef _WIN32
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
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));
}
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