Blame utils/oscap-info.c

Packit 517ee8
/*
Packit 517ee8
 * Copyright 2010--2014 Red Hat Inc., Durham, North Carolina.
Packit 517ee8
 * All Rights Reserved.
Packit 517ee8
 *
Packit 517ee8
 * This library is free software; you can redistribute it and/or
Packit 517ee8
 * modify it under the terms of the GNU Lesser General Public
Packit 517ee8
 * License as published by the Free Software Foundation; either
Packit 517ee8
 * version 2.1 of the License, or (at your option) any later version.
Packit 517ee8
 *
Packit 517ee8
 * This library is distributed in the hope that it will be useful,
Packit 517ee8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 517ee8
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 517ee8
 * Lesser General Public License for more details.
Packit 517ee8
 *
Packit 517ee8
 * You should have received a copy of the GNU Lesser General Public
Packit 517ee8
 * License along with this library; if not, write to the Free Software
Packit 517ee8
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Packit 517ee8
 *
Packit 517ee8
 * Authors:
Packit 517ee8
 *      Peter Vrabec  <pvrabec@redhat.com>
Packit 517ee8
 */
Packit 517ee8
Packit 517ee8
#ifdef HAVE_CONFIG_H
Packit 517ee8
#include <config.h>
Packit 517ee8
#endif
Packit 517ee8
Packit 517ee8
/* Standard header files */
Packit 517ee8
#include <stdio.h>
Packit 517ee8
#include <stdlib.h>
Packit 517ee8
#include <string.h>
Packit 517ee8
#ifdef HAVE_GETOPT_H
Packit 517ee8
#include <getopt.h>
Packit 517ee8
#endif
Packit 517ee8
#include <assert.h>
Packit 517ee8
#include <math.h>
Packit 517ee8
#include <time.h>
Packit 517ee8
#include <sys/types.h>
Packit 517ee8
#include <sys/stat.h>
Packit 517ee8
#include <limits.h>
Packit 517ee8
Packit 517ee8
#include <oscap.h>
Packit 517ee8
#include "oscap_source.h"
Packit 517ee8
#include <xccdf_policy.h>
Packit 517ee8
#include <oval_results.h>
Packit 517ee8
#include <oval_variables.h>
Packit 517ee8
#include <oval_system_characteristics.h>
Packit 517ee8
#include <oval_directives.h>
Packit 517ee8
#include <scap_ds.h>
Packit 517ee8
#include <ds_rds_session.h>
Packit 517ee8
#include <ds_sds_session.h>
Packit 517ee8
#include <xccdf_session.h>
Packit 517ee8
Packit 517ee8
#include "oscap-tool.h"
Packit 517ee8
Packit 517ee8
Packit 517ee8
static bool getopt_info(int argc, char **argv, struct oscap_action *action);
Packit 517ee8
static int app_info(const struct oscap_action *action);
Packit 517ee8
Packit 517ee8
struct oscap_module OSCAP_INFO_MODULE = {
Packit 517ee8
    .name = "info",
Packit 517ee8
    .parent = &OSCAP_ROOT_MODULE,
Packit 517ee8
	.summary = "Print information about a SCAP file.",
Packit 517ee8
    .usage = "some-file.xml",
Packit 517ee8
	.help = "Options:\n"
Packit 517ee8
		"   --fetch-remote-resources      - Download remote content referenced by DataStream.\n"
Packit 517ee8
		"   --profile <id>                - Show info of the profile with the given ID.\n"
Packit 517ee8
		"   --profiles                    - Show profiles from the input file in the <id>:<title> format, one line per profile.\n",
Packit 517ee8
    .opt_parser = getopt_info,
Packit 517ee8
    .func = app_info
Packit 517ee8
};
Packit 517ee8
Packit 517ee8
static void print_time(const char *file) {
Packit 517ee8
	struct stat buffer;
Packit 517ee8
	char timeStr[ 100 ] = "";
Packit 517ee8
Packit 517ee8
	if(!stat(file, &buffer)) {
Packit 517ee8
		strftime(timeStr, 100, "%Y-%m-%dT%H:%M:%S", localtime(&buffer.st_mtime));
Packit 517ee8
		printf("Imported: %s\n", timeStr);
Packit 517ee8
	}
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_status(struct xccdf_status *status, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	if (status) {
Packit 517ee8
		printf("%sStatus: %s\n", prefix, xccdf_status_type_to_text(xccdf_status_get_status(status)));
Packit 517ee8
		const time_t date_time = xccdf_status_get_date(status);
Packit 517ee8
		if (date_time != 0) {
Packit 517ee8
			struct tm *date = localtime(&date_time);
Packit 517ee8
			char date_str[] = "YYYY-DD-MM";
Packit 517ee8
			int ret = snprintf(date_str, sizeof(date_str), "%04d-%02d-%02d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday);
Packit 517ee8
			if (ret < 0) {
Packit 517ee8
				return;
Packit 517ee8
			}
Packit 517ee8
			printf("%sGenerated: %s\n", prefix, date_str);
Packit 517ee8
		}
Packit 517ee8
	}
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _remove_occurence_of_character_from_string(char *string, char c)
Packit 517ee8
{
Packit 517ee8
	char *reading_ptr = string, *writing_ptr = string;
Packit 517ee8
	while (*reading_ptr) {
Packit 517ee8
		*writing_ptr = *reading_ptr;
Packit 517ee8
		if (*reading_ptr != c)
Packit 517ee8
			writing_ptr++;
Packit 517ee8
		reading_ptr++;
Packit 517ee8
	}
Packit 517ee8
	*writing_ptr = '\0';
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _translate_character_in_string(char *string, char to_replace, char replace_with)
Packit 517ee8
{
Packit 517ee8
	char *string_iterator = string;
Packit 517ee8
	while (*string_iterator) {
Packit 517ee8
		if (*string_iterator == to_replace)
Packit 517ee8
			*string_iterator = replace_with;
Packit 517ee8
		string_iterator++;
Packit 517ee8
	}
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _print_xccdf_profile_default(const struct xccdf_profile *prof, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	struct oscap_text_iterator *title_it = xccdf_profile_get_title(prof);
Packit 517ee8
	char *profile_title = oscap_textlist_get_preferred_plaintext(title_it, NULL);
Packit 517ee8
	oscap_text_iterator_free(title_it);
Packit 517ee8
	_remove_occurence_of_character_from_string(profile_title, '\n');
Packit 517ee8
	printf("%s\tTitle: %s\n", prefix, profile_title);
Packit 517ee8
	free(profile_title);
Packit 517ee8
	printf("%s\t\tId: %s%s\n", prefix,
Packit 517ee8
		xccdf_profile_get_id(prof),
Packit 517ee8
		xccdf_profile_get_abstract(prof) ? " (abstract)" : "");
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _print_xccdf_profile_verbose(const struct xccdf_profile *prof, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	struct oscap_text_iterator *text_it;
Packit 517ee8
Packit 517ee8
	printf("%sProfile\n", prefix);
Packit 517ee8
Packit 517ee8
	text_it = xccdf_profile_get_title(prof);
Packit 517ee8
	char *profile_title = oscap_textlist_get_preferred_plaintext(text_it, NULL);
Packit 517ee8
	oscap_text_iterator_free(text_it);
Packit 517ee8
	_remove_occurence_of_character_from_string(profile_title, '\n');
Packit 517ee8
	printf("%s\tTitle: %s\n", prefix, profile_title);
Packit 517ee8
	free(profile_title);
Packit 517ee8
Packit 517ee8
	printf("%s\tId: %s%s\n\n", prefix,
Packit 517ee8
		xccdf_profile_get_id(prof),
Packit 517ee8
		xccdf_profile_get_abstract(prof) ? " (abstract)" : "");
Packit 517ee8
Packit 517ee8
	text_it = xccdf_profile_get_description(prof);
Packit 517ee8
	char *profile_description = oscap_textlist_get_preferred_plaintext(text_it, NULL);
Packit 517ee8
	oscap_text_iterator_free(text_it);
Packit 517ee8
	_translate_character_in_string(profile_description, '\n', ' ');
Packit 517ee8
	printf("%s\tDescription: %s\n", prefix, profile_description);
Packit 517ee8
	free(profile_description);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _print_xccdf_profile_terse(const struct xccdf_profile *prof, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	struct oscap_text_iterator *title_it = xccdf_profile_get_title(prof);
Packit 517ee8
	char *profile_title = oscap_textlist_get_preferred_plaintext(title_it, NULL);
Packit 517ee8
	_remove_occurence_of_character_from_string(profile_title, '\n');
Packit 517ee8
	oscap_text_iterator_free(title_it);
Packit 517ee8
	const char *profile_id = xccdf_profile_get_id(prof);
Packit 517ee8
	char cleaned_profile_id[1024];
Packit 517ee8
	strncpy(cleaned_profile_id, profile_id, sizeof(cleaned_profile_id) - 1);
Packit 517ee8
	_remove_occurence_of_character_from_string(cleaned_profile_id, '\n');
Packit 517ee8
	printf("%s:%s\n",
Packit 517ee8
		cleaned_profile_id,
Packit 517ee8
		profile_title);
Packit 517ee8
	free(profile_title);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _print_xccdf_profile_with_id(struct xccdf_profile *profile, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	if (profile == NULL)
Packit 517ee8
		return;
Packit 517ee8
Packit 517ee8
	_print_xccdf_profile_verbose(profile, prefix);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_profiles(struct xccdf_profile_iterator *prof_it, const char *prefix, void (*print_one_profile)(const struct xccdf_profile *, const char *))
Packit 517ee8
{
Packit 517ee8
	if (prefix)
Packit 517ee8
		printf("%sProfiles:\n", prefix);
Packit 517ee8
Packit 517ee8
	if (print_one_profile == NULL)
Packit 517ee8
		print_one_profile = &_print_xccdf_profile_default;
Packit 517ee8
Packit 517ee8
	while (xccdf_profile_iterator_has_more(prof_it)) {
Packit 517ee8
		struct xccdf_profile *prof = xccdf_profile_iterator_next(prof_it);
Packit 517ee8
		print_one_profile(prof, prefix);
Packit 517ee8
	}
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_referenced_files(struct xccdf_policy_model *policy_model, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	struct oscap_file_entry_list *referenced_files = xccdf_policy_model_get_systems_and_files(policy_model);
Packit 517ee8
	struct oscap_file_entry_iterator *files_it = oscap_file_entry_list_get_files(referenced_files);
Packit 517ee8
	printf("%sReferenced check files:\n", prefix);
Packit 517ee8
	while (oscap_file_entry_iterator_has_more(files_it)) {
Packit 517ee8
		struct oscap_file_entry *file_entry = (struct oscap_file_entry *) oscap_file_entry_iterator_next(files_it);
Packit 517ee8
		printf("%s\t%s\n", prefix, oscap_file_entry_get_file(file_entry));
Packit 517ee8
		printf("%s\t\tsystem: %s\n", prefix, oscap_file_entry_get_system(file_entry));
Packit 517ee8
	}
Packit 517ee8
	oscap_file_entry_iterator_free(files_it);
Packit 517ee8
	oscap_file_entry_list_free(referenced_files);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_result(struct xccdf_result *xccdf_result, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	const char *result_id = xccdf_result_get_id(xccdf_result);
Packit 517ee8
	const char *benchmark_uri = xccdf_result_get_benchmark_uri(xccdf_result);
Packit 517ee8
	const char *xccdf_profile = xccdf_result_get_profile(xccdf_result);
Packit 517ee8
	if (xccdf_profile == NULL) {
Packit 517ee8
		xccdf_profile = "(default)";
Packit 517ee8
	}
Packit 517ee8
	const char *start_time = xccdf_result_get_start_time(xccdf_result);
Packit 517ee8
	const char *end_time = xccdf_result_get_end_time(xccdf_result);
Packit 517ee8
	printf("%s\tResult ID: %s\n", prefix, result_id);
Packit 517ee8
	printf("%s\tSource benchmark: %s\n", prefix, benchmark_uri);
Packit 517ee8
	printf("%s\tSource profile: %s\n", prefix, xccdf_profile);
Packit 517ee8
	printf("%s\tEvaluation started: %s\n", prefix, start_time);
Packit 517ee8
	printf("%s\tEvaluation finished: %s\n", prefix, end_time);
Packit 517ee8
	printf("%s\tPlatform CPEs:\n", prefix);
Packit 517ee8
	struct oscap_string_iterator *platforms_it = xccdf_result_get_platforms(xccdf_result);
Packit 517ee8
	if (!oscap_string_iterator_has_more(platforms_it)) {
Packit 517ee8
		printf("%s\t\t(none)\n", prefix);
Packit 517ee8
	}
Packit 517ee8
	while (oscap_string_iterator_has_more(platforms_it)) {
Packit 517ee8
		const char *platform = oscap_string_iterator_next(platforms_it);
Packit 517ee8
		printf("%s\t\t%s\n", prefix, platform);
Packit 517ee8
	}
Packit 517ee8
	oscap_string_iterator_free(platforms_it);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_testresults(struct xccdf_benchmark *bench, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	struct xccdf_result_iterator *res_it = xccdf_benchmark_get_results(bench);
Packit 517ee8
	if (xccdf_result_iterator_has_more(res_it))
Packit 517ee8
		printf("%sTest Results:\n", prefix);
Packit 517ee8
	while (xccdf_result_iterator_has_more(res_it)) {
Packit 517ee8
		struct xccdf_result *test_result = xccdf_result_iterator_next(res_it);
Packit 517ee8
		_print_xccdf_result(test_result, prefix);
Packit 517ee8
	}
Packit 517ee8
	xccdf_result_iterator_free(res_it);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_benchmark(struct xccdf_benchmark *bench, const char *prefix, void (*print_one_profile)(const struct xccdf_profile *, const char *))
Packit 517ee8
{
Packit 517ee8
	_print_xccdf_status(xccdf_benchmark_get_status_current(bench), prefix);
Packit 517ee8
	printf("%sResolved: %s\n", prefix, xccdf_benchmark_get_resolved(bench) ? "true" : "false");
Packit 517ee8
Packit 517ee8
	struct xccdf_profile_iterator *prof_it = xccdf_benchmark_get_profiles(bench);
Packit 517ee8
	_print_xccdf_profiles(prof_it, prefix, print_one_profile);
Packit 517ee8
	xccdf_profile_iterator_free(prof_it);
Packit 517ee8
Packit 517ee8
	struct xccdf_policy_model *policy_model = xccdf_policy_model_new(bench);
Packit 517ee8
	_print_xccdf_referenced_files(policy_model, prefix);
Packit 517ee8
	_print_xccdf_testresults(bench, prefix);
Packit 517ee8
Packit 517ee8
	xccdf_policy_model_free(policy_model);
Packit 517ee8
	// xccdf_benchmark_free not needed, it si already freed by the policy!
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_tailoring_header(struct xccdf_tailoring *tailoring, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	if (tailoring == NULL) {
Packit 517ee8
		return;
Packit 517ee8
	}
Packit 517ee8
	printf("%sBenchmark Hint: %s\n", prefix ? prefix : "", xccdf_tailoring_get_benchmark_ref(tailoring));
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static inline void _print_xccdf_tailoring(struct oscap_source *source, const char *prefix, void (*print_one_profile)(const struct xccdf_profile *, const char *))
Packit 517ee8
{
Packit 517ee8
	struct xccdf_tailoring *tailoring = xccdf_tailoring_import_source(source, NULL);
Packit 517ee8
	_print_xccdf_tailoring_header(tailoring, prefix);
Packit 517ee8
Packit 517ee8
	struct xccdf_profile_iterator *prof_it = xccdf_tailoring_get_profiles(tailoring);
Packit 517ee8
	_print_xccdf_profiles(prof_it, prefix, print_one_profile);
Packit 517ee8
	xccdf_profile_iterator_free(prof_it);
Packit 517ee8
Packit 517ee8
	xccdf_tailoring_free(tailoring);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _print_single_benchmark_profiles_only(struct xccdf_benchmark *bench)
Packit 517ee8
{
Packit 517ee8
	struct xccdf_profile_iterator *prof_it = xccdf_benchmark_get_profiles(bench);
Packit 517ee8
	_print_xccdf_profiles(prof_it, 0, _print_xccdf_profile_terse);
Packit 517ee8
	xccdf_profile_iterator_free(prof_it);
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _print_single_benchmark_one_profile(struct xccdf_benchmark *bench, const char *profile_id)
Packit 517ee8
{
Packit 517ee8
	struct xccdf_profile *profile = xccdf_benchmark_get_profile_by_id(bench, profile_id);
Packit 517ee8
	if (profile != NULL)
Packit 517ee8
		_print_xccdf_profile_with_id(profile, "");
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void _print_single_benchmark_all(struct xccdf_benchmark *bench, const char *prefix)
Packit 517ee8
{
Packit 517ee8
	_print_xccdf_benchmark(bench, prefix, 0);
Packit 517ee8
	// bench is freed as a side-effect of the function above
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static int app_info_single_ds_profiles_only(struct ds_stream_index_iterator* sds_it, struct ds_sds_session *session, const struct oscap_action *action)
Packit 517ee8
{
Packit 517ee8
	struct ds_stream_index * stream = ds_stream_index_iterator_next(sds_it);
Packit 517ee8
	struct oscap_string_iterator* checklist_it = ds_stream_index_get_checklists(stream);
Packit 517ee8
Packit 517ee8
	while (oscap_string_iterator_has_more(checklist_it)) {
Packit 517ee8
		const char * id = oscap_string_iterator_next(checklist_it);
Packit 517ee8
		/* decompose */
Packit 517ee8
		struct oscap_source *xccdf_source = ds_sds_session_select_checklist(session, ds_stream_index_get_id(stream), id, NULL);
Packit 517ee8
		if (xccdf_source == NULL) {
Packit 517ee8
			oscap_string_iterator_free(checklist_it);
Packit 517ee8
			ds_stream_index_iterator_free(sds_it);
Packit 517ee8
			ds_sds_session_free(session);
Packit 517ee8
			return OSCAP_ERROR;
Packit 517ee8
		}
Packit 517ee8
Packit 517ee8
		if (oscap_source_get_scap_type(xccdf_source) == OSCAP_DOCUMENT_XCCDF) {
Packit 517ee8
			struct xccdf_benchmark* bench = xccdf_benchmark_import_source(xccdf_source);
Packit 517ee8
			if(!bench) {
Packit 517ee8
				oscap_string_iterator_free(checklist_it);
Packit 517ee8
				ds_stream_index_iterator_free(sds_it);
Packit 517ee8
				ds_sds_session_free(session);
Packit 517ee8
				return OSCAP_ERROR;
Packit 517ee8
			}
Packit 517ee8
			_print_single_benchmark_profiles_only(bench);
Packit 517ee8
			xccdf_benchmark_free(bench);
Packit 517ee8
Packit 517ee8
		} else if (oscap_source_get_scap_type(xccdf_source) == OSCAP_DOCUMENT_XCCDF_TAILORING) {
Packit 517ee8
			_print_xccdf_tailoring(xccdf_source, 0, _print_xccdf_profile_terse);
Packit 517ee8
		}
Packit 517ee8
		ds_sds_session_reset(session);
Packit 517ee8
	}
Packit 517ee8
	oscap_string_iterator_free(checklist_it);
Packit 517ee8
	return OSCAP_OK;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static const char *tailoring_get_profile_or_report_multiple_ids(struct xccdf_tailoring *tailoring, const char *profile_suffix, const char *source_file)
Packit 517ee8
{
Packit 517ee8
	int match_status;
Packit 517ee8
	const char *result = xccdf_tailoring_match_profile_id(tailoring, profile_suffix, &match_status);
Packit 517ee8
	evaluate_suffix_match_result_with_custom_reports(match_status, profile_suffix, source_file, NULL, &report_multiple_profile_matches);
Packit 517ee8
	return result;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static const char *benchmark_get_profile_or_report_multiple_ids(struct xccdf_benchmark *bench, const char *profile_suffix, const char *source_file)
Packit 517ee8
{
Packit 517ee8
	int match_status;
Packit 517ee8
	const char *result = xccdf_benchmark_match_profile_id(bench, profile_suffix, &match_status);
Packit 517ee8
	evaluate_suffix_match_result_with_custom_reports(match_status, profile_suffix, source_file, NULL, &report_multiple_profile_matches);
Packit 517ee8
	return result;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static const char *benchmark_get_profile_or_report_id_issues(struct xccdf_benchmark *bench, const char *profile_suffix, const char *source_file)
Packit 517ee8
{
Packit 517ee8
	int match_status;
Packit 517ee8
	const char *result = xccdf_benchmark_match_profile_id(bench, profile_suffix, &match_status);
Packit 517ee8
	evaluate_suffix_match_result(match_status, profile_suffix, source_file);
Packit 517ee8
	return result;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static int app_info_single_ds_one_profile(struct ds_stream_index_iterator* sds_it, struct ds_sds_session *session, const char *profile_suffix, const char *filename)
Packit 517ee8
{
Packit 517ee8
	const char *prefix = "";
Packit 517ee8
	struct ds_stream_index * stream = ds_stream_index_iterator_next(sds_it);
Packit 517ee8
	struct oscap_string_iterator* checklist_it = ds_stream_index_get_checklists(stream);
Packit 517ee8
Packit 517ee8
	printf("\nStream: %s\n", ds_stream_index_get_id(stream));
Packit 517ee8
	printf("Generated: %s\n", ds_stream_index_get_timestamp(stream));
Packit 517ee8
	printf("Version: %s\n", ds_stream_index_get_version(stream));
Packit 517ee8
	bool profile_not_found = true;
Packit 517ee8
Packit 517ee8
	while (oscap_string_iterator_has_more(checklist_it) && profile_not_found) {
Packit 517ee8
		const char * id = oscap_string_iterator_next(checklist_it);
Packit 517ee8
Packit 517ee8
		/* decompose */
Packit 517ee8
		struct oscap_source *xccdf_source = ds_sds_session_select_checklist(session, ds_stream_index_get_id(stream), id, NULL);
Packit 517ee8
		if (xccdf_source == NULL) {
Packit 517ee8
			oscap_string_iterator_free(checklist_it);
Packit 517ee8
			ds_stream_index_iterator_free(sds_it);
Packit 517ee8
			ds_sds_session_free(session);
Packit 517ee8
			return OSCAP_ERROR;
Packit 517ee8
		}
Packit 517ee8
Packit 517ee8
		if (oscap_source_get_scap_type(xccdf_source) == OSCAP_DOCUMENT_XCCDF) {
Packit 517ee8
			struct xccdf_benchmark *bench = xccdf_benchmark_import_source(xccdf_source);
Packit 517ee8
			if(!bench) {
Packit 517ee8
				oscap_string_iterator_free(checklist_it);
Packit 517ee8
				ds_stream_index_iterator_free(sds_it);
Packit 517ee8
				ds_sds_session_free(session);
Packit 517ee8
				return OSCAP_ERROR;
Packit 517ee8
			}
Packit 517ee8
			const char *profile_id = benchmark_get_profile_or_report_multiple_ids(bench, profile_suffix, filename);
Packit 517ee8
			if (profile_id != NULL) {
Packit 517ee8
				_print_single_benchmark_one_profile(bench, profile_id);
Packit 517ee8
				profile_not_found = false;
Packit 517ee8
			}
Packit 517ee8
			xccdf_benchmark_free(bench);
Packit 517ee8
		} else if (oscap_source_get_scap_type(xccdf_source) == OSCAP_DOCUMENT_XCCDF_TAILORING) {
Packit 517ee8
			struct xccdf_tailoring *tailoring = xccdf_tailoring_import_source(xccdf_source, NULL);
Packit 517ee8
Packit 517ee8
			const char *profile_id = tailoring_get_profile_or_report_multiple_ids(tailoring, profile_suffix, filename);
Packit 517ee8
			if (profile_id != NULL) {
Packit 517ee8
				struct xccdf_profile *profile = xccdf_tailoring_get_profile_by_id(tailoring, profile_id);
Packit 517ee8
				_print_xccdf_profile_with_id(profile, prefix);
Packit 517ee8
				profile_not_found = false;
Packit 517ee8
			}
Packit 517ee8
Packit 517ee8
			xccdf_tailoring_free(tailoring);
Packit 517ee8
		}
Packit 517ee8
		ds_sds_session_reset(session);
Packit 517ee8
	}
Packit 517ee8
	oscap_string_iterator_free(checklist_it);
Packit 517ee8
	if (profile_not_found) {
Packit 517ee8
		report_missing_profile(profile_suffix, filename);
Packit 517ee8
	}
Packit 517ee8
	return OSCAP_OK;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static int app_info_single_ds_all(struct ds_stream_index_iterator* sds_it, struct ds_sds_session *session, const struct oscap_action *action)
Packit 517ee8
{
Packit 517ee8
	const char *prefix = "\t\t";
Packit 517ee8
	struct ds_stream_index * stream = ds_stream_index_iterator_next(sds_it);
Packit 517ee8
	struct oscap_string_iterator* checklist_it = ds_stream_index_get_checklists(stream);
Packit 517ee8
Packit 517ee8
	printf("\nStream: %s\n", ds_stream_index_get_id(stream));
Packit 517ee8
	printf("Generated: %s\n", ds_stream_index_get_timestamp(stream));
Packit 517ee8
	printf("Version: %s\n", ds_stream_index_get_version(stream));
Packit 517ee8
Packit 517ee8
	printf("Checklists:\n");
Packit 517ee8
	while (oscap_string_iterator_has_more(checklist_it)) {
Packit 517ee8
		const char * id = oscap_string_iterator_next(checklist_it);
Packit 517ee8
		printf("\tRef-Id: %s\n", id);
Packit 517ee8
Packit 517ee8
		/* decompose */
Packit 517ee8
		struct oscap_source *xccdf_source = ds_sds_session_select_checklist(session, ds_stream_index_get_id(stream), id, NULL);
Packit 517ee8
		if (xccdf_source == NULL) {
Packit 517ee8
			oscap_string_iterator_free(checklist_it);
Packit 517ee8
			ds_stream_index_iterator_free(sds_it);
Packit 517ee8
			ds_sds_session_free(session);
Packit 517ee8
			return OSCAP_ERROR;
Packit 517ee8
		}
Packit 517ee8
Packit 517ee8
		if (oscap_source_get_scap_type(xccdf_source) == OSCAP_DOCUMENT_XCCDF) {
Packit 517ee8
			struct xccdf_benchmark* bench = xccdf_benchmark_import_source(xccdf_source);
Packit 517ee8
			if(!bench) {
Packit 517ee8
				oscap_string_iterator_free(checklist_it);
Packit 517ee8
				ds_stream_index_iterator_free(sds_it);
Packit 517ee8
				ds_sds_session_free(session);
Packit 517ee8
				return OSCAP_ERROR;
Packit 517ee8
			}
Packit 517ee8
			_print_xccdf_benchmark(bench, prefix, 0);
Packit 517ee8
			// bench is freed as a side-effect of the function above
Packit 517ee8
		} else if (oscap_source_get_scap_type(xccdf_source) == OSCAP_DOCUMENT_XCCDF_TAILORING) {
Packit 517ee8
			_print_xccdf_tailoring(xccdf_source, prefix, 0);
Packit 517ee8
		}
Packit 517ee8
		ds_sds_session_reset(session);
Packit 517ee8
	}
Packit 517ee8
	oscap_string_iterator_free(checklist_it);
Packit 517ee8
Packit 517ee8
	printf("Checks:\n");
Packit 517ee8
	struct oscap_string_iterator* checks_it = ds_stream_index_get_checks(stream);
Packit 517ee8
	while (oscap_string_iterator_has_more(checks_it)) {
Packit 517ee8
		const char * id = oscap_string_iterator_next(checks_it);
Packit 517ee8
		printf("\tRef-Id: %s\n", id);
Packit 517ee8
	}
Packit 517ee8
	oscap_string_iterator_free(checks_it);
Packit 517ee8
Packit 517ee8
	struct oscap_string_iterator* dict_it = ds_stream_index_get_dictionaries(stream);
Packit 517ee8
	if (oscap_string_iterator_has_more(dict_it)) {
Packit 517ee8
		printf("Dictionaries:\n");
Packit 517ee8
	} else {
Packit 517ee8
		printf("No dictionaries.\n");
Packit 517ee8
	}
Packit 517ee8
	while (oscap_string_iterator_has_more(dict_it)) {
Packit 517ee8
		const char * id = oscap_string_iterator_next(dict_it);
Packit 517ee8
		printf("\tRef-Id: %s\n", id);
Packit 517ee8
	}
Packit 517ee8
	oscap_string_iterator_free(dict_it);
Packit 517ee8
	return OSCAP_OK;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static void app_info_single_benchmark(struct xccdf_benchmark *bench, const struct oscap_action *action, struct oscap_source *source)
Packit 517ee8
{
Packit 517ee8
	if (action->show_profiles_only) {
Packit 517ee8
		_print_single_benchmark_profiles_only(bench);
Packit 517ee8
		xccdf_benchmark_free(bench);
Packit 517ee8
	} else if (action->profile) {
Packit 517ee8
		const char *profile_id = benchmark_get_profile_or_report_id_issues(bench, action->profile, action->file);
Packit 517ee8
		if (profile_id != NULL) {
Packit 517ee8
			_print_single_benchmark_one_profile(bench, profile_id);
Packit 517ee8
		}
Packit 517ee8
		xccdf_benchmark_free(bench);
Packit 517ee8
	} else {
Packit 517ee8
		printf("Checklist version: %s\n", oscap_source_get_schema_version(source));
Packit 517ee8
		print_time(action->file);
Packit 517ee8
Packit 517ee8
		_print_single_benchmark_all(bench, "");
Packit 517ee8
		// bench is freed as a side-effect of the function above
Packit 517ee8
	}
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static int app_info_single_ds(struct ds_stream_index_iterator* sds_it, struct ds_sds_session *session, const struct oscap_action *action)
Packit 517ee8
{
Packit 517ee8
	int return_value;
Packit 517ee8
	if (action->show_profiles_only) {
Packit 517ee8
		return_value = app_info_single_ds_profiles_only(sds_it, session, action);
Packit 517ee8
	} else if (action->profile) {
Packit 517ee8
		return_value = app_info_single_ds_one_profile(sds_it, session, action->profile, action->file);
Packit 517ee8
	} else {
Packit 517ee8
		return_value = app_info_single_ds_all(sds_it, session, action);
Packit 517ee8
	}
Packit 517ee8
	return return_value;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static int app_info_sds(struct oscap_source *source, const struct oscap_action *action)
Packit 517ee8
{
Packit 517ee8
	if (! action->provide_machine_readable_output) {
Packit 517ee8
		printf("Document type: Source Data Stream\n");
Packit 517ee8
		print_time(action->file);
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	struct ds_sds_session *session = ds_sds_session_new_from_source(source);
Packit 517ee8
	if (session == NULL) {
Packit 517ee8
		return OSCAP_ERROR;
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	ds_sds_session_set_remote_resources(session, action->remote_resources, download_reporting_callback);
Packit 517ee8
Packit 517ee8
	/* get collection */
Packit 517ee8
	struct ds_sds_index *sds = ds_sds_session_get_sds_idx(session);
Packit 517ee8
	if (!sds) {
Packit 517ee8
		ds_sds_session_free(session);
Packit 517ee8
		return OSCAP_ERROR;
Packit 517ee8
	}
Packit 517ee8
	/* iterate over streams */
Packit 517ee8
	struct ds_stream_index_iterator* sds_it = ds_sds_index_get_streams(sds);
Packit 517ee8
	while (ds_stream_index_iterator_has_more(sds_it)) {
Packit 517ee8
		if (app_info_single_ds(sds_it, session, action) == OSCAP_ERROR)
Packit 517ee8
			return OSCAP_ERROR;
Packit 517ee8
	}
Packit 517ee8
	ds_stream_index_iterator_free(sds_it);
Packit 517ee8
	ds_sds_session_free(session);
Packit 517ee8
	return OSCAP_OK;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
static int app_info(const struct oscap_action *action)
Packit 517ee8
{
Packit 517ee8
        int result = OSCAP_ERROR;
Packit 517ee8
Packit 517ee8
	struct oscap_source *source = oscap_source_new_from_file(action->file);
Packit 517ee8
Packit 517ee8
	switch (oscap_source_get_scap_type(source)) {
Packit 517ee8
	case OSCAP_DOCUMENT_OVAL_DEFINITIONS: {
Packit 517ee8
		printf("Document type: OVAL Definitions\n");
Packit 517ee8
		struct oval_definition_model *def_model = oval_definition_model_import_source(source);
Packit 517ee8
		if(!def_model)
Packit 517ee8
			goto cleanup;
Packit 517ee8
		struct oval_generator *gen = oval_definition_model_get_generator(def_model);
Packit 517ee8
		printf("OVAL version: %s\n", oval_generator_get_core_schema_version(gen));
Packit 517ee8
		printf("Generated: %s\n", oval_generator_get_timestamp(gen));
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		oval_definition_model_free(def_model);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_OVAL_VARIABLES: {
Packit 517ee8
		printf("Document type: OVAL Variables\n");
Packit 517ee8
		struct oval_variable_model *var_model = oval_variable_model_import_source(source);
Packit 517ee8
		if(!var_model)
Packit 517ee8
			goto cleanup;
Packit 517ee8
		struct oval_generator *gen = oval_variable_model_get_generator(var_model);
Packit 517ee8
		printf("OVAL version: %s\n", oval_generator_get_core_schema_version(gen));
Packit 517ee8
		printf("Generated: %s\n", oval_generator_get_timestamp(gen));
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		oval_variable_model_free(var_model);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_OVAL_DIRECTIVES: {
Packit 517ee8
		printf("Document type: OVAL Directives\n");
Packit 517ee8
		struct oval_directives_model *dir_model = oval_directives_model_new();
Packit 517ee8
		int ret = oval_directives_model_import_source(dir_model, source);
Packit 517ee8
		if(ret)
Packit 517ee8
			goto cleanup;
Packit 517ee8
		struct oval_generator *gen = oval_directives_model_get_generator(dir_model);
Packit 517ee8
		printf("OVAL version: %s\n", oval_generator_get_core_schema_version(gen));
Packit 517ee8
		printf("Generated: %s\n", oval_generator_get_timestamp(gen));
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		oval_directives_model_free(dir_model);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_OVAL_SYSCHAR: {
Packit 517ee8
		printf("Document type: OVAL System Characteristics\n");
Packit 517ee8
		struct oval_definition_model * def_model = oval_definition_model_new();
Packit 517ee8
		struct oval_syschar_model * sys_model = oval_syschar_model_new(def_model);
Packit 517ee8
		int ret = oval_syschar_model_import_source(sys_model, source);
Packit 517ee8
		if(ret)
Packit 517ee8
			goto cleanup;
Packit 517ee8
		struct oval_generator *gen = oval_syschar_model_get_generator(sys_model);
Packit 517ee8
		printf("OVAL version: %s\n", oval_generator_get_core_schema_version(gen));
Packit 517ee8
		printf("Generated: %s\n", oval_generator_get_timestamp(gen));
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		oval_syschar_model_free(sys_model);
Packit 517ee8
		oval_definition_model_free(def_model);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_OVAL_RESULTS: {
Packit 517ee8
		printf("Document type: OVAL Results\n");
Packit 517ee8
		struct oval_definition_model * def_model=oval_definition_model_new();
Packit 517ee8
		struct oval_results_model * res_model = oval_results_model_new(def_model,NULL);
Packit 517ee8
		int ret = oval_results_model_import_source(res_model, source);
Packit 517ee8
		if(ret)
Packit 517ee8
			goto cleanup;
Packit 517ee8
		struct oval_generator *gen = oval_results_model_get_generator(res_model);
Packit 517ee8
		printf("OVAL version: %s\n", oval_generator_get_core_schema_version(gen));
Packit 517ee8
		printf("Generated: %s\n", oval_generator_get_timestamp(gen));
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		oval_results_model_free(res_model);
Packit 517ee8
		oval_definition_model_free(def_model);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_XCCDF: {
Packit 517ee8
                if (!action->provide_machine_readable_output)
Packit 517ee8
			printf("Document type: XCCDF Checklist\n");
Packit 517ee8
		struct xccdf_benchmark* bench = xccdf_benchmark_import_source(source);
Packit 517ee8
		if(!bench)
Packit 517ee8
			goto cleanup;
Packit 517ee8
		app_info_single_benchmark(bench, action, source);
Packit 517ee8
		// bench is freed as a side-effect of the function above
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_CPE_LANGUAGE: {
Packit 517ee8
		printf("Document type: CPE Language\n");
Packit 517ee8
		print_time(action->file);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_CPE_DICTIONARY: {
Packit 517ee8
		printf("Document type: CPE Dictionary\n");
Packit 517ee8
		struct cpe_dict_model *dict_model = cpe_dict_model_import_source(source);
Packit 517ee8
		if (!dict_model)
Packit 517ee8
			goto cleanup;
Packit 517ee8
		struct cpe_generator *gen = cpe_dict_model_get_generator(dict_model);
Packit 517ee8
		if (gen != NULL) {
Packit 517ee8
			printf("CPE version: %s\n", cpe_generator_get_schema_version(gen));
Packit 517ee8
			printf("Generated: %s\n", cpe_generator_get_timestamp(gen));
Packit 517ee8
		}
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		cpe_dict_model_free(dict_model);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_SDS: {
Packit 517ee8
		if (app_info_sds(source, action) == OSCAP_ERROR)
Packit 517ee8
			goto cleanup;
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_ARF: {
Packit 517ee8
		printf("Document type: Result Data Stream\n");
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		struct ds_rds_session *session = ds_rds_session_new_from_source(source);
Packit 517ee8
		if (session == NULL) {
Packit 517ee8
			goto cleanup;
Packit 517ee8
		}
Packit 517ee8
		struct rds_index *rds = ds_rds_session_get_rds_idx(session);
Packit 517ee8
		if (!rds) {
Packit 517ee8
			ds_rds_session_free(session);
Packit 517ee8
			goto cleanup;
Packit 517ee8
		}
Packit 517ee8
Packit 517ee8
		struct rds_asset_index_iterator* asset_it = rds_index_get_assets(rds);
Packit 517ee8
		while (rds_asset_index_iterator_has_more(asset_it)) {
Packit 517ee8
			struct rds_asset_index* asset = rds_asset_index_iterator_next(asset_it);
Packit 517ee8
			printf("\nAsset: %s\n", rds_asset_index_get_id(asset));
Packit 517ee8
Packit 517ee8
			struct rds_report_index_iterator* report_it = rds_asset_index_get_reports(asset);
Packit 517ee8
			while (rds_report_index_iterator_has_more(report_it)) {
Packit 517ee8
				struct rds_report_index* report = rds_report_index_iterator_next(report_it);
Packit 517ee8
				struct rds_report_request_index* request = rds_report_index_get_request(report);
Packit 517ee8
				const char *report_request_id = rds_report_request_index_get_id(request);
Packit 517ee8
				const char *report_id = rds_report_index_get_id(report);
Packit 517ee8
Packit 517ee8
				struct oscap_source *report_source = ds_rds_session_select_report(session, report_id);
Packit 517ee8
				if (report_source == NULL) {
Packit 517ee8
					rds_report_index_iterator_free(report_it);
Packit 517ee8
					rds_asset_index_iterator_free(asset_it);
Packit 517ee8
					ds_rds_session_free(session);
Packit 517ee8
					goto cleanup;
Packit 517ee8
				}
Packit 517ee8
				oscap_document_type_t report_source_type = oscap_source_get_scap_type(report_source);
Packit 517ee8
				if (report_source_type != OSCAP_DOCUMENT_XCCDF) {
Packit 517ee8
					rds_report_index_iterator_free(report_it);
Packit 517ee8
					rds_asset_index_iterator_free(asset_it);
Packit 517ee8
					ds_rds_session_free(session);
Packit 517ee8
					oscap_source_free(report_source);
Packit 517ee8
					goto cleanup;
Packit 517ee8
				}
Packit 517ee8
				struct xccdf_result *xccdf_result = xccdf_result_import_source(report_source);
Packit 517ee8
				if (xccdf_result == NULL) {
Packit 517ee8
					rds_report_index_iterator_free(report_it);
Packit 517ee8
					rds_asset_index_iterator_free(asset_it);
Packit 517ee8
					ds_rds_session_free(session);
Packit 517ee8
					oscap_source_free(report_source);
Packit 517ee8
					goto cleanup;
Packit 517ee8
				}
Packit 517ee8
				printf("\tARF report: %s\n", report_id);
Packit 517ee8
				printf("\t\tReport request: %s\n", report_request_id);
Packit 517ee8
				_print_xccdf_result(xccdf_result, "\t");
Packit 517ee8
				xccdf_result_free(xccdf_result);
Packit 517ee8
				// oscap_source_free is not needed, it is already freed by xccdf_result_free
Packit 517ee8
Packit 517ee8
			}
Packit 517ee8
			rds_report_index_iterator_free(report_it);
Packit 517ee8
		}
Packit 517ee8
		rds_asset_index_iterator_free(asset_it);
Packit 517ee8
		ds_rds_session_free(session);
Packit 517ee8
	}
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_XCCDF_TAILORING:
Packit 517ee8
		printf("Document type: XCCDF Tailoring\n");
Packit 517ee8
		print_time(action->file);
Packit 517ee8
		_print_xccdf_tailoring(source, "", 0);
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_CVE_FEED:
Packit 517ee8
		printf("Document type: CVE Feed\n");
Packit 517ee8
		// TODO: Provide more info about CVE feeds
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_CVRF_FEED:
Packit 517ee8
		printf("Document type: CVRF Feed\n");
Packit 517ee8
		// TODO: Provide more info about CVRF feeds
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_SCE_RESULT:
Packit 517ee8
		printf("Document type: SCE Result File\n");
Packit 517ee8
		// Currently, we do not have any SCE result file parsing capabilities.
Packit 517ee8
	break;
Packit 517ee8
	case OSCAP_DOCUMENT_OCIL:
Packit 517ee8
		printf("Document type: OCIL Definitions file\n");
Packit 517ee8
		// we don't support OCIL yet
Packit 517ee8
	break;
Packit 517ee8
	default:
Packit 517ee8
		printf("Could not determine document type\n");
Packit 517ee8
		goto cleanup;
Packit 517ee8
		break;
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	result = OSCAP_OK;
Packit 517ee8
Packit 517ee8
cleanup:
Packit 517ee8
	oscap_source_free(source);
Packit 517ee8
	oscap_print_error();
Packit 517ee8
Packit 517ee8
	return result;
Packit 517ee8
}
Packit 517ee8
Packit 517ee8
bool getopt_info(int argc, char **argv, struct oscap_action *action)
Packit 517ee8
{
Packit 517ee8
	assert(action != NULL);
Packit 517ee8
Packit 517ee8
	/* Command-options */
Packit 517ee8
	const struct option long_options[] = {
Packit 517ee8
		{"fetch-remote-resources", no_argument, &action->remote_resources, 1},
Packit 517ee8
		{"profile", required_argument, 0, 'p'},
Packit 517ee8
		{"profiles", no_argument, 0, 'n'},
Packit 517ee8
		// end
Packit 517ee8
		{0, 0, 0, 0}
Packit 517ee8
	};
Packit 517ee8
Packit 517ee8
	int c;
Packit 517ee8
	while ((c = getopt_long(argc, argv, "o:i:p:", long_options, NULL)) != -1) {
Packit 517ee8
		switch(c) {
Packit 517ee8
			case 0: break;
Packit 517ee8
			case 'p':
Packit 517ee8
				action->profile = optarg;
Packit 517ee8
				break;
Packit 517ee8
			case 'n':
Packit 517ee8
				action->show_profiles_only = 1;
Packit 517ee8
				action->provide_machine_readable_output = 1;
Packit 517ee8
				break;
Packit 517ee8
			default: return oscap_module_usage(action->module, stderr, NULL);
Packit 517ee8
		}
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	if (optind >= argc) {
Packit 517ee8
		oscap_module_usage(action->module, stderr, "SCAP file needs to be specified!\n");
Packit 517ee8
		return false;
Packit 517ee8
	}
Packit 517ee8
Packit 517ee8
	action->file = argv[optind];
Packit 517ee8
Packit 517ee8
	return true;
Packit 517ee8
}