From b7679e90e34519417792ac469584e1e9b8da6831 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Fri, 23 May 2014 23:26:44 +0200 Subject: [PATCH] Support targeted retrieval of SWID tags --- src/libpts/swid/swid_inventory.c | 281 +++++++++++++++++++------------ 1 file changed, 176 insertions(+), 105 deletions(-) diff --git a/src/libpts/swid/swid_inventory.c b/src/libpts/swid/swid_inventory.c index f81d9a92b..4e696ef33 100644 --- a/src/libpts/swid/swid_inventory.c +++ b/src/libpts/swid/swid_inventory.c @@ -52,120 +52,188 @@ 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) +{ + swid_tag_t *tag; + bio_writer_t *writer; + chunk_t tag_encoding, tag_file_path = chunk_empty; + bool more_tags = TRUE, end_of_tag; + char line[131072]; + + while (more_tags) + { + end_of_tag = FALSE; + writer = bio_writer_create(512); + do + { + if (fgets(line, sizeof(line), file) <= 0) + { + more_tags = FALSE; + end_of_tag = TRUE; + break; + } + if (line[0] == '\n') + { + end_of_tag = TRUE; + break; + } + else + { + writer->write_data(writer, chunk_from_str(line)); + } + } + while (!end_of_tag); + + 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--; + } + DBG2(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) <= 0) + { + return SUCCESS; + } + len = strlen(line); + + /* remove trailing newline if present */ + if (len > 0 && line[len - 1] == '\n') + { + len--; + } + DBG2(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[512], line[2048]; - char entity_name = "strongSwan Project"; - chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty; - swid_tag_id_t *tag_id; - swid_tag_t *tag; + char command[BUF_LEN]; + char entity_name[] = "strongSwan Project"; status_t status = SUCCESS; - /* Assemble the SWID generator command */ - snprintf(command, sizeof(command), "%s %s %s%s%s%s\n", generator, - (this->full_tags) ? "swid" : "software-id", - (this->full_tags && entity_name) ? entity_name : "", - (this->full_tags && pretty) ? " --pretty" : "", - (this->full_tags && !pretty) ? " --doc-separator $'\n\n'" : "", - (this->full_tags && full) ? " --full" : ""); - - /* Open a pipe stream for reading the output of the dpkg-query commmand */ - file = popen(command, "r"); - if (!file) + if (targets->get_count(targets) == 0) { - DBG1(DBG_IMC, "failed to run swid_generator command"); - return NOT_SUPPORTED; - } - if (this->full_tags) - { - bio_writer_t *writer; - chunk_t tag_encoding; - bool more_tags = TRUE, end_of_tag; - - DBG2(DBG_IMC, "SWID tags generated by package manager:"); - while (more_tags) + /* Assemble the SWID generator command */ + if (this->full_tags) { - end_of_tag = FALSE; - writer = bio_writer_create(512); - do - { - if (fgets(line, sizeof(line), file) <= 0) - { - more_tags = FALSE; - end_of_tag = TRUE; - break; - } - if (line[0] == '\n') - { - end_of_tag = TRUE; - break; - } - else - { - writer->write_data(writer, chunk_from_str(line)); - } - } - while (!end_of_tag); - - 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--; - } - DBG2(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); + snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" %s%s", + generator, entity_name, + pretty ? "--pretty" : "--doc-separator $'\n\n'", + full ? " --full" : ""); } - } - else - { - DBG2(DBG_IMC, "SWID tag IDs generated by package manager:"); - while (TRUE) + else { - char *separator; - size_t len; - - if (fgets(line, sizeof(line), file) <= 0) - { - goto end; - } - len = strlen(line); - - /* remove trailing newline if present */ - if (len > 0 && line[len - 1] == '\n') - { - len--; - } - DBG2(DBG_IMC, " %.*s", len, line); - - separator = strchr(line, '_'); - if (!separator) - { - DBG1(DBG_IMC, "separation of regid from unique software ID " - "failed"); - status = FAILED; - goto end; - } - 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); + snprintf(command, BUF_LEN, "%s software-id", generator); } + + /* 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; + } + + if (this->full_tags) + { + DBG2(DBG_IMC, "SWID tags generated by package manager:"); + status = read_swid_tags(this, file); + } + else + { + DBG2(DBG_IMC, "SWID tag IDs generated by package manager:"); + status = read_swid_tag_ids(this, file); + } + pclose(file); + } + else if (this->full_tags) + { + swid_tag_id_t *tag_id; + enumerator_t *enumerator; + + enumerator = targets->create_enumerator(targets); + while (enumerator->enumerate(enumerator, &tag_id)) + { + char software_id[BUF_LEN]; + chunk_t tag_creator, unique_sw_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 " + "--entity-name \"%s\"%s%s", + generator, software_id, entity_name, + 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) + { + break; + } + } + enumerator->destroy(enumerator); } -end: - pclose(file); return status; } @@ -191,6 +259,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, char * start, *stop; chunk_t tag_creator; chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty; + if (!strstr(rel_name, "regid.")) { continue; @@ -254,6 +323,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, /* In case of a targeted request */ if (targets->get_count(targets)) { + chunk_t target_unique_sw_id, target_tag_creator; enumerator_t *target_enumerator; swid_tag_id_t *tag_id; bool match = FALSE; @@ -261,10 +331,11 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname, target_enumerator = targets->create_enumerator(targets); while (target_enumerator->enumerate(target_enumerator, &tag_id)) { - if (chunk_equals(tag_id->get_unique_sw_id(tag_id, NULL), - unique_sw_id) && - chunk_equals(tag_id->get_tag_creator(tag_id), - tag_creator)) + target_unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL); + 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)) { match = TRUE; break;