swtpm_setup: Implement option --create-config-files to create config files

Implement the option --create-config-files to create config files
for swtpm_setup and swtpm-localca for a user account. The files will
be created under the $XDG_CONFIG_HOME or $HOME/.config directories.

This option supports optional arguments 'overwrite' to allow overwriting
existing config files as well as the optional argument 'root' to create
config files under root's home directory. Both options can be passed
by separating them with a ','.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2021-10-06 16:58:04 -04:00 committed by Stefan Berger
parent 50670dca12
commit 2b60723766
7 changed files with 208 additions and 4 deletions

View File

@ -195,6 +195,7 @@ The output may contain the following:
"cmdarg-keyfile-fd",
"cmdarg-pwdfile-fd",
"cmdarg-write-ek-cert-files",
"cmdarg-create-config-files",
"tpm2-rsa-keysize-2048",
"tpm2-rsa-keysize-3072",
"tpm12-not-need-root",
@ -220,7 +221,11 @@ The I<--pwdfile-fd> option is supported.
=item B<cmdarg-write-ek-cert-files>
The I<--write-ek-cert-files> option is supported
The I<--write-ek-cert-files> option is supported.
=item B<cmdarg-create-config-files>
The I<--create-config-files> option is supported.
=item B<tpm2-rsa-keysize-2048, ...>
@ -255,6 +260,27 @@ The keys that are written for a TPM 2 may change over time as the default
strength of the EK keys changes. This means that one should look for all
files with the above filename pattern when looking for the EKs.
=item B<--create-config-files [[overwrite][,root]]>
This option allows a user to create config files for swtpm_setup and
swtpm-localca under the $XDG_CONFIG_HOME or $HOME/.config directories.
The meaning of the options is as follows:
=over 4
==item B<overwrite>
Overwrite any existing config files.
==item B<root>
Create the config files even under the root account. These config files
may then shadow any other existing config files, such as
/etc/swtpm-localca.conf for example.
=back
=item B<--help, -h>
Display the help screen

View File

@ -874,6 +874,12 @@ static void usage(const char *prgname, const char *default_config_file)
"--print-capabilities\n"
" : Print JSON formatted capabilites added after v0.1 and exit.\n"
"\n"
"--create-config-files [[overwrite][,root]]\n"
" : Create swtpm_setup and swtpm-localca config files for a\n"
" user account.\n"
" overwrite: overwrite any existing files\n"
" root: allow to create files under root's home directory\n"
"\n"
"--version : Display version and exit\n"
"\n"
"--help,-h,-? : Display this help screen\n\n",
@ -1022,7 +1028,7 @@ static int print_capabilities(char **swtpm_prg_l, gboolean swtpm_has_tpm12,
printf("{ \"type\": \"swtpm_setup\", "
"\"features\": [ %s%s\"cmdarg-keyfile-fd\", \"cmdarg-pwdfile-fd\", \"tpm12-not-need-root\""
", \"cmdarg-write-ek-cert-files\""
", \"cmdarg-write-ek-cert-files\", \"cmdarg-create-config-files\""
"%s ], "
"\"version\": \"" VERSION "\" "
"}\n",
@ -1082,6 +1088,21 @@ error:
return ret;
}
static int handle_create_config_files(const char *optarg)
{
g_auto(GStrv) tokens = NULL;
gboolean overwrite = FALSE;
gboolean root_flag = FALSE;
if (optarg) {
tokens = g_strsplit_set(optarg, ", ", -1);
overwrite = g_strv_contains((const gchar **)tokens, "overwrite");
root_flag = g_strv_contains((const gchar **)tokens, "root");
}
return create_config_files(overwrite, root_flag);
}
int main(int argc, char *argv[])
{
int opt, option_index = 0;
@ -1119,6 +1140,7 @@ int main(int argc, char *argv[])
{"pcr-banks", required_argument, NULL, 'b'},
{"rsa-keysize", required_argument, NULL, 'A'},
{"write-ek-cert-files", required_argument, NULL, '3'},
{"create-config-files", optional_argument, NULL, 'u'},
{"tcsd-system-ps-file", required_argument, NULL, 'F'},
{"version", no_argument, NULL, '1'},
{"print-capabilities", no_argument, NULL, 'y'},
@ -1312,6 +1334,11 @@ int main(int argc, char *argv[])
user_certsdir = g_strdup(optarg);
flags |= SETUP_WRITE_EK_CERT_FILES_F;
break;
case 'u':
if (optarg == NULL && optind < argc && argv[optind][0] != '0')
optarg = argv[optind++];
ret = handle_create_config_files(optarg);
goto out;
case 'F': /* --tcsd-system-ps-file */
printf("Warning: --tcsd-system-ps-file is deprecated and has no effect.");
break;

View File

@ -15,5 +15,6 @@
#define SWTPM_VER_MICRO @SWTPM_VER_MICRO@
#define SYSCONFDIR "@SYSCONFDIR@"
#define DATAROOTDIR "@DATAROOTDIR@"
#endif /* SWTPM_SETUP_CONF_H */

View File

@ -9,10 +9,17 @@
#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_setup_conf.h"
#include "swtpm_setup_utils.h"
#include "swtpm_utils.h"
@ -49,3 +56,145 @@ gchar *get_config_value(gchar **config_file_lines, const gchar *configname)
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
*/
int create_config_files(gboolean overwrite, gboolean root_flag)
{
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 char *xch = getenv("XDG_CONFIG_HOME");
const char *home = getenv("HOME");
g_autofree gchar *create_certs_tool = NULL;
g_autofree gchar *directory = 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;
}
if (xch == NULL) {
fprintf(stdout, "Environment variable XDG_CONFIG_HOME is not set. Using ${HOME}/.config.\n");
directory = g_build_filename(home, ".config", NULL);
} else {
directory = g_strdup(xch);
}
configfiles = g_new0(gchar *, NUM_FILES + 1);
for (i = 0; i < NUM_FILES; i++) {
configfiles[i] = g_build_filename(directory, filenames[i], NULL);
if (!overwrite && g_file_test(configfiles[i], G_FILE_TEST_EXISTS)) {
fprintf(stderr, "File %s already exists. Refusing to overwrite.\n",
configfiles[i]);
goto out;
}
}
swtpm_localca_dir = g_build_filename(directory,
"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(DATAROOTDIR,
"swtpm", "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",
create_certs_tool,
configfiles[SWTPM_LOCALCA_CONF],
configfiles[SWTPM_LOCALCA_OPTIONS]
);
/* 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;
}

View File

@ -13,5 +13,6 @@
#include <glib.h>
gchar *get_config_value(gchar **config_file_lines, const gchar *configname);
int create_config_files(gboolean overwrite, gboolean root_flag);
#endif /* SWPTM_SETUP_UTILS_H */

View File

@ -43,7 +43,7 @@ if [ $? -ne 0 ]; then
fi
# The are some variable parameters at the end, use regex
exp='\{ "type": "swtpm_setup", "features": \[ "tpm-1.2",( "tpm-2.0",)? "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}'
exp='\{ "type": "swtpm_setup", "features": \[ "tpm-1.2",( "tpm-2.0",)? "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files", "cmdarg-create-config-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}'
if ! [[ ${msg} =~ ${exp} ]]; then
echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:"
echo "Actual : ${msg}"

View File

@ -44,7 +44,7 @@ if [ $? -ne 0 ]; then
fi
# The are some variable parameters at the end, use regex
exp='\{ "type": "swtpm_setup", "features": \[( "tpm-1.2",)? "tpm-2.0", "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}'
exp='\{ "type": "swtpm_setup", "features": \[( "tpm-1.2",)? "tpm-2.0", "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root", "cmdarg-write-ek-cert-files", "cmdarg-create-config-files"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \], "version": "[^"]*" \}'
if ! [[ ${msg} =~ ${exp} ]]; then
echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:"
echo "Actual : ${msg}"