diff options
Diffstat (limited to 'src/libimcv/swid/swid_inventory.c')
-rw-r--r-- | src/libimcv/swid/swid_inventory.c | 302 |
1 files changed, 95 insertions, 207 deletions
diff --git a/src/libimcv/swid/swid_inventory.c b/src/libimcv/swid/swid_inventory.c index a49286954..5f6e50cb7 100644 --- a/src/libimcv/swid/swid_inventory.c +++ b/src/libimcv/swid/swid_inventory.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Andreas Steffen + * Copyright (C) 2013-2017 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -16,9 +16,10 @@ #include "swid_inventory.h" #include "swid_tag.h" #include "swid_tag_id.h" +#include "swid_gen/swid_gen.h" #include <collections/linked_list.h> -#include <bio/bio_writer.h> +#include <utils/lexparser.h> #include <utils/debug.h> #include <stdio.h> @@ -52,192 +53,99 @@ struct private_swid_inventory_t { linked_list_t *list; }; -/** - * Read SWID tags issued by the swid_generator tool - */ -static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file) +static status_t generate_tags(private_swid_inventory_t *this, + swid_inventory_t *targets, bool pretty, bool full) { + swid_gen_t *swid_gen; swid_tag_t *tag; - bio_writer_t *writer; - chunk_t tag_encoding, tag_file_path = chunk_empty; - bool more_tags = TRUE, last_newline; - char line[8192]; - size_t len; - - while (more_tags) - { - last_newline = TRUE; - writer = bio_writer_create(512); - while (TRUE) - { - if (!fgets(line, sizeof(line), file)) - { - more_tags = FALSE; - 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)); - } - } - - tag_encoding = writer->get_buf(writer); - - if (tag_encoding.len > 1) - { - /* remove trailing newline if present */ - if (tag_encoding.ptr[tag_encoding.len - 1] == '\n') - { - tag_encoding.len--; - } - DBG3(DBG_IMC, " %.*s", tag_encoding.len, tag_encoding.ptr); - - tag = swid_tag_create(tag_encoding, tag_file_path); - this->list->insert_last(this->list, tag); - } - writer->destroy(writer); - } - - return SUCCESS; -} - -/** - * Read SWID tag or software IDs issued by the swid_generator tool - */ -static status_t read_swid_tag_ids(private_swid_inventory_t *this, FILE *file) -{ swid_tag_id_t *tag_id; - chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty; - char line[BUF_LEN]; - - while (TRUE) - { - char *separator; - size_t len; - - if (!fgets(line, sizeof(line), file)) - { - return SUCCESS; - } - len = strlen(line); - - /* remove trailing newline if present */ - if (len > 0 && line[len - 1] == '\n') - { - len--; - } - DBG3(DBG_IMC, " %.*s", len, line); - - separator = strchr(line, '_'); - if (!separator) - { - DBG1(DBG_IMC, "separation of regid from unique software ID failed"); - return FAILED; - } - tag_creator = chunk_create(line, separator - line); - separator++; - - unique_sw_id = chunk_create(separator, len - (separator - line)); - tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path); - this->list->insert_last(this->list, tag_id); - } -} - -static status_t generate_tags(private_swid_inventory_t *this, char *generator, - swid_inventory_t *targets, bool pretty, bool full) -{ - FILE *file; - char command[BUF_LEN]; - char doc_separator[] = "'\n\n'"; - + enumerator_t *enumerator; status_t status = SUCCESS; + chunk_t out; + + swid_gen = swid_gen_create(); if (targets->get_count(targets) == 0) { - /* Assemble the SWID generator command */ - if (this->full_tags) - { - snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s", - generator, doc_separator, pretty ? " --pretty" : "", - full ? " --full" : ""); - } - else - { - snprintf(command, BUF_LEN, "%s software-id", generator); - } + DBG2(DBG_IMC, "SWID tag%s generation by package manager", + this->full_tags ? "" : " ID"); - /* Open a pipe stream for reading the SWID generator output */ - file = popen(command, "r"); - if (!file) + enumerator = swid_gen->create_tag_enumerator(swid_gen, !this->full_tags, + full, pretty); + if (enumerator) { - DBG1(DBG_IMC, "failed to run swid_generator command"); - return NOT_SUPPORTED; - } + while (enumerator->enumerate(enumerator, &out)) + { + if (this->full_tags) + { + chunk_t swid_tag = out; - if (this->full_tags) - { - DBG2(DBG_IMC, "SWID tag generation by package manager"); - status = read_swid_tags(this, file); + tag = swid_tag_create(swid_tag, chunk_empty); + this->list->insert_last(this->list, tag); + } + else + { + chunk_t tag_creator, sw_id = out; + + if (extract_token_str(&tag_creator, "__", &sw_id)) + { + tag_id = swid_tag_id_create(tag_creator, sw_id, + chunk_empty); + this->list->insert_last(this->list, tag_id); + } + else + { + DBG1(DBG_IMC, "separation of regid from unique " + "software ID failed"); + status = FAILED; + chunk_free(&out); + break; + } + } + chunk_free(&out); + } + enumerator->destroy(enumerator); } else { - DBG2(DBG_IMC, "SWID tag ID generation by package manager"); - status = read_swid_tag_ids(this, file); + status = NOT_SUPPORTED; } - pclose(file); } else if (this->full_tags) { - swid_tag_id_t *tag_id; - enumerator_t *enumerator; + DBG2(DBG_IMC, "targeted SWID tag generation"); enumerator = targets->create_enumerator(targets); while (enumerator->enumerate(enumerator, &tag_id)) { - char software_id[BUF_LEN]; - chunk_t tag_creator, unique_sw_id; + char software_id[BUF_LEN], *swid_tag; + chunk_t tag_creator, sw_id; + /* Construct software ID from tag creator and unique software ID */ tag_creator = tag_id->get_tag_creator(tag_id); - unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL); - snprintf(software_id, BUF_LEN, "%.*s_%.*s", - tag_creator.len, tag_creator.ptr, - unique_sw_id.len, unique_sw_id.ptr); - - /* Assemble the SWID generator command */ - snprintf(command, BUF_LEN, "%s swid --software-id %s%s%s", - generator, software_id, 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 NOT_SUPPORTED; - } - status = read_swid_tags(this, file); - pclose(file); - - if (status != SUCCESS) + sw_id = tag_id->get_unique_sw_id(tag_id, NULL); + snprintf(software_id, BUF_LEN, "%.*s__%.*s", + (int)tag_creator.len, tag_creator.ptr, + (int)sw_id.len, sw_id.ptr); + + swid_tag = swid_gen->generate_tag(swid_gen, software_id, NULL, NULL, + full, pretty); + if (swid_tag) { - break; + tag = swid_tag_create(chunk_from_str(swid_tag), chunk_empty); + this->list->insert_last(this->list, tag); + free(swid_tag); } } enumerator->destroy(enumerator); } + swid_gen->destroy(swid_gen); return status; } static bool collect_tags(private_swid_inventory_t *this, char *pathname, - swid_inventory_t *targets) + swid_inventory_t *targets, bool is_swidtag_dir) { char *rel_name, *abs_name; struct stat st; @@ -251,72 +159,49 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, pathname, strerror(errno)); return FALSE; } - DBG2(DBG_IMC, "entering %s", pathname); + if (is_swidtag_dir) + { + DBG2(DBG_IMC, "entering %s", pathname); + } while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st)) { - char * start, *stop; + char *separator, *suffix; chunk_t tag_creator; chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty; - if (!strstr(rel_name, "regid.")) - { - continue; - } if (S_ISDIR(st.st_mode)) { - /* In case of a targeted request */ - if (targets->get_count(targets)) - { - enumerator_t *target_enumerator; - swid_tag_id_t *tag_id; - bool match = FALSE; - - target_enumerator = targets->create_enumerator(targets); - while (target_enumerator->enumerate(target_enumerator, &tag_id)) - { - if (chunk_equals(tag_id->get_tag_creator(tag_id), - chunk_from_str(rel_name))) - { - match = TRUE; - break; - } - } - target_enumerator->destroy(target_enumerator); - - if (!match) - { - continue; - } - } - - if (!collect_tags(this, abs_name, targets)) + if (!collect_tags(this, abs_name, targets, is_swidtag_dir || + streq(rel_name, "swidtag"))) { goto end; } continue; } + if (!is_swidtag_dir) + { + continue; + } - /* parse the regid filename into its components */ - start = rel_name; - stop = strchr(start, '_'); - if (!stop) + /* found a swidtag file? */ + suffix = strstr(rel_name, ".swidtag"); + if (!suffix) { - DBG1(DBG_IMC, " %s", rel_name); - DBG1(DBG_IMC, " '_' separator not found"); - goto end; + continue; } - tag_creator = chunk_create(start, stop-start); - start = stop + 1; - stop = strstr(start, ".swidtag"); - if (!stop) + /* parse the swidtag filename into its components */ + separator = strstr(rel_name, "__"); + if (!separator) { DBG1(DBG_IMC, " %s", rel_name); - DBG1(DBG_IMC, " swidtag postfix not found"); + DBG1(DBG_IMC, " '__' separator not found"); goto end; } - unique_sw_id = chunk_create(start, stop-start); + tag_creator = chunk_create(rel_name, separator-rel_name); + + unique_sw_id = chunk_create(separator+2, suffix-separator-2); tag_file_path = chunk_from_str(abs_name); /* In case of a targeted request */ @@ -334,7 +219,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, target_tag_creator = tag_id->get_tag_creator(tag_id); if (chunk_equals(target_unique_sw_id, unique_sw_id) && - chunk_equals(target_tag_creator, tag_creator)) + chunk_equals(target_tag_creator, tag_creator)) { match = TRUE; break; @@ -358,7 +243,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, if (!xml_tag) { DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name, - strerror(errno)); + strerror(errno)); goto end; } @@ -378,25 +263,28 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, end: enumerator->destroy(enumerator); - DBG2(DBG_IMC, "leaving %s", pathname); + if (is_swidtag_dir) + { + DBG2(DBG_IMC, "leaving %s", pathname); + } return success; } METHOD(swid_inventory_t, collect, bool, - private_swid_inventory_t *this, char *directory, char *generator, - swid_inventory_t *targets, bool pretty, bool full) + private_swid_inventory_t *this, char *directory, swid_inventory_t *targets, + bool pretty, bool full) { /** * Tags are generated by a package manager */ - generate_tags(this, generator, targets, pretty, full); + generate_tags(this, targets, pretty, full); /** * Collect swidtag files by iteratively entering all directories in * the tree under the "directory" path. */ - return collect_tags(this, directory, targets); + return collect_tags(this, directory, targets, FALSE); } METHOD(swid_inventory_t, add, void, |