Support targeted retrieval of SWID tags
[strongswan.git] / src / libpts / swid / swid_inventory.c
index f81d9a9..4e696ef 100644 (file)
@@ -52,120 +52,188 @@ struct private_swid_inventory_t {
        linked_list_t *list;
 };
 
-static status_t generate_tags(private_swid_inventory_t *this, char *generator,
-                                                         swid_inventory_t *targets, bool pretty, bool full)
+/**
+ * Read SWID tags issued by the swid_generator tool
+ */
+static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file)
 {
-       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;
-       status_t status = SUCCESS;
+       bio_writer_t *writer;
+       chunk_t tag_encoding, tag_file_path = chunk_empty;
+       bool more_tags = TRUE, end_of_tag;
+       char line[131072];
 
-       /* 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)
-       {
-               DBG1(DBG_IMC, "failed to run swid_generator command");
-               return NOT_SUPPORTED;
-       }
-       if (this->full_tags)
+       while (more_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)
+               end_of_tag = FALSE;
+               writer = bio_writer_create(512);
+               do
                {
-                       end_of_tag = FALSE;
-                       writer = bio_writer_create(512);
-                       do
+                       if (fgets(line, sizeof(line), file) <= 0)
                        {
-                               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));
-                               }
+                               more_tags = FALSE;
+                               end_of_tag = TRUE;
+                               break;
+                       }
+                       if (line[0] == '\n')
+                       {
+                               end_of_tag = TRUE;
+                               break;
                        }
-                       while (!end_of_tag);
+                       else
+                       {
+                               writer->write_data(writer, chunk_from_str(line));
+                       }
+               }
+               while (!end_of_tag);
 
-                       tag_encoding = writer->get_buf(writer);
+               tag_encoding = writer->get_buf(writer);
 
-                       if (tag_encoding.len > 1)
+               if (tag_encoding.len > 1)
+               {
+                       /* remove trailing newline if present */
+                       if (tag_encoding.ptr[tag_encoding.len - 1] == '\n')
                        {
-                               /* 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);
+                               tag_encoding.len--;
                        }
-                       writer->destroy(writer);
+                       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);
        }
-       else
+
+       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)
        {
-               DBG2(DBG_IMC, "SWID tag IDs generated by package manager:");
-               while (TRUE)
+               char *separator;
+               size_t len;
+
+               if (fgets(line, sizeof(line), file) <= 0)
                {
-                       char *separator;
-                       size_t len;
+                       return SUCCESS;
+               }
+               len = strlen(line);
 
-                       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);
 
-                       /* remove trailing newline if present */
-                       if (len > 0 && line[len - 1] == '\n')
+               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 entity_name[] = "strongSwan Project";
+       status_t status = SUCCESS;
+
+       if (targets->get_count(targets) == 0)
+       {
+               /* Assemble the SWID generator command */
+               if (this->full_tags)
+               {
+                       snprintf(command, BUF_LEN, "%s swid --entity-name \"%s\" %s%s",
+                                        generator, entity_name,
+                                        pretty ? "--pretty" : "--doc-separator $'\n\n'",
+                                        full   ? " --full" : "");
+               }
+               else
+               {
+                       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)
                        {
-                               len--;
+                               DBG1(DBG_IMC, "failed to run swid_generator command");
+                               return NOT_SUPPORTED;
                        }
-                       DBG2(DBG_IMC, "  %.*s", len, line);
+                       status = read_swid_tags(this, file);
+                       pclose(file);
 
-                       separator = strchr(line, '_');
-                       if (!separator)
+                       if (status != SUCCESS)
                        {
-                               DBG1(DBG_IMC, "separation of regid from unique software ID "
-                                                         "failed");
-                               status = FAILED;
-                               goto end;
+                               break;
                        }
-                       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);
                }
+               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;