diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.cpp | 24 | ||||
-rw-r--r-- | src/certs.cpp | 9 | ||||
-rw-r--r-- | src/db/sql_query.cpp | 124 | ||||
-rw-r--r-- | src/include/cchecker/app.h | 18 | ||||
-rw-r--r-- | src/include/cchecker/sql_query.h | 1 |
5 files changed, 127 insertions, 49 deletions
diff --git a/src/app.cpp b/src/app.cpp index 58a7883..08b79a5 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -22,16 +22,14 @@ #include <sstream> #include <string> -#include <vector> #include <sys/types.h> #include <cchecker/app.h> +#include <cchecker/log.h> namespace CCHECKER { app_t::app_t(void): - check_id(-1), // -1 as invalid check_id - assume that in database - // all check_ids will be positive uid((uid_t)-1), // (uid_t)-1 (0xFF) is defined to be invalid uid. According // to chown manual page, you cannot change file group of owner // to (uid_t)-1, so we'll use it as initial, invalid value. @@ -41,19 +39,17 @@ app_t::app_t(void): app_t::app_t(const std::string &app_id, const std::string &pkg_id, uid_t uid, - const std::vector<std::string> &certificates): - check_id(-1), + const signatures_t &signatures): app_id(app_id), pkg_id(pkg_id), uid(uid), - certificates(certificates), + signatures(signatures), verified(verified_t::UNKNOWN) {} std::ostream & operator<< (std::ostream &out, const app_t &app) { - out << "app: " << app.app_id << ", pkg: " << app.pkg_id << ", uid: " << app.uid << - ", check_id: " << app.check_id; + out << "app: " << app.app_id << ", pkg: " << app.pkg_id << ", uid: " << app.uid; return out; } @@ -64,4 +60,16 @@ std::string app_t::str() const return ss.str(); } +std::string app_t::str_certs(void) const +{ + std::stringstream ss; + + for (const auto &iter : signatures) { + for (const auto iter_cert : iter) { + ss << "\"" << iter_cert << "\", "; + } + } + return ss.str(); +} + } //CCHECKER diff --git a/src/certs.cpp b/src/certs.cpp index 4a69fde..5b69ba0 100644 --- a/src/certs.cpp +++ b/src/certs.cpp @@ -119,7 +119,8 @@ void Certs::find_app_signatures (app_t &app, const std::string &app_path, ocsp_u LogDebug("Number of signature files: " << signature_files.size()); LogDebug("Searching for certificates"); - for (auto iter = signature_files.begin(); iter != signature_files.end(); iter++){ + for (auto iter = signature_files.begin(); iter != signature_files.end(); iter++) { + chain_t chain; LogDebug("Checking signature"); ValidationCore::SignatureData data(app_path + std::string("/") + (*iter).getFileName(), (*iter).getFileNumber()); @@ -131,7 +132,7 @@ void Certs::find_app_signatures (app_t &app, const std::string &app_path, ocsp_u ValidationCore::CertificateList certs = data.getCertList(); for (auto cert_iter = certs.begin(); cert_iter != certs.end(); cert_iter++ ){ std::string app_cert = (*cert_iter)->getBase64(); - app.certificates.push_back(app_cert); + chain.push_back(app_cert); LogDebug("Certificate: " << app_cert << " has been added"); // check OCSP URL @@ -150,6 +151,10 @@ void Certs::find_app_signatures (app_t &app, const std::string &app_path, ocsp_u // Needs to catch parser exceptions LogError("Error occured in ParserSchema: " << exception.DumpToString()); } + if (!chain.empty()) { + app.signatures.push_back(chain); + LogDebug("Certificates chain added to the app"); + } } } diff --git a/src/db/sql_query.cpp b/src/db/sql_query.cpp index 0968717..27eb52e 100644 --- a/src/db/sql_query.cpp +++ b/src/db/sql_query.cpp @@ -36,6 +36,12 @@ namespace { // 107 - check_id // 108 - certificate // 109 - verified + // 110 - chain_id + + // setup + const char *DB_CMD_SETUP = "VACUUM; PRAGMA foregin_keys=ON;"; + + const char *DB_CMD_GET_LAST_INSERTED_ROW = "SELECT last_insert_rowid();"; // urls const char *DB_CMD_GET_URL = @@ -54,17 +60,24 @@ namespace { const char *DB_CMD_GET_CHECK_ID = "SELECT check_id FROM to_check WHERE app_id=?104 AND pkg_id=?105 AND uid=?106;"; + const char *DB_CMD_ADD_CHAIN = + "INSERT INTO chains_to_check(check_id) VALUES(?107);"; + const char *DB_CMD_ADD_CERT = - "INSERT INTO certs_to_check(check_id, certificate) VALUES(?107, ?108);"; + "INSERT INTO certs_to_check(chain_id, certificate) VALUES(?110, ?108);"; + + const char *DB_CMD_GET_CHAINS = + "SELECT chain_id FROM chains_to_check INNER JOIN to_check ON chains_to_check.check_id=to_check.check_id \ +WHERE to_check.app_id=?104 AND to_check.pkg_id=?105 AND to_check.uid=?106;"; const char *DB_CMD_REMOVE_APP = "DELETE FROM to_check WHERE app_id=?104 AND pkg_id=?105 AND uid=?106;"; const char *DB_CMD_GET_APPS = - "SELECT * FROM to_check"; + "SELECT app_id, pkg_id, uid, verified FROM to_check"; const char *DB_CMD_GET_CERTS = - "SELECT certificate FROM certs_to_check WHERE check_id=?107;"; + "SELECT certificate FROM certs_to_check WHERE chain_id=?110;"; const char *DB_CMD_SET_APP_AS_VERIFIED = "UPDATE to_check SET verified=?109 WHERE check_id=?107"; @@ -91,7 +104,7 @@ bool SqlQuery::connect(const std::string& path) Try { m_connection = new SqlConnection(path, SqlConnection::Flag::None, SqlConnection::Flag::Option::CRW); - m_connection->ExecCommand("VACUUM;"); + m_connection->ExecCommand(DB_CMD_SETUP); return true; } Catch(std::bad_alloc) { LogError("Couldn't allocate SqlConnection"); @@ -185,6 +198,25 @@ bool SqlQuery::get_check_id(const app_t &app, int32_t &check_id) return false; } +bool SqlQuery::add_chain_id(const int32_t check_id, int32_t &chain_id) +{ + // Add new chain for an app + SqlConnection::DataCommandAutoPtr addChainCommand = + m_connection->PrepareDataCommand(DB_CMD_ADD_CHAIN); + addChainCommand->BindInt32(107, check_id); + addChainCommand->Step(); + + // get chain_id + SqlConnection::DataCommandAutoPtr getLastInserted = + m_connection->PrepareDataCommand(DB_CMD_GET_LAST_INSERTED_ROW); + if(getLastInserted->Step()) { + chain_id = getLastInserted->GetColumnInt32(0); + LogDebug("Found chain_id: " << chain_id << ", for check_id " << check_id); + return true; + } + return false; +} + bool SqlQuery::add_app_to_check_list(const app_t &app) { //Check if app exists in DB @@ -206,23 +238,35 @@ bool SqlQuery::add_app_to_check_list(const app_t &app) // Get check_id int32_t check_id; - if (get_check_id(app, check_id)) { - // If get check_id succeed we can add certificates to database - for (const auto &iter : app.certificates) { - SqlConnection::DataCommandAutoPtr addCertCommand = - m_connection->PrepareDataCommand(DB_CMD_ADD_CERT); - addCertCommand->BindInt32(107, check_id); - addCertCommand->BindString(108, iter.c_str()); - addCertCommand->Step(); - LogDebug("Certificate for app " << app.app_id << "added"); - } - m_connection->CommitTransaction(); - return true; - } else { // If get check_id failed return false; + if (!get_check_id(app, check_id)) { // If get check_id failed return false; LogDebug("Failed while addind app "<< app.app_id << " to to_check table."); m_connection->RollbackTransaction(); return false; } + + // If get check_id succeed we can add chain to database + int32_t chain_id; + for (const auto &iter : app.signatures) { + // Add chain + if (add_chain_id(check_id, chain_id)) { + // add certificates from chain + for (const auto &iter_cert : iter) { + SqlConnection::DataCommandAutoPtr addCertCommand = + m_connection->PrepareDataCommand(DB_CMD_ADD_CERT); + addCertCommand->BindInt32(110, chain_id); + addCertCommand->BindString(108, iter_cert.c_str()); + addCertCommand->Step(); + LogDebug("Certificate for app " << app.app_id << "added"); + } + } else { + LogDebug("Failed to add certificates chain"); + m_connection->RollbackTransaction(); + return false; + } + + } + m_connection->CommitTransaction(); + return true; } void SqlQuery::remove_app_from_check_list(const app_t &app) @@ -265,12 +309,11 @@ void SqlQuery::get_apps(std::list<app_t> &apps_buffer) while (getAppsCommand->Step()) { app_t app; - app.check_id = getAppsCommand->GetColumnInt32(0); - app.app_id = getAppsCommand->GetColumnString(1); - app.pkg_id = getAppsCommand->GetColumnString(2); - app.uid = getAppsCommand->GetColumnInt64(3); - app.verified = static_cast<app_t::verified_t>(getAppsCommand->GetColumnInt32(4)); - app.certificates = {}; + app.app_id = getAppsCommand->GetColumnString(0); + app.pkg_id = getAppsCommand->GetColumnString(1); + app.uid = getAppsCommand->GetColumnInt64(2); + app.verified = static_cast<app_t::verified_t>(getAppsCommand->GetColumnInt32(3)); + app.signatures = {}; LogDebug("App read from DB: app_id: " << app.str() << ", verified: " << static_cast<int32_t>(app.verified)); apps_buffer.push_back(app); } @@ -278,18 +321,37 @@ void SqlQuery::get_apps(std::list<app_t> &apps_buffer) void SqlQuery::get_app_list(std::list<app_t> &apps_buffer) { + m_connection->BeginTransaction(); get_apps(apps_buffer); - // Get certificates for apps - for (auto &iter : apps_buffer) { - SqlConnection::DataCommandAutoPtr getCertsCommand = - m_connection->PrepareDataCommand(DB_CMD_GET_CERTS); - getCertsCommand->BindInt32(107, iter.check_id); - - while (getCertsCommand->Step()) { - iter.certificates.push_back(getCertsCommand->GetColumnString(0)); + // Get chain for every application + for (auto &iter_app : apps_buffer) { + SqlConnection::DataCommandAutoPtr getChainsCommand = + m_connection->PrepareDataCommand(DB_CMD_GET_CHAINS); + getChainsCommand->BindString(104, iter_app.app_id.c_str()); + getChainsCommand->BindString(105, iter_app.pkg_id.c_str()); + getChainsCommand->BindInt32(106, iter_app.uid); + + // Get all certs from chain + while (getChainsCommand->Step()) { + chain_t chain; + int32_t chain_id; + chain_id = getChainsCommand->GetColumnInt32(0); + LogDebug("Found chain (" << chain_id << ") for " << iter_app.str()); + + SqlConnection::DataCommandAutoPtr getCertsCommand = + m_connection->PrepareDataCommand(DB_CMD_GET_CERTS); + getCertsCommand->BindInt32(110, chain_id); + + // Add found certs to chain + while (getCertsCommand->Step()) { + chain.push_back(getCertsCommand->GetColumnString(0)); + LogDebug("Found certificate (" << chain.size() << ") in chain no. " << chain_id); + } + iter_app.signatures.push_back(chain); } } + m_connection->CommitTransaction(); } } // DB diff --git a/src/include/cchecker/app.h b/src/include/cchecker/app.h index 3217bdb..46fd9b6 100644 --- a/src/include/cchecker/app.h +++ b/src/include/cchecker/app.h @@ -23,7 +23,6 @@ #define CCHECKER_APP_H #include <string> -#include <vector> #include <list> #include <sys/types.h> @@ -33,6 +32,9 @@ namespace CCHECKER { // Currently in signals from pkgmgr only information about pkg_id is included const char *const TEMP_APP_ID = "temp#app_id"; +typedef std::list<std::string> chain_t; +typedef std::list<chain_t> signatures_t; + struct app_t { enum class verified_t : int32_t { NO = 0, @@ -40,19 +42,19 @@ struct app_t { UNKNOWN = 2 }; - int32_t check_id; - std::string app_id; - std::string pkg_id; - uid_t uid; - std::vector<std::string> certificates; //TODO: add typedef - verified_t verified; + std::string app_id; + std::string pkg_id; + uid_t uid; + signatures_t signatures; + verified_t verified; app_t(void); app_t(const std::string &app_id, const std::string &pkg_id, uid_t uid, - const std::vector<std::string> &certificates); + const signatures_t &signatures); std::string str(void) const; + std::string str_certs(void) const; }; struct url_t { diff --git a/src/include/cchecker/sql_query.h b/src/include/cchecker/sql_query.h index 5a22740..e4cc582 100644 --- a/src/include/cchecker/sql_query.h +++ b/src/include/cchecker/sql_query.h @@ -69,6 +69,7 @@ class SqlQuery { void get_apps(std::list<app_t> &apps_buffer); bool check_if_app_exists(const app_t &app); bool get_check_id(const app_t &app, int32_t &check_id); + bool add_chain_id(const int32_t check_id, int32_t &chain_id); int verified_enum_to_int(const app_t::verified_t &verified); app_t::verified_t verified_int_to_enum(const int &verified); }; |