strongswan/src/libimcv/plugins/imv_os/imv_os_database.c

217 lines
4.9 KiB
C

/*
* Copyright (C) 2012 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#define _GNU_SOURCE /* for stdndup() */
#include <string.h>
#include "imv_os_database.h"
#include <utils/debug.h>
typedef struct private_imv_os_database_t private_imv_os_database_t;
/**
* Private data of a imv_os_database_t object.
*
*/
struct private_imv_os_database_t {
/**
* Public imv_os_database_t interface.
*/
imv_os_database_t public;
/**
* database instance
*/
database_t *db;
};
METHOD(imv_os_database_t, check_packages, status_t,
private_imv_os_database_t *this, imv_os_state_t *state,
enumerator_t *package_enumerator)
{
char *product, *package, *release, *cur_release;
chunk_t name, version;
os_type_t os_type;
int pid, gid, security, blacklist;
int count = 0, count_ok = 0, count_no_match = 0, count_blacklist = 0;
enumerator_t *e;
status_t status = SUCCESS;
bool found, match;
product = state->get_info(state, &os_type, NULL, NULL);
if (os_type == OS_TYPE_ANDROID)
{
/*no package dependency on Android version */
product = enum_to_name(os_type_names, os_type);
}
DBG1(DBG_IMV, "processing installed '%s' packages", product);
/* Get primary key of product */
e = this->db->query(this->db,
"SELECT id FROM products WHERE name = ?",
DB_TEXT, product, DB_INT);
if (!e)
{
return FAILED;
}
if (!e->enumerate(e, &pid))
{
e->destroy(e);
return NOT_FOUND;
}
e->destroy(e);
while (package_enumerator->enumerate(package_enumerator, &name, &version))
{
/* Convert package name chunk to a string */
package = strndup(name.ptr, name.len);
count++;
/* Get primary key of package */
e = this->db->query(this->db,
"SELECT id FROM packages WHERE name = ?",
DB_TEXT, package, DB_INT);
if (!e)
{
free(package);
return FAILED;
}
if (!e->enumerate(e, &gid))
{
/* package not present in database for any product - skip */
if (os_type == OS_TYPE_ANDROID)
{
DBG2(DBG_IMV, "package '%s' (%.*s) not found",
package, version.len, version.ptr);
}
free(package);
e->destroy(e);
continue;
}
e->destroy(e);
/* Convert package version chunk to a string */
release = strndup(version.ptr, version.len);
/* Enumerate over all acceptable versions */
e = this->db->query(this->db,
"SELECT release, security, blacklist FROM versions "
"WHERE product = ? AND package = ?",
DB_INT, pid, DB_INT, gid, DB_TEXT, DB_INT, DB_INT);
if (!e)
{
free(package);
free(release);
return FAILED;
}
found = FALSE;
match = FALSE;
while (e->enumerate(e, &cur_release, &security, &blacklist))
{
found = TRUE;
if (streq(release, cur_release) || streq("*", cur_release))
{
match = TRUE;
break;
}
}
e->destroy(e);
if (found)
{
if (match)
{
if (blacklist)
{
DBG2(DBG_IMV, "package '%s' (%s) is blacklisted",
package, release);
count_blacklist++;
state->add_bad_package(state, package,
OS_PACKAGE_STATE_BLACKLIST);
}
else
{
DBG2(DBG_IMV, "package '%s' (%s)%s is ok", package, release,
security ? " [s]" : "");
count_ok++;
}
}
else
{
DBG1(DBG_IMV, "package '%s' (%s) no match", package, release);
count_no_match++;
state->add_bad_package(state, package,
OS_PACKAGE_STATE_SECURITY);
}
}
else
{
/* package not present in database for this product - skip */
}
free(package);
free(release);
}
state->set_count(state, count, count_no_match, count_blacklist, count_ok);
return status;
}
METHOD(imv_os_database_t, set_device_info, void,
private_imv_os_database_t *this, int session_id, int count,
int count_update, int count_blacklist, u_int flags)
{
this->db->execute(this->db, NULL,
"INSERT INTO device_infos (session, count, count_update, "
"count_blacklist, flags) VALUES (?, ?, ?, ?, ?)",
DB_INT, session_id, DB_INT, count, DB_INT, count_update,
DB_INT, count_blacklist, DB_UINT, flags);
}
METHOD(imv_os_database_t, destroy, void,
private_imv_os_database_t *this)
{
free(this);
}
/**
* See header
*/
imv_os_database_t *imv_os_database_create(imv_database_t *imv_db)
{
private_imv_os_database_t *this;
if (!imv_db)
{
return NULL;
}
INIT(this,
.public = {
.check_packages = _check_packages,
.set_device_info = _set_device_info,
.destroy = _destroy,
},
.db = imv_db->get_database(imv_db),
);
return &this->public;
}