sec-updater: Import SWID tags of updated packages
sec-updater downloads the deb package files from security updates from a given linux repository and uses the swid_generator command to derive a SWID tag. The SWID tag is then imported into strongTNC using the manage.py importswid command.
This commit is contained in:
@@ -25,6 +25,7 @@ options = \
|
||||
options/starter.opt \
|
||||
options/swanctl.opt \
|
||||
options/tnc.opt \
|
||||
options/sec-updater.opt \
|
||||
options/sw-collector.opt
|
||||
|
||||
plugins = \
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
sec-updater {}
|
||||
Options for the sec-updater tool.
|
||||
|
||||
Options for the sec-updater tool.
|
||||
|
||||
sec-updater.database =
|
||||
Global IMV policy database URI. If it contains a password, make sure to
|
||||
adjust the permissions of the config file accordingly.
|
||||
|
||||
sec-updater.swid_gen.command = /usr/local/bin/swid_generator
|
||||
SWID generator command to be executed.
|
||||
|
||||
sec-updater.swid_gen.tag_creator.name = strongSwan Project
|
||||
Name of the tagCreator entity.
|
||||
|
||||
sec-updater.swid_gen.tag_creator.regid = strongswan.org
|
||||
regid of the tagCreator entity.
|
||||
|
||||
sec-updater.tnc_manager_command = /var/www/tnc/manager.py
|
||||
strongTNC manage.py command used to import SWID tags.
|
||||
|
||||
sec-updater.tmp.deb_file = /tmp/sec-updater.deb
|
||||
Temporary storage for downloaded deb package file.
|
||||
|
||||
sec-updater.tmp.tag_file = /tmp/sec-updater.tag
|
||||
Temporary storage for generated SWID tags.
|
||||
|
||||
sec-updater.load =
|
||||
Plugins to load in sec-updater tool.
|
||||
@@ -10,7 +10,9 @@ sec-updater \- Extracts security update information of Linux distributions
|
||||
.OP \-\-debug level
|
||||
.OP \-\-quiet
|
||||
.OP \-\-security
|
||||
.BI \-\-product " name"
|
||||
.BI \-\-os " string"
|
||||
.BI \-\-arch " string"
|
||||
.BI \-\-uri " uri"
|
||||
.BI \-\-file " filename"
|
||||
.YS
|
||||
.
|
||||
@@ -44,20 +46,37 @@ Disable debug output to stderr.
|
||||
.B "\-s, \-\-security"
|
||||
Set when parsing a distributions file with security updates.
|
||||
.TP
|
||||
.BI "\-p, \-\-product " name
|
||||
Name of Linux version as stored in database. eg. "Ubuntu 16.04 x86_64".
|
||||
.BI "\-o, \-\-os " string
|
||||
Name of operating system (OS). eg. "Ubuntu 16.04".
|
||||
.TP
|
||||
.BI "\-o, \-\-arch " string
|
||||
Name of HW architecture. eg. "x86_64".
|
||||
.TP
|
||||
.BI "\-o, \-\-uri " uri
|
||||
URI where to download deb package from.
|
||||
.TP
|
||||
.BI "\-f, \-\-file " filename
|
||||
Linux package information file to parse.
|
||||
.
|
||||
.SH "CONFIGURATION"
|
||||
.
|
||||
The following parameter must be configured in strongswan.conf:
|
||||
The following parameters can be configured in strongswan.conf:
|
||||
.P
|
||||
sec-updater {
|
||||
database = sqlite:///etc/pts/config.db
|
||||
database = sqlite:///etc/pts/config.db
|
||||
swid_gen {
|
||||
command = /usr/local/bin/swid_generator
|
||||
tag_creator {
|
||||
name = strongSwan Project
|
||||
regid = strongswan.org
|
||||
}
|
||||
}
|
||||
tnc_manage_command = /var/www/tnc/manage.py
|
||||
tmp {
|
||||
deb_file = /tmp/sec-updater.deb
|
||||
tag_file = /tmp/sec-updater.tag
|
||||
}
|
||||
}
|
||||
.P
|
||||
.
|
||||
.SH "SEE ALSO"
|
||||
.
|
||||
|
||||
+147
-38
@@ -28,12 +28,17 @@
|
||||
#include <utils/debug.h>
|
||||
|
||||
#define EXIT_NO_UPDATES 80
|
||||
#define TMP_DEB_FILE "/tmp/sec-updater.deb"
|
||||
#define TMP_TAG_FILE "/tmp/sec-updater.tag"
|
||||
#define SWID_GEN_CMD "/usr/local/bin/swid_generator"
|
||||
#define TNC_MANAGE_CMD "/var/www/tnc/manage.py"
|
||||
|
||||
typedef enum sec_update_state_t sec_update_state_t;
|
||||
|
||||
enum sec_update_state_t {
|
||||
SEC_UPDATE_STATE_BEGIN_PACKAGE,
|
||||
SEC_UPDATE_STATE_VERSION,
|
||||
SEC_UPDATE_STATE_FILENAME,
|
||||
SEC_UPDATE_STATE_END_PACKAGE
|
||||
};
|
||||
|
||||
@@ -106,21 +111,24 @@ static void usage(void)
|
||||
printf("\
|
||||
Usage:\n\
|
||||
sec-updater --help\n\
|
||||
sec-updater [--debug <level>] [--quiet] [--security] --product <name> --file <filename>\n\n\
|
||||
sec-updater [--debug <level>] [--quiet] [--security] --os <string>\n\
|
||||
--arch <string> --uri <uri> --file <filename>\n\n\
|
||||
Options:\n\
|
||||
--help print usage information\n\
|
||||
--debug set debug level\n\
|
||||
--debug <level> set debug level\n\
|
||||
--quiet suppress debug output to stderr\n\
|
||||
--os <string> operating system\n\
|
||||
--arch <string> hw architecture\n\
|
||||
--security set when parsing a file with security updates\n\
|
||||
--product <name> name of the Linux version as stored in the database\n\
|
||||
--file <filename> package information file to parse");
|
||||
}
|
||||
--file <filename> package information file to parse\n\
|
||||
--uri <uri> uri where to download deb package from\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the package database
|
||||
*/
|
||||
static bool update_database(database_t *db, char *package, char *version,
|
||||
bool security, stats_t *stats)
|
||||
bool security, stats_t *stats, bool *new)
|
||||
{
|
||||
int pid = 0, vid = 0, sec_flag;
|
||||
bool first = TRUE, found = FALSE;
|
||||
@@ -130,6 +138,9 @@ static bool update_database(database_t *db, char *package, char *version,
|
||||
/* increment package count */
|
||||
stats->packages++;
|
||||
|
||||
/* set new output variable */
|
||||
*new = FALSE;
|
||||
|
||||
/* check if package is already in database */
|
||||
e = db->query(db, "SELECT id FROM packages WHERE name = ?",
|
||||
DB_TEXT, package, DB_INT);
|
||||
@@ -221,6 +232,7 @@ static bool update_database(database_t *db, char *package, char *version,
|
||||
return FALSE;
|
||||
}
|
||||
stats->new_versions++;
|
||||
*new = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -229,16 +241,21 @@ static bool update_database(database_t *db, char *package, char *version,
|
||||
/**
|
||||
* Process a package file and store updates in the database
|
||||
*/
|
||||
static int process_packages(char *filename, char *product, bool security)
|
||||
static int process_packages(char *path, char *os, char *arch, char *uri,
|
||||
bool security)
|
||||
{
|
||||
char *uri, line[BUF_LEN], *pos, *package = NULL, *version = NULL;
|
||||
char line[BUF_LEN], product[BUF_LEN], command[BUF_LEN];
|
||||
char *db_uri, *download_uri = NULL, *swid_regid, *swid_entity;
|
||||
char *pos, *package = NULL, *version = NULL, *filename = NULL;
|
||||
char *swid_gen_cmd, *tnc_manage_cmd, *tmp_deb_file, *tmp_tag_file;
|
||||
sec_update_state_t state;
|
||||
enumerator_t *e;
|
||||
database_t *db;
|
||||
int pid;
|
||||
int len, pid;
|
||||
chunk_t deb = chunk_empty;
|
||||
FILE *file;
|
||||
stats_t stats;
|
||||
bool success;
|
||||
bool success, new;
|
||||
|
||||
/* initialize statistics */
|
||||
memset(&stats, 0x00, sizeof(stats_t));
|
||||
@@ -247,29 +264,32 @@ static int process_packages(char *filename, char *product, bool security)
|
||||
stats.release = time(NULL);
|
||||
|
||||
/* opening package file */
|
||||
file = fopen(filename, "r");
|
||||
file = fopen(path, "r");
|
||||
if (!file)
|
||||
{
|
||||
DBG1(DBG_IMV, " could not open \"%s\"", filename);
|
||||
DBG1(DBG_IMV, " could not open \"%s\"", path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* connect package database */
|
||||
uri = lib->settings->get_str(lib->settings, "sec-updater.database", NULL);
|
||||
if (!uri)
|
||||
db_uri = lib->settings->get_str(lib->settings, "sec-updater.database", NULL);
|
||||
if (!db_uri)
|
||||
{
|
||||
DBG1(DBG_IMV, "database URI sec-updater.database not set");
|
||||
fclose(file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
db = lib->db->create(lib->db, uri);
|
||||
db = lib->db->create(lib->db, db_uri);
|
||||
if (!db)
|
||||
{
|
||||
DBG1(DBG_IMV, "could not connect to database '%s'", uri);
|
||||
DBG1(DBG_IMV, "could not connect to database '%s'", db_uri);
|
||||
fclose(file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* form product name by concatenating os and arch strings */
|
||||
snprintf(product, BUF_LEN, "%s %s", os, arch);
|
||||
|
||||
/* check if product is already in database */
|
||||
e = db->query(db, "SELECT id FROM products WHERE name = ?",
|
||||
DB_TEXT, product, DB_INT);
|
||||
@@ -295,6 +315,22 @@ static int process_packages(char *filename, char *product, bool security)
|
||||
stats.product = pid;
|
||||
}
|
||||
|
||||
/* get settings for the loop */
|
||||
swid_regid = lib->settings->get_str(lib->settings,
|
||||
"sec-updater.swid_gen.tag_creator.regid",
|
||||
"strongswan.org");
|
||||
swid_entity = lib->settings->get_str(lib->settings,
|
||||
"sec-updater.swid_gen.tag_creator.name",
|
||||
"strongSwan Project");
|
||||
swid_gen_cmd = lib->settings->get_str(lib->settings,
|
||||
"sec-updater.swid_gen.command", SWID_GEN_CMD);
|
||||
tnc_manage_cmd = lib->settings->get_str(lib->settings,
|
||||
"sec-updater.tnc_manage_command", TNC_MANAGE_CMD);
|
||||
tmp_deb_file = lib->settings->get_str(lib->settings,
|
||||
"sec-updater.tmp.deb_file", TMP_DEB_FILE);
|
||||
tmp_tag_file = lib->settings->get_str(lib->settings,
|
||||
"sec-updater.tmp.tag_file", TMP_TAG_FILE);
|
||||
|
||||
state = SEC_UPDATE_STATE_BEGIN_PACKAGE;
|
||||
|
||||
while (fgets(line, sizeof(line), file))
|
||||
@@ -331,7 +367,58 @@ static int process_packages(char *filename, char *product, bool security)
|
||||
if (pos)
|
||||
{
|
||||
version = strndup(version, pos - version);
|
||||
state = SEC_UPDATE_STATE_END_PACKAGE;
|
||||
success = update_database(db, package, version, security,
|
||||
&stats, &new);
|
||||
state = (success && new) ? SEC_UPDATE_STATE_FILENAME :
|
||||
SEC_UPDATE_STATE_END_PACKAGE;
|
||||
}
|
||||
break;
|
||||
case SEC_UPDATE_STATE_FILENAME:
|
||||
pos = strstr(pos, "Filename: ");
|
||||
if (!pos)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
state = SEC_UPDATE_STATE_END_PACKAGE;
|
||||
|
||||
pos += 10;
|
||||
filename = pos;
|
||||
pos = strchr(pos, '\n');
|
||||
if (!pos)
|
||||
{
|
||||
break;
|
||||
}
|
||||
len = pos - filename;
|
||||
if (asprintf(&download_uri, "%s/%.*s", uri, len, filename) == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* retrieve deb package file from linux repository */
|
||||
if (lib->fetcher->fetch(lib->fetcher, download_uri,
|
||||
&deb, FETCH_END) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IMV, " %s failed", download_uri);
|
||||
break;
|
||||
}
|
||||
DBG1(DBG_IMV, " %s (%u bytes)", download_uri, deb.len);
|
||||
|
||||
/* store deb package file to temporary location */
|
||||
if (!chunk_write(deb, tmp_deb_file, 0022, TRUE))
|
||||
{
|
||||
DBG1(DBG_IMV, " save to '%s' failed", tmp_deb_file);
|
||||
break;
|
||||
}
|
||||
|
||||
/* generate SWID tag for downloaded deb package */
|
||||
snprintf(command, BUF_LEN, "%s swid --full --package-file %s "
|
||||
"--regid %s --entity-name '%s' --os '%s' --arch '%s' "
|
||||
">> %s", swid_gen_cmd, tmp_deb_file, swid_regid,
|
||||
swid_entity, os, arch, tmp_tag_file);
|
||||
if (system(command) != 0)
|
||||
{
|
||||
DBG1(DBG_IMV, " tag generation failed");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SEC_UPDATE_STATE_END_PACKAGE:
|
||||
@@ -339,9 +426,12 @@ static int process_packages(char *filename, char *product, bool security)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
success = update_database(db, package, version, security, &stats);
|
||||
free(package);
|
||||
free(version);
|
||||
free(download_uri);
|
||||
chunk_free(&deb);
|
||||
package = version = download_uri = NULL;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
fclose(file);
|
||||
@@ -351,22 +441,32 @@ static int process_packages(char *filename, char *product, bool security)
|
||||
state = SEC_UPDATE_STATE_BEGIN_PACKAGE;
|
||||
}
|
||||
}
|
||||
switch (state)
|
||||
{
|
||||
case SEC_UPDATE_STATE_END_PACKAGE:
|
||||
free(version);
|
||||
/* fall-through */
|
||||
case SEC_UPDATE_STATE_VERSION:
|
||||
free(package);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(package);
|
||||
free(version);
|
||||
free(download_uri);
|
||||
fclose(file);
|
||||
db->destroy(db);
|
||||
|
||||
/* import swid tags into strongTNC */
|
||||
if (stats.new_versions > 0)
|
||||
{
|
||||
snprintf(command, BUF_LEN, "%s importswid %s",
|
||||
tnc_manage_cmd, tmp_tag_file);
|
||||
if (system(command) != 0)
|
||||
{
|
||||
DBG1(DBG_IMV, "tag import failed");
|
||||
}
|
||||
snprintf(command, BUF_LEN, "rm %s %s",
|
||||
tmp_deb_file, tmp_tag_file);
|
||||
if (system(command) != 0)
|
||||
{
|
||||
DBG1(DBG_IMV, "removing temporary files failed");
|
||||
}
|
||||
}
|
||||
|
||||
DBG1(DBG_IMV, "processed \"%s\": %d packages, %d new versions, "
|
||||
"%d updated versions", filename, stats.packages,
|
||||
"%d updated versions", path, stats.packages,
|
||||
stats.new_versions, stats.updated_versions);
|
||||
|
||||
return (stats.new_versions + stats.updated_versions) ?
|
||||
@@ -375,7 +475,7 @@ static int process_packages(char *filename, char *product, bool security)
|
||||
|
||||
static int do_args(int argc, char *argv[])
|
||||
{
|
||||
char *filename = NULL, *product = NULL;
|
||||
char *filename = NULL, *arch = NULL, *os = NULL, *uri = NULL;
|
||||
bool security = FALSE;
|
||||
|
||||
/* reinit getopt state */
|
||||
@@ -387,15 +487,17 @@ static int do_args(int argc, char *argv[])
|
||||
|
||||
struct option long_opts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "arch", required_argument, NULL, 'a' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "file", required_argument, NULL, 'f' },
|
||||
{ "product", required_argument, NULL, 'p' },
|
||||
{ "os", required_argument, NULL, 'o' },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "security", no_argument, NULL, 's' },
|
||||
{ "uri", required_argument, NULL, 'u' },
|
||||
{ 0,0,0,0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "", long_opts, NULL);
|
||||
c = getopt_long(argc, argv, "ha:d:f:o:qsu:", long_opts, NULL);
|
||||
switch (c)
|
||||
{
|
||||
case EOF:
|
||||
@@ -403,14 +505,17 @@ static int do_args(int argc, char *argv[])
|
||||
case 'h':
|
||||
usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'a':
|
||||
arch = optarg;
|
||||
continue;
|
||||
case 'd':
|
||||
debug_level = atoi(optarg);
|
||||
continue;
|
||||
case 'f':
|
||||
filename = optarg;
|
||||
continue;
|
||||
case 'p':
|
||||
product = optarg;
|
||||
case 'o':
|
||||
os = optarg;
|
||||
continue;
|
||||
case 'q':
|
||||
stderr_quiet = TRUE;
|
||||
@@ -418,13 +523,16 @@ static int do_args(int argc, char *argv[])
|
||||
case 's':
|
||||
security = TRUE;
|
||||
continue;
|
||||
case 'u':
|
||||
uri = optarg;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (filename && product)
|
||||
if (filename && os && arch && uri)
|
||||
{
|
||||
return process_packages(filename, product, security);
|
||||
return process_packages(filename, os, arch, uri, security);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -447,7 +555,8 @@ int main(int argc, char *argv[])
|
||||
exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
|
||||
}
|
||||
if (!lib->plugins->load(lib->plugins,
|
||||
lib->settings->get_str(lib->settings, "sec-updater.load", "sqlite")))
|
||||
lib->settings->get_str(lib->settings, "sec-updater.load",
|
||||
"sqlite curl")))
|
||||
{
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ UBUNTU_ARCH="binary-amd64"
|
||||
DEBIAN="http://security.debian.org"
|
||||
DEBIAN_VERSIONS="jessie wheezy"
|
||||
DEBIAN_DIRS="main contrib non-free"
|
||||
DEBIAN_ARCH="binary-amd64"
|
||||
DEBIAN_ARCH="binary-amd64 binary-armhf"
|
||||
RASPIAN="http://archive.raspberrypi.org/debian"
|
||||
RASPIAN_VERSIONS="jessie wheezy"
|
||||
RASPIAN_DIRS="main"
|
||||
@@ -74,66 +74,88 @@ done
|
||||
for f in xenial-security/binary-amd64/*
|
||||
do
|
||||
echo "security: $f"
|
||||
$CMD --product "Ubuntu 16.04 x86_64" --file $f --security >> $CMD_LOG 2>&1
|
||||
$CMD --os "Ubuntu 16.04" --arch "x86_64" --file $f --security \
|
||||
--uri $UBUNTU >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
echo $DEL_LOG
|
||||
fi
|
||||
done
|
||||
|
||||
for f in xenial-updates/binary-amd64/*
|
||||
do
|
||||
echo "updates: $f"
|
||||
$CMD --product "Ubuntu 16.04 x86_64" --file $f >> $CMD_LOG 2>&1
|
||||
$CMD --os "Ubuntu 16.04" --arch "x86_64" --file $f \
|
||||
--uri $UBUNTU >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
echo $DEL_LOG
|
||||
fi
|
||||
done
|
||||
|
||||
for f in jessie-updates/binary-amd64/*
|
||||
do
|
||||
echo "security: $f"
|
||||
$CMD --product "Debian 8.0 x86_64" --file $f --security >> $CMD_LOG 2>&1
|
||||
$CMD --os "Debian 8.0" --arch "x86_64" --file $f --security \
|
||||
--uri $DEBIAN >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
echo $DEL_LOG
|
||||
fi
|
||||
done
|
||||
|
||||
for f in wheezy-updates/binary-amd64/*
|
||||
do
|
||||
echo "security: $f"
|
||||
$CMD --product "Debian 7.0 x86_64" --file $f --security >> $CMD_LOG 2>&1
|
||||
$CMD --os "Debian 7.0" --arch "x86_64" --file $f --security \
|
||||
--uri $DEBIAN >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
fi
|
||||
done
|
||||
|
||||
for f in jessie-updates/binary-armhf/*
|
||||
do
|
||||
echo "security: $f"
|
||||
$CMD --os "Debian 8.0" --arch "armhf" --file $f --security \
|
||||
--uri $DEBIAN >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
fi
|
||||
done
|
||||
|
||||
for f in wheezy-updates/binary-armhf/*
|
||||
do
|
||||
echo "security: $f"
|
||||
$CMD --os "Debian 7.0" --arch "armhf" --file $f --security \
|
||||
--uri $DEBIAN >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
echo $DEL_LOG
|
||||
fi
|
||||
done
|
||||
|
||||
for f in jessie-raspian/binary-armhf/*
|
||||
do
|
||||
echo "security: $f"
|
||||
$CMD --product "Debian 8.0 armv7l" --file $f --security >> $CMD_LOG 2>&1
|
||||
$CMD --os "Debian 8.0" --arch "armv7l" --file $f --security \
|
||||
--uri $RASPIAN >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
echo $DEL_LOG
|
||||
fi
|
||||
done
|
||||
|
||||
for f in wheezy-raspian/binary-armhf/*
|
||||
do
|
||||
echo "security: $f"
|
||||
$CMD --product "Debian 7.11 armv7l" --file $f --security >> $CMD_LOG 2>&1
|
||||
$CMD --os "Debian 7.11" --arch "armv7l" --file $f --security \
|
||||
--uri $RASPIAN >> $CMD_LOG 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
DEL_LOG=0
|
||||
echo $DEL_LOG
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user