[libgdata] core: Filter sensitive details out of debug log output
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata] core: Filter sensitive details out of debug log output
- Date: Mon, 10 Oct 2011 08:39:48 +0000 (UTC)
commit fd2d8a5f14aece4b28b07d2bffeb766d77c972aa
Author: Philip Withnall <philip tecnocode co uk>
Date: Mon Oct 10 09:38:19 2011 +0100
core: Filter sensitive details out of debug log output
Add a new log level, GDATA_LOG_FULL_UNREDACTED = 4, and redact usernames,
passwords and auth. tokens from all log levels below it. Thus, taking a
debug log with LIBGDATA_DEBUG=3 will no longer inadvertently reveal the
user's password.
Helps: bgo#656783
README | 5 ++-
gdata/gdata-private.h | 8 +++-
gdata/gdata-service.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++-
gdata/tests/common.c | 2 +-
4 files changed, 105 insertions(+), 6 deletions(-)
---
diff --git a/README b/README
index 2ef0388..82893ea 100644
--- a/README
+++ b/README
@@ -30,7 +30,10 @@ values, libgdata will give debug output (at various levels):
0: Output no debug messages or network logs
1: Output debug messages, but not network logs
2: Output debug messages and network traffic headers
- 3: Output debug messages and full network traffic logs
+ 3: Output debug messages and full network traffic logs, redacting usernames,
+ passwords and auth. tokens
+ 4: Output debug messages and full network traffic logs, and don't redact
+ usernames, passwords and auth. tokens
If LIBGDATA_DEBUG is unset, no debug output will be produced.
Deprecation guards
diff --git a/gdata/gdata-private.h b/gdata/gdata-private.h
index 6e55451..95685a7 100644
--- a/gdata/gdata-private.h
+++ b/gdata/gdata-private.h
@@ -33,7 +33,10 @@ G_BEGIN_DECLS
* @GDATA_LOG_NONE: Output no debug messages or network logs
* @GDATA_LOG_MESSAGES: Output debug messages, but not network logs
* @GDATA_LOG_HEADERS: Output debug messages and network traffic headers
- * @GDATA_LOG_FULL: Output debug messages and full network traffic logs
+ * @GDATA_LOG_FULL: Output debug messages and full network traffic logs,
+ * redacting usernames, passwords and auth. tokens
+ * @GDATA_LOG_FULL_UNREDACTED: Output debug messages and full network traffic
+ * logs, and don't redact usernames, passwords and auth. tokens
*
* Logging level.
**/
@@ -41,7 +44,8 @@ typedef enum {
GDATA_LOG_NONE = 0,
GDATA_LOG_MESSAGES = 1,
GDATA_LOG_HEADERS = 2,
- GDATA_LOG_FULL = 3
+ GDATA_LOG_FULL = 3,
+ GDATA_LOG_FULL_UNREDACTED = 4,
} GDataLogLevel;
#include "gdata-service.h"
diff --git a/gdata/gdata-service.c b/gdata/gdata-service.c
index f2a383f..cd98ae6 100644
--- a/gdata/gdata-service.c
+++ b/gdata/gdata-service.c
@@ -1975,7 +1975,98 @@ debug_handler (const char *log_domain, GLogLevelFlags log_level, const char *mes
static void
soup_log_printer (SoupLogger *logger, SoupLoggerLogLevel level, char direction, const char *data, gpointer user_data)
{
- g_debug ("%c %s", direction, data);
+ gboolean filter_data;
+ gchar *_data = NULL;
+
+ filter_data = (_gdata_service_get_log_level () > GDATA_LOG_NONE && _gdata_service_get_log_level () < GDATA_LOG_FULL_UNREDACTED) ? TRUE : FALSE;
+
+ if (filter_data == TRUE) {
+ /* Filter out lines which look like they might contain usernames, passwords or auth. tokens. */
+ if (direction == '>' && g_str_has_prefix (data, "Authorization: GoogleLogin ") == TRUE) {
+ _data = g_strdup ("Authorization: GoogleLogin <redacted>");
+ } else if (direction == '>' && g_str_has_prefix (data, "Authorization: OAuth ") == TRUE) {
+ _data = g_strdup ("Authorization: OAuth <redacted>");
+ } else if (direction == '<' && g_str_has_prefix (data, "Set-Cookie: ") == TRUE) {
+ _data = g_strdup ("Set-Cookie: <redacted>");
+ } else if (direction == '<' && g_str_has_prefix (data, "Location: ") == TRUE) {
+ /* Looks like:
+ * "Location: https://www.google.com/calendar/feeds/default/owncalendars/full?gsessionid=sBjmp05m5i67exYA51XjDA". */
+ SoupURI *uri;
+ gchar *_uri;
+ GHashTable *params;
+
+ uri = soup_uri_new (data + strlen ("Location: "));
+
+ if (uri->query != NULL) {
+ params = soup_form_decode (uri->query);
+
+ /* strdup()s are necessary because the hash table's set up to free keys. */
+ if (g_hash_table_lookup (params, "gsessionid") != NULL) {
+ g_hash_table_insert (params, (gpointer) g_strdup ("gsessionid"), (gpointer) "<redacted>");
+ }
+
+ soup_uri_set_query_from_form (uri, params);
+ g_hash_table_destroy (params);
+ }
+
+ _uri = soup_uri_to_string (uri, FALSE);
+ _data = g_strconcat ("Location: ", _uri, NULL);
+ g_free (_uri);
+
+ soup_uri_free (uri);
+ } else if (direction == '<' && g_str_has_prefix (data, "SID=") == TRUE) {
+ _data = g_strdup ("SID=<redacted>");
+ } else if (direction == '<' && g_str_has_prefix (data, "LSID=") == TRUE) {
+ _data = g_strdup ("LSID=<redacted>");
+ } else if (direction == '<' && g_str_has_prefix (data, "Auth=") == TRUE) {
+ _data = g_strdup ("Auth=<redacted>");
+ } else if (direction == '>' && g_str_has_prefix (data, "accountType=") == TRUE) {
+ /* Looks like: "> accountType=HOSTED%5FOR%5FGOOGLE&Email=[e-mail address]&Passwd=[plaintex password]"
+ "&service=[service name]&source=ytapi%2DGNOME%2Dlibgdata%2D444fubtt%2D0". */
+ GHashTable *params = soup_form_decode (data);
+
+ /* strdup()s are necessary because the hash table's set up to free keys. */
+ if (g_hash_table_lookup (params, "Email") != NULL) {
+ g_hash_table_insert (params, (gpointer) g_strdup ("Email"), (gpointer) "<redacted>");
+ }
+ if (g_hash_table_lookup (params, "Passwd") != NULL) {
+ g_hash_table_insert (params, (gpointer) g_strdup ("Passwd"), (gpointer) "<redacted>");
+ }
+
+ _data = soup_form_encode_hash (params);
+
+ g_hash_table_destroy (params);
+ } else if (direction == '<' && g_str_has_prefix (data, "oauth_token=") == TRUE) {
+ /* Looks like: "< oauth_token=4%2FI-WU7sBzKk5GhGlQUF8a_TCZRnb7&oauth_token_secret=qTTTJg3no25auiiWFerzjW4I"
+ "&oauth_callback_confirmed=true". */
+ GHashTable *params = soup_form_decode (data);
+
+ /* strdup()s are necessary because the hash table's set up to free keys. */
+ if (g_hash_table_lookup (params, "oauth_token") != NULL) {
+ g_hash_table_insert (params, (gpointer) g_strdup ("oauth_token"), (gpointer) "<redacted>");
+ }
+ if (g_hash_table_lookup (params, "oauth_token_secret") != NULL) {
+ g_hash_table_insert (params, (gpointer) g_strdup ("oauth_token_secret"), (gpointer) "<redacted>");
+ }
+
+ _data = soup_form_encode_hash (params);
+
+ g_hash_table_destroy (params);
+ } else {
+ /* Nothing to redact. */
+ _data = g_strdup (data);
+ }
+ } else {
+ /* Don't dupe the string. */
+ _data = (gchar*) data;
+ }
+
+ /* Log the data. */
+ g_debug ("%c %s", direction, _data);
+
+ if (filter_data == TRUE) {
+ g_free (_data);
+ }
}
/**
@@ -1996,7 +2087,7 @@ _gdata_service_get_log_level (void)
const gchar *envvar = g_getenv ("LIBGDATA_DEBUG");
if (envvar != NULL)
level = atoi (envvar);
- level = MIN (MAX (level, 0), GDATA_LOG_FULL);
+ level = MIN (MAX (level, 0), GDATA_LOG_FULL_UNREDACTED);
}
return level;
@@ -2027,6 +2118,7 @@ _gdata_service_build_session (void)
SoupLogger *logger;
switch (_gdata_service_get_log_level ()) {
+ case GDATA_LOG_FULL_UNREDACTED:
case GDATA_LOG_FULL:
level = SOUP_LOGGER_LOG_BODY;
break;
diff --git a/gdata/tests/common.c b/gdata/tests/common.c
index a4b0573..feacd99 100644
--- a/gdata/tests/common.c
+++ b/gdata/tests/common.c
@@ -74,7 +74,7 @@ gdata_test_init (int argc, char **argv)
g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=");
/* Enable full debugging */
- g_setenv ("LIBGDATA_DEBUG", "3", FALSE);
+ g_setenv ("LIBGDATA_DEBUG", "3" /* GDATA_LOG_FULL */, FALSE);
}
/*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]