diff options
Diffstat (limited to 'src/libimcv/swid_gen')
-rw-r--r-- | src/libimcv/swid_gen/swid_gen.c | 291 | ||||
-rw-r--r-- | src/libimcv/swid_gen/swid_gen.h | 69 | ||||
-rw-r--r-- | src/libimcv/swid_gen/swid_gen_info.c | 174 | ||||
-rw-r--r-- | src/libimcv/swid_gen/swid_gen_info.h | 69 |
4 files changed, 603 insertions, 0 deletions
diff --git a/src/libimcv/swid_gen/swid_gen.c b/src/libimcv/swid_gen/swid_gen.c new file mode 100644 index 000000000..206d41d11 --- /dev/null +++ b/src/libimcv/swid_gen/swid_gen.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2017 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 +#include <stdio.h> + +#include "swid_gen.h" + +#include <bio/bio_writer.h> + +#define SWID_GENERATOR "/usr/local/bin/swid_generator" + +typedef struct private_swid_gen_t private_swid_gen_t; + +/** + * Private data of a swid_gen_t object. + * + */ +struct private_swid_gen_t { + + /** + * Public swid_gen_t interface. + */ + swid_gen_t public; + + /** + * Path of the SWID generator command + */ + char *generator; + + /** + * Entity name of the tagCreator + */ + char *entity; + + /** + * Regid of the tagCreator + */ + char *regid; + +}; + +METHOD(swid_gen_t, generate_tag, char*, + private_swid_gen_t *this, char *sw_id, char *package, char *version, + bool full, bool pretty) +{ + char *tag = NULL; + size_t tag_buf_len = 8192; + char tag_buf[tag_buf_len], command[BUF_LEN]; + bio_writer_t *writer; + chunk_t swid_tag; + FILE *file; + + /* Compose the SWID generator command */ + if (full || !package || !version) + { + snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" " + "--regid %s --software-id %s%s%s", + this->generator, this->entity, this->regid, sw_id, + full ? " --full" : "", pretty ? " --pretty" : ""); + } + else + { + snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" " + "--regid %s --name %s --version-string %s%s", + this->generator, this->entity, this->regid, package, + version, pretty ? " --pretty" : ""); + } + + /* Open a pipe stream for reading the SWID generator output */ + file = popen(command, "r"); + if (file) + { + writer = bio_writer_create(tag_buf_len); + while (TRUE) + { + if (!fgets(tag_buf, tag_buf_len, file)) + { + break; + } + writer->write_data(writer, chunk_create(tag_buf, strlen(tag_buf))); + } + pclose(file); + swid_tag = writer->extract_buf(writer); + writer->destroy(writer); + + if (swid_tag.len > 0) + { + tag = swid_tag.ptr; + tag[swid_tag.len - 1] = '\0'; + } + else + { + chunk_free(&swid_tag); + } + } + else + { + DBG1(DBG_IMC, "failed to run swid_generator command"); + } + + return tag; +} + +typedef struct { + /** public enumerator interface */ + enumerator_t public; + /** swid_generator output stream */ + FILE *file; + /** generate software identifier only */ + bool sw_id_only; +} swid_gen_enumerator_t; + +METHOD(enumerator_t, enumerate, bool, + swid_gen_enumerator_t *this, va_list args) +{ + chunk_t *out; + + VA_ARGS_VGET(args, out); + + if (this->sw_id_only) + { + char line[BUF_LEN]; + size_t len; + + if (!fgets(line, sizeof(line), this->file)) + { + return FALSE; + } + len = strlen(line); + + if (len == 0) + { + return FALSE; + } + + /* remove trailing newline if present */ + if (line[len - 1] == '\n') + { + len--; + } + DBG3(DBG_IMC, " %.*s", len, line); + *out = chunk_clone(chunk_create(line, len)); + } + else + { + bool last_newline = TRUE; + size_t len, line_len = 8192; + char line[line_len]; + bio_writer_t *writer; + chunk_t swid_tag; + + writer = bio_writer_create(line_len); + while (TRUE) + { + if (!fgets(line, line_len, this->file)) + { + break; + } + len = strlen(line); + + if (last_newline && line[0] == '\n') + { + break; + } + else + { + last_newline = (line[len-1] == '\n'); + writer->write_data(writer, chunk_create(line, len)); + } + } + swid_tag = writer->extract_buf(writer); + writer->destroy(writer); + + if (swid_tag.len <= 1) + { + chunk_free(&swid_tag); + return FALSE; + } + + /* remove trailing newline if present */ + if (swid_tag.ptr[swid_tag.len - 1] == '\n') + { + swid_tag.len--; + } + DBG3(DBG_IMC, " %.*s", swid_tag.len, swid_tag.ptr); + *out = swid_tag; + } + + return TRUE; +} + +METHOD(enumerator_t, enumerator_destroy, void, + swid_gen_enumerator_t *this) +{ + pclose(this->file); + free(this); +} + +METHOD(swid_gen_t, create_tag_enumerator, enumerator_t*, + private_swid_gen_t *this, bool sw_id_only, bool full, bool pretty) +{ + swid_gen_enumerator_t *enumerator; + char command[BUF_LEN]; + char doc_separator[] = "'\n\n'"; + FILE *file; + + /* Assemble the SWID generator command */ + if (sw_id_only) + { + snprintf(command, BUF_LEN, "%s software-id --regid %s ", + this->generator, this->regid); + } + else + { + snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" --regid %s " + "--doc-separator %s%s%s", this->generator, this->entity, + this->regid, doc_separator, pretty ? " --pretty" : "", + full ? " --full" : ""); + } + + /* Open a pipe stream for reading the SWID generator output */ + file = popen(command, "r"); + if (!file) + { + DBG1(DBG_IMC, "failed to run swid_generator command"); + return NULL; + } + + INIT(enumerator, + .public = { + .enumerate = enumerator_enumerate_default, + .venumerate = _enumerate, + .destroy = _enumerator_destroy, + }, + .sw_id_only = sw_id_only, + .file = file, + ); + + return &enumerator->public; +} + +METHOD(swid_gen_t, destroy, void, + private_swid_gen_t *this) +{ + free(this->generator); + free(this->entity); + free(this->regid); + free(this); +} + +/** + * See header + */ +swid_gen_t *swid_gen_create(void) +{ + private_swid_gen_t *this; + char *entity, *regid, *generator; + + entity = lib->settings->get_str(lib->settings, + "libimcv.swid_gen.tag_creator.name", "strongSwan Project"); + regid = lib->settings->get_str(lib->settings, + "libimcv.swid_gen.tag_creator.regid", "strongswan.org"); + generator = lib->settings->get_str(lib->settings, + "libimcv.swid_gen.command", SWID_GENERATOR); + + INIT(this, + .public = { + .generate_tag = _generate_tag, + .create_tag_enumerator = _create_tag_enumerator, + .destroy = _destroy, + }, + .generator = strdup(generator), + .entity = strdup(entity), + .regid = strdup(regid), + ); + + return &this->public; +} diff --git a/src/libimcv/swid_gen/swid_gen.h b/src/libimcv/swid_gen/swid_gen.h new file mode 100644 index 000000000..c143f292d --- /dev/null +++ b/src/libimcv/swid_gen/swid_gen.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @defgroup swid_gen swid_gen + * @{ @ingroup libimcv + */ + +#ifndef SWID_GEN_H_ +#define SWID_GEN_H_ + +#include <library.h> + +typedef struct swid_gen_t swid_gen_t; + +/** + * Class generating a either a full or a minimalistic ISO 19770-2:2015 SWID tag + */ +struct swid_gen_t { + + /** + * Generate a SWID tag + * + * @param sw_id Software identifier + * @param package Package name (can be NULL) + * @param version Package version (can be NULL) + * @param full Generate full SWID tags with file information + * @param pretty Generate SWID tags with pretty formatting + * @return SWID tag + */ + char* (*generate_tag)(swid_gen_t *this, char *sw_id, char *package, + char *version, bool full, bool pretty); + + /** + * Generate a SWID tag + * + * @param sw_id_only Return software identifier only + * @param full Generate full SWID tags with file information + * @param pretty Generate SWID tags with pretty formatting + * @return Tag enumerator (sw_id, tag) + */ + enumerator_t* (*create_tag_enumerator)(swid_gen_t *this, bool sw_id_only, + bool full, bool pretty); + + /** + * Destroys a swid_gen_t object. + */ + void (*destroy)(swid_gen_t *this); + +}; + +/** + * Creates a swid_gen_t object + */ +swid_gen_t* swid_gen_create(void); + +#endif /** SWID_GEN_H_ @}*/ diff --git a/src/libimcv/swid_gen/swid_gen_info.c b/src/libimcv/swid_gen/swid_gen_info.c new file mode 100644 index 000000000..bdaeedce7 --- /dev/null +++ b/src/libimcv/swid_gen/swid_gen_info.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2017 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 +#include <stdio.h> + +#include "swid_gen_info.h" + +#include <library.h> +#include <utils/lexparser.h> + +typedef struct private_swid_gen_info_t private_swid_gen_info_t; + +/** + * Private data of an swid_gen_info_t object. + */ +struct private_swid_gen_info_t { + + /** + * Public members of swid_gen_info_state_t + */ + swid_gen_info_t public; + + /** + * tagCreator + */ + char *tag_creator; + + /** + * OS string 'Name_Version-Arch' + */ + char *os; + + /** + * Product string 'Name Version Arch' + */ + char *product; + + /** + * OS info about endpoint + */ + imc_os_info_t *os_info; + +}; + +/** + * Replaces invalid character by a valid one + */ +static void sanitize_uri(char *uri, char a, char b) +{ + char *pos = uri; + + while (TRUE) + { + pos = strchr(pos, a); + if (!pos) + { + break; + } + *pos = b; + pos++; + } +} + +METHOD(swid_gen_info_t, get_os_type, os_type_t, + private_swid_gen_info_t *this) +{ + return this->os_info->get_type(this->os_info); +} + +METHOD(swid_gen_info_t, get_os, char*, + private_swid_gen_info_t *this, char **product) +{ + if (product) + { + *product = this->product; + } + return this->os; +} + +METHOD(swid_gen_info_t, create_sw_id, char*, + private_swid_gen_info_t *this, char *package, char *version) +{ + char *sw_id; + + if (asprintf(&sw_id, "%s__%s-%s%s%s", this->tag_creator, this->os, + package, strlen(version) ? "-" : "", version) == -1) + { + return NULL; + } + sanitize_uri(sw_id, ':', '~'); + sanitize_uri(sw_id, '+', '~'); + + return sw_id; +} + +METHOD(swid_gen_info_t, destroy, void, + private_swid_gen_info_t *this) +{ + this->os_info->destroy(this->os_info); + free(this->os); + free(this->product); + free(this->tag_creator); + free(this); +} + +/** + * Described in header. + */ +swid_gen_info_t *swid_gen_info_create(void) +{ + private_swid_gen_info_t *this; + chunk_t os_name, os_version, os_arch; + char *tag_creator; + + tag_creator = lib->settings->get_str(lib->settings, + "libimcv.swid_gen.tag_creator.regid", "strongswan.org"); + + INIT(this, + .public = { + .get_os_type = _get_os_type, + .get_os = _get_os, + .create_sw_id = _create_sw_id, + .destroy = _destroy, + }, + .os_info = imc_os_info_create(), + .tag_creator = strdup(tag_creator), + ); + + os_name = this->os_info->get_name(this->os_info); + os_arch = this->os_info->get_version(this->os_info); + + /* get_version() returns version followed by arch */ + if (!extract_token(&os_version, ' ', &os_arch)) + { + DBG1(DBG_IMC, "separation of OS version from arch failed"); + destroy(this); + return NULL; + } + + /* construct OS string */ + if (asprintf(&this->os, "%.*s_%.*s-%.*s", (int)os_name.len, os_name.ptr, + (int)os_version.len, os_version.ptr, (int)os_arch.len, + os_arch.ptr) == -1) + { + DBG1(DBG_IMC, "constructon of OS string failed"); + destroy(this); + return NULL; + } + + /* construct product string */ + if (asprintf(&this->product, "%.*s %.*s %.*s", (int)os_name.len, + os_name.ptr, (int)os_version.len, os_version.ptr, + (int)os_arch.len, os_arch.ptr) == -1) + { + DBG1(DBG_IMC, "constructon of product string failed"); + destroy(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libimcv/swid_gen/swid_gen_info.h b/src/libimcv/swid_gen/swid_gen_info.h new file mode 100644 index 000000000..b99fec4f3 --- /dev/null +++ b/src/libimcv/swid_gen/swid_gen_info.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * @defgroup sw_collector sw-collector + * + * @defgroup swid_gen_info_t swid_gen_info + * @{ @ingroup sw_collector + */ + +#ifndef SWID_GEN_INFO_H_ +#define SWID_GEN_INFO_H_ + +typedef struct swid_gen_info_t swid_gen_info_t; + +#include "imc/imc_os_info.h" + +struct swid_gen_info_t { + + /** + * Get OS type + * + * @return OS type + */ + os_type_t (*get_os_type)(swid_gen_info_t *this); + + /** + * Get OS and product strings + * + * @param product Product string 'Name Version Arch' + * @return OS string 'Name_Version-Arch' + */ + char* (*get_os)(swid_gen_info_t *this, char **product); + + /** + * Create software identifier including tagCreator and OS + * + * @param package Package string + * @param version Version string + * @return Software Identifier string + */ + char* (*create_sw_id)(swid_gen_info_t *this, char *package, + char *version); + + /** + * Destroy swid_gen_info_t object + */ + void (*destroy)(swid_gen_info_t *this); + +}; + +/** + * Create an swid_gen_info_t instance + */ +swid_gen_info_t* swid_gen_info_create(void); + +#endif /** SWID_GEN_INFO_H_ @}*/ |