From a2f5be9497597111b101a21195d66316aeb99afe Mon Sep 17 00:00:00 2001 From: Bjoern Sikora Date: Wed, 9 Sep 2009 14:55:11 +0200 Subject: [PATCH] Added error handling in Util::compute_md5_digest and avoided using of C functions like sprintf. --- src/logger.cpp | 20 ++++++++++++++++ src/logger.h | 2 + src/service_gnudip.cpp | 23 +++++++++++++++++- src/util.cpp | 57 +++++++++++++++++++++++++++++++---------------- src/util.h | 16 ++----------- 5 files changed, 83 insertions(+), 35 deletions(-) diff --git a/src/logger.cpp b/src/logger.cpp index f413b9a..f265eae 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -1420,6 +1420,10 @@ void Logger::print_could_not_get_initial_gnudip_data() const } + +/** + * Gnudip protocol requires explicit declaration of a servername. + */ void Logger::print_gnudip_requires_servername() const { int level = 0; @@ -1430,3 +1434,19 @@ void Logger::print_gnudip_requires_servername() const log_warning(msg.str(),level); } } + + +/** + * An exception occured while computing the md5 sum. + * @param what The exception occured. + */ +void Logger::print_exception_md5_sum(const std::string& what) const +{ + int level = 0; + if ( (level <= Loglevel) || ((level <= ExternalWarningLevel) && (!ExternalWarningLog.empty())) ) + { + ostringstream msg; + msg << "An exception occured while computing a md5 sum: " << what << endl; + log_error(msg.str(),level); + } +} diff --git a/src/logger.h b/src/logger.h index 61f7055..7d85cdb 100644 --- a/src/logger.h +++ b/src/logger.h @@ -207,6 +207,8 @@ public: void print_could_not_get_initial_gnudip_data() const; void print_gnudip_requires_servername() const; + + void print_exception_md5_sum(const std::string& what) const; }; #endif diff --git a/src/service_gnudip.cpp b/src/service_gnudip.cpp index 7109b6a..fe5064a 100644 --- a/src/service_gnudip.cpp +++ b/src/service_gnudip.cpp @@ -227,12 +227,31 @@ int ServiceGnudip::perform_update(const std::string& ip) get_logger()->print_could_not_get_initial_gnudip_data(); // compute md5 sum from users password and get the HEX representation - string pw_md5_hex = Util::compute_md5_digest(get_password()); + string pw_md5_hex; + try + { + pw_md5_hex = Util::compute_md5_digest(get_password()); + } + catch ( invalid_argument e ) + { + get_logger()->print_exception_md5_sum(e.what()); + return -1; + } // append "." and salt and compute md5 sum and get the HEX representation pw_md5_hex.append("."); pw_md5_hex.append(salt); - string secret = Util::compute_md5_digest(pw_md5_hex); + + string secret; + try + { + secret = Util::compute_md5_digest(pw_md5_hex); + } + catch ( invalid_argument e ) + { + get_logger()->print_exception_md5_sum(e.what()); + return -1; + } // Now its time to issue the second http_get operation string url = assemble_update_url(salt, time, sign, secret, ip); diff --git a/src/util.cpp b/src/util.cpp index 1f10ce8..d2078d7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,5 +1,5 @@ /** @file - * @brief Util class implementation. + * @brief Util namespace implementation. * * * @@ -9,50 +9,67 @@ #include "util.h" -#include +#include #include -#include -Util::Util() -{ -} - -Util::~Util() -{ -} +using namespace std; /** * Computes a MD5 Digest from the given string and returns the HEX representation * @param data The string to compute the md5 for * @return The computed md5 in hex */ -std::string Util::compute_md5_digest(std::string data) +string Util::compute_md5_digest(string data) throw (invalid_argument) { // compute an MD5 digest. - string result; EVP_MD_CTX mdctx; const EVP_MD *md; unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len; + unsigned int md_len = 0; + // Add all digest algorithms to the internal table. OpenSSL_add_all_digests(); + // Get the md5 digest algorithm from the internal table. md = EVP_get_digestbyname("md5"); + // Test if md is initialized. + if ( (md == NULL) || (EVP_MD_size(md) == 0) ) + throw invalid_argument("NULL pointer: md"); + + // Initalize digest content mdctx. EVP_MD_CTX_init(&mdctx); + + // Now we can call init_ex. EVP_DigestInit_ex(&mdctx, md, NULL); - EVP_DigestUpdate(&mdctx, data.c_str(), strlen(data.c_str())); + + // Test if data is empty. + if ( data.empty() ) + throw invalid_argument("Passed data is empty"); + + // Hash the data. At this point data is not empty and &mdctx is initialized. + EVP_DigestUpdate(&mdctx, data.c_str(), data.size()); + + // Retrieve the digest value from &mdctx and place it in md_value. EVP_DigestFinal_ex(&mdctx, md_value, &md_len); - EVP_MD_CTX_cleanup(&mdctx); - char buffer[2]; + // Test if md_value is filled correctly and md_len is not zero. + if ( (md_len == 0) || (md_value == NULL) || (EVP_MD_CTX_size(&mdctx) == 0) ) + throw invalid_argument("Retrieved invalid digest value"); + + // Internal cleanup of the digest content. + EVP_MD_CTX_cleanup(&mdctx); + EVP_cleanup(); - for(int i = 0; i < md_len; i++) + // Convert md5 digest C string to hex. + ostringstream oss_digest_md5_hex; + for(unsigned int i = 0; i < md_len; ++i) { - sprintf(buffer,"%02x", md_value[i]); - result.append(buffer); + // We have to do a static cast to an decimal representation, cause otherwise ostringstream would interpret + // the stream as a character and output the character representation of the hex value. + oss_digest_md5_hex << hex << static_cast(md_value[i]); } - return result; + return oss_digest_md5_hex.str(); } diff --git a/src/util.h b/src/util.h index 43321de..b7cb9fc 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,5 @@ /** @file - * @brief Util class header. + * @brief Util namespace header. * * * @@ -11,19 +11,9 @@ #define UTIL_H -class Util +namespace Util { -private: - - -public: - - Util(); - - ~Util(); - - static std::string compute_md5_digest(std::string); - + static std::string compute_md5_digest(std::string) throw (std::invalid_argument); }; #endif -- 1.7.1