From 9854cd50f374ba8599a4333a692b1265af952da6 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Mon, 24 Aug 2015 09:52:41 +0200 Subject: [PATCH] xml: handle failure of xmlSecBase64Decode() (fixes #8070) Thanks to fpeters for the patch. --- lasso/xml/tools.c | 5 +++ tests/non_regression_tests.c | 21 ++++++++++++ tests/tests.c | 13 ++++++-- tests/tests.h | 63 +++++++++++++++++++++++------------- 4 files changed, 78 insertions(+), 24 deletions(-) diff --git a/lasso/xml/tools.c b/lasso/xml/tools.c index bb434a56..ba707d4a 100644 --- a/lasso/xml/tools.c +++ b/lasso/xml/tools.c @@ -1363,6 +1363,11 @@ lasso_node_init_from_deflated_query_part(LassoNode *node, char *deflate_string) zre = xmlMalloc(len*4); len = xmlSecBase64Decode(b64_zre, zre, len*4); xmlFree(b64_zre); + if (len == -1) { + message(G_LOG_LEVEL_CRITICAL, "Failed to base64-decode query"); + xmlFree(zre); + return FALSE; + } re = lasso_inflate(zre, len); xmlFree(zre); diff --git a/tests/non_regression_tests.c b/tests/non_regression_tests.c index ef304393..d2993ecd 100644 --- a/tests/non_regression_tests.c +++ b/tests/non_regression_tests.c @@ -213,6 +213,26 @@ START_TEST(wrong_endpoint_index_in_artifacts) } END_TEST +START_TEST(malformed_logout_request) +{ + /* Sent by Songling Han on 2015-08-08 */ + LassoServer *server = NULL; + LassoLogout *logout = NULL; + char *msg = "SAMLRequest=lZJRS8MwFIX/SsnrSJOmmWlCLQz3UpgKTnzwZaRZugW6pPam6s+3WxFRRPAp5HJPznfuTQn61PVqEw5hjA/2ZbQQk3p9jXb8SgrJucRUXi0xp7nAUi8zXEgjZZ43hSwMSp7sAC74a8RSipIaYLS1h6h9nEo0W2JaYCoeWaZYobhIRbZ8Rsl6cnFex4vyGGMPipBMsJTlac7TQpLFm21ee78g87nrLoDpMZ46lNwED/bsMA5eBQ0OlNcnCyoatV3dbtQEo8zcpEYPvTWudXaPkrsQ7/39sGqjHX4C5vkX4Pup86Aus/nbpR9CDCZ0qCov4YdZ+rdIA9jhHB5V5/BT9jfnJxiGWWocmJB2weiO6H0LZGp9dcYCicMIsSSzTVXeTc/W6//aQfCHzvmSzPKqnPe/tXBeY+339r3aZQ3XVlCOdcZbzDPW4ELsp2tLBWXcSslESX5Rfha/fafqAw==tLBWXcSslESX5Rfha%2ffafqAw%3d%3d&Signature=a3Pm6zoaMTJDv8cDOOa+u1BEBvFuAtUmcqsUIUGkOIkCswlq44VNvAJ1NaHZfk8uf+q1KEfl8CLASjL1Rgjzc6JjzRv0U4qRPeF9U5D07W1G+f9AZWMat6AHAwXoAq42B5fdJJtDhCXjEYQRoWKMzJQzn/6QFezUMbErPz3gzku384+RBTrlTpNYdEoC4j2YOGiTBvlZAUdmDNpCkKeEVUOKZhe7V5u8nqOK2F+WhLlCU8g5EIvoEeIXpmY4rn4h2lRsLKJTKLB2RNJoE3U7lBkUzObHmmt0gfiFxGOuL0vxmfrKt/psvZsRMOsVzmZrUW7BVaCw2j0uB7X9njbDiA==0uB7X9njbDiA%3d%3d&SigAlg=http://www.w3.org/2000/09/xmldsig#rsa-sha1sig%23rsa-sha1"; + + check_not_null(server = lasso_server_new(TESTSDATADIR "/idp5-saml2/metadata.xml", + TESTSDATADIR "/idp5-saml2/private-key.pem", NULL, NULL)); + check_good_rc(lasso_server_add_provider(server, LASSO_PROVIDER_ROLE_SP, + TESTSDATADIR "/sp5-saml2/metadata.xml", NULL, NULL)); + check_not_null(logout = lasso_logout_new(server)); + block_lasso_logs; + check_equals(lasso_logout_process_request_msg(logout, msg), LASSO_PROFILE_ERROR_INVALID_MSG); + unblock_lasso_logs; + lasso_release_gobject(logout); + lasso_release_gobject(server); +} +END_TEST + struct { char *name; void *function; @@ -221,6 +241,7 @@ struct { { "Wrong assertionConsumer ordering on 08-10-2010", indexed_endpoints_20101008}, { "Warning when parsing AttributeValue node containing unknown namespace nodes", remove_warning_when_parssing_unknown_SNIPPET_LIST_NODES_20111007 }, { "Wrong endpoint index in artifacts", wrong_endpoint_index_in_artifacts }, + { "Malformed logout request", malformed_logout_request }, }; Suite* diff --git a/tests/tests.c b/tests/tests.c index 7536c096..606f5bbe 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -26,6 +26,7 @@ #include #include +#include #include "../lasso/lasso.h" #include "../lasso/lasso_config.h" @@ -55,7 +56,15 @@ SuiteFunction suites[] = { #endif NULL }; -void error_logger(const gchar *log_domain, GLogLevelFlags log_level, + +void +mute_logger(G_GNUC_UNUSED const gchar *domain, + G_GNUC_UNUSED GLogLevelFlags log_level, G_GNUC_UNUSED const gchar *message, + G_GNUC_UNUSED gpointer user_data) { +} + +void +fail_logger(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, G_GNUC_UNUSED gpointer user_data) { fail("No logging output expected: message «%s» was emitted for domain «%s» at the level" @@ -77,7 +86,7 @@ main(int argc, char *argv[]) } lasso_init(); - g_log_set_default_handler(error_logger, NULL); + unblock_lasso_logs; sr = srunner_create(suites[0]()); diff --git a/tests/tests.h b/tests/tests.h index 52920555..0f2a6c9e 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -73,21 +73,24 @@ fail_unless(g_strcmp0(__tmp, to) != 0, "%s:%i: " #what " is equal to %s", __func__, __LINE__, to); \ } -static inline void mute_logger(G_GNUC_UNUSED const gchar *domain, +void mute_logger(G_GNUC_UNUSED const gchar *domain, G_GNUC_UNUSED GLogLevelFlags log_level, G_GNUC_UNUSED const gchar *message, - G_GNUC_UNUSED gpointer user_data) { -} -G_GNUC_UNUSED static guint mute_log_handler = 0; + G_GNUC_UNUSED gpointer user_data); -#define block_lasso_logs mute_log_handler = g_log_set_handler(LASSO_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \ - mute_logger, NULL) +void fail_logger(const gchar *log_domain, GLogLevelFlags log_level, + const gchar *message, G_GNUC_UNUSED gpointer user_data); -#define unblock_lasso_logs g_log_remove_handler(LASSO_LOG_DOMAIN, mute_log_handler) +#define block_lasso_logs g_log_set_default_handler(mute_logger, NULL); + +#define unblock_lasso_logs g_log_set_default_handler(fail_logger, NULL); + + +#define CHECKING_LOG_HANDLER_SIZE 30 struct CheckingLogHandlerUserData { - GLogLevelFlags log_level; - const char *message; - gboolean endswith; + GLogLevelFlags log_levels[CHECKING_LOG_HANDLER_SIZE]; + const char *messages[CHECKING_LOG_HANDLER_SIZE]; + gboolean endswith[CHECKING_LOG_HANDLER_SIZE]; GLogLevelFlags log_level_found; char *message_found; }; @@ -108,24 +111,40 @@ static inline void checking_logger(G_GNUC_UNUSED const gchar *domain, G_GNUC_UNUSED GLogLevelFlags log_level, G_GNUC_UNUSED const gchar *message, G_GNUC_UNUSED gpointer user_data) { struct CheckingLogHandlerUserData *ck_user_data = user_data; - if (log_level == ck_user_data->log_level && check_message(message, ck_user_data->message, - ck_user_data->endswith)) { - } else { - g_log_default_handler(domain, log_level, message, user_data); - checking_log_handler_flag = 0; + int i = 0; + for (i = 0; i < CHECKING_LOG_HANDLER_SIZE; i++) { + if (log_level == ck_user_data->log_levels[i] && check_message(message, ck_user_data->messages[i], + ck_user_data->endswith[i])) { + ck_user_data->log_level_found = log_level; + ck_user_data->message_found = g_strdup(message); + return; + } } - ck_user_data->log_level_found = log_level; - ck_user_data->message_found = g_strdup(message); + g_log_default_handler(domain, log_level, message, user_data); + checking_log_handler_flag = 0; } + +static inline void add_check_log(GLogLevelFlags log_level, const char *message, gboolean endswith) { + int i = 0; + + for (i = 0; i < CHECKING_LOG_HANDLER_SIZE-1; i++) { + if (! checking_logger_user_data.messages[i]) { + checking_logger_user_data.log_levels[i] = log_level; + checking_logger_user_data.messages[i] = message; + checking_logger_user_data.endswith[i] = endswith; + return; + } + } + g_assert_not_reached(); +} + /* begin_check_do_log(level, message, endswith)/end_check_do_log() with check that the only * message emitted between the two macros is one equals to message at the level level, * or ending with message if endswith is True. */ static inline void begin_check_do_log(GLogLevelFlags level, const char *message, gboolean endswith) { memset(&checking_logger_user_data, 0, sizeof(struct CheckingLogHandlerUserData)); - checking_logger_user_data.log_level = level; - checking_logger_user_data.message = message; - checking_logger_user_data.endswith = endswith; + add_check_log(level, message, endswith); checking_log_handler = g_log_set_handler(LASSO_LOG_DOMAIN, level, checking_logger, &checking_logger_user_data); checking_log_handler_flag = 1; } @@ -134,8 +153,8 @@ static inline void end_check_do_log() { g_log_remove_handler(LASSO_LOG_DOMAIN, checking_log_handler); checking_log_handler = 0; fail_unless(checking_log_handler_flag, "Logging failure: expected log level %d and message «%s», got %d and «%s»", - checking_logger_user_data.log_level, - checking_logger_user_data.message, + checking_logger_user_data.log_levels[0], + checking_logger_user_data.messages[0], checking_logger_user_data.log_level_found, checking_logger_user_data.message_found); if (checking_logger_user_data.message_found) {