mirror of
https://github.com/stefanberger/swtpm.git
synced 2026-01-12 09:44:46 +00:00
Have swtpm_setup --create-config-files write profile entries into swtpm_setup.conf. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
205 lines
6.2 KiB
C
205 lines
6.2 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause */
|
|
/*
|
|
* swtpm_setup_utils.c: Utility functions for swtpm_setup
|
|
*
|
|
* Author: Stefan Berger, stefanb@linux.ibm.com
|
|
*
|
|
* Copyright (c) IBM Corporation, 2021
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
#include <regex.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/utsname.h>
|
|
#include <unistd.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include "swtpm_conf.h"
|
|
#include "swtpm_utils.h"
|
|
#include "swtpm_setup_utils.h"
|
|
|
|
/* Get a configuration value given its name */
|
|
gchar *get_config_value(gchar *const *config_file_lines, const gchar *configname)
|
|
{
|
|
g_autofree gchar *regex = g_strdup_printf("^%s[[:space:]]*=[[:space:]]*([^#\n]*).*",
|
|
configname);
|
|
gchar *result = NULL;
|
|
regmatch_t pmatch[2];
|
|
regex_t preg;
|
|
size_t idx;
|
|
|
|
if (regcomp(&preg, regex, REG_EXTENDED) != 0) {
|
|
logerr(gl_LOGFILE, "Internal error: Could not compile regex\n");
|
|
return NULL;
|
|
}
|
|
|
|
for (idx = 0; config_file_lines[idx] != NULL; idx++) {
|
|
const gchar *line = config_file_lines[idx];
|
|
if (regexec(&preg, line, 2, pmatch, 0) == 0) {
|
|
g_autofree gchar *tmp = NULL;
|
|
|
|
tmp = g_strndup(&line[pmatch[1].rm_so],
|
|
pmatch[1].rm_eo - pmatch[1].rm_so);
|
|
g_strchomp(tmp);
|
|
result = resolve_string(tmp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
regfree(&preg);
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Create swtpm_setup and swtpm-localca config files for a user
|
|
*
|
|
* @overwrite: TRUE: overwrite any existing config files
|
|
* FALSE: return error if any file exists
|
|
* @root_flag: TRUE: create the config files under root's home
|
|
* directory shadowing any existing config files in /etc/
|
|
* FALSE: refuse to create config files as root
|
|
* @skip_if_exist: TRUE if any one config files exists return with no error
|
|
*
|
|
*/
|
|
int create_config_files(gboolean overwrite, gboolean root_flag,
|
|
gboolean skip_if_exist)
|
|
{
|
|
enum {
|
|
SWTPM_SETUP_CONF = 0,
|
|
SWTPM_LOCALCA_CONF = 1,
|
|
SWTPM_LOCALCA_OPTIONS = 2,
|
|
NUM_FILES = 3,
|
|
};
|
|
const gchar *filenames[NUM_FILES] = {
|
|
"swtpm_setup.conf",
|
|
"swtpm-localca.conf",
|
|
"swtpm-localca.options"
|
|
};
|
|
const gchar *configdir = g_get_user_config_dir();
|
|
g_autofree gchar *create_certs_tool = NULL;
|
|
g_autofree gchar *swtpm_localca_dir = NULL;
|
|
g_autofree gchar *signkey = NULL;
|
|
g_autofree gchar *issuercert = NULL;
|
|
g_autofree gchar *certserial = NULL;
|
|
g_autofree gchar *platform_manufacturer = NULL;
|
|
g_autofree gchar *platform_version = NULL;
|
|
g_autofree gchar *platform_model = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
gboolean delete_files = FALSE;
|
|
g_auto(GStrv) configfiles = NULL;
|
|
g_auto(GStrv) filedata = NULL;
|
|
struct utsname utsname;
|
|
int ret = 1;
|
|
size_t i;
|
|
|
|
if (getuid() == 0 && !root_flag) {
|
|
fprintf(stderr, "Requiring the 'root' flag since the configuration "
|
|
"files will shadow those in %s.\n", SYSCONFDIR);
|
|
goto error;
|
|
}
|
|
|
|
configfiles = g_new0(gchar *, NUM_FILES + 1);
|
|
for (i = 0; i < NUM_FILES; i++) {
|
|
configfiles[i] = g_build_filename(configdir, filenames[i], NULL);
|
|
if (!overwrite && g_file_test(configfiles[i], G_FILE_TEST_EXISTS)) {
|
|
if (skip_if_exist) {
|
|
ret = 0;
|
|
} else {
|
|
fprintf(stderr, "File %s already exists. Refusing to overwrite.\n",
|
|
configfiles[i]);
|
|
}
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
swtpm_localca_dir = g_build_filename(configdir,
|
|
"var", "lib", "swtpm-localca", NULL);
|
|
if (g_mkdir_with_parents(swtpm_localca_dir, 0775) < 0) {
|
|
fprintf(stderr, "Could not create %s: %s\n",
|
|
swtpm_localca_dir, strerror(errno));
|
|
goto error;
|
|
}
|
|
|
|
filedata = g_new0(gchar *, NUM_FILES + 1);
|
|
|
|
/* setpm_setup.conf */
|
|
create_certs_tool = g_build_filename(BINDIR,
|
|
"swtpm_localca", NULL);
|
|
filedata[SWTPM_SETUP_CONF] = g_strdup_printf(
|
|
"create_certs_tool = %s\n"
|
|
"create_certs_tool_config = %s\n"
|
|
"create_certs_tool_options = %s\n"
|
|
"# Comma-separated list (no spaces) of PCR banks to activate by default\n"
|
|
"active_pcr_banks = %s\n"
|
|
"profile = {\"Name\":\"default-v1\"}\n"
|
|
"# profile_file =\n"
|
|
"local_profiles_dir = %s/etc/swtpm/profiles/\n",
|
|
create_certs_tool,
|
|
configfiles[SWTPM_LOCALCA_CONF],
|
|
configfiles[SWTPM_LOCALCA_OPTIONS],
|
|
DEFAULT_PCR_BANKS,
|
|
configdir
|
|
);
|
|
|
|
/* swtpm-localca.conf */
|
|
signkey = g_build_filename(swtpm_localca_dir, "signkey.pem", NULL);
|
|
issuercert = g_build_filename(swtpm_localca_dir, "issuercert.pem", NULL);
|
|
certserial = g_build_filename(swtpm_localca_dir, "certserial", NULL);
|
|
filedata[SWTPM_LOCALCA_CONF] = g_strdup_printf(
|
|
"statedir = %s\n"
|
|
"signingkey = %s\n"
|
|
"issuercert = %s\n"
|
|
"certserial = %s\n",
|
|
swtpm_localca_dir,
|
|
signkey,
|
|
issuercert,
|
|
certserial
|
|
);
|
|
|
|
/* swtpm-localca.options */
|
|
if (uname(&utsname) < 0) {
|
|
fprintf(stderr, "uname failed: %s\n", strerror(errno));
|
|
goto error;
|
|
}
|
|
|
|
platform_manufacturer = str_replace(utsname.sysname, " ", "_");
|
|
platform_version = str_replace(utsname.version, " ", "_");
|
|
platform_model = str_replace(utsname.sysname, " ", "_");
|
|
|
|
filedata[SWTPM_LOCALCA_OPTIONS] = g_strdup_printf(
|
|
"--platform-manufacturer %s\n"
|
|
"--platform-version %s\n"
|
|
"--platform-model %s\n",
|
|
platform_manufacturer,
|
|
platform_version,
|
|
platform_model
|
|
);
|
|
|
|
for (i = 0; i < NUM_FILES; i++) {
|
|
fprintf(stdout, "Writing %s.\n", configfiles[i]);
|
|
if (!g_file_set_contents(configfiles[i], filedata[i], -1, &error)) {
|
|
fprintf(stderr,
|
|
"Could not write to %s: %s\n",
|
|
configfiles[i], strerror(errno));
|
|
delete_files = TRUE;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
error:
|
|
if (delete_files) {
|
|
for (i = 0; i < NUM_FILES; i++)
|
|
unlink(configfiles[i]);
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|