mirror of
https://github.com/stefanberger/swtpm.git
synced 2026-01-07 19:21:09 +00:00
swtpm_setup: add abstract swtpm_backend_ops with dir:// implementation
Abstract away implementation specific code for handling TPM state in swtpm_setup. The current code for handling directories is moved to 'swtpm_backend_dir.c'. Where possible, the input argument is simply passed verbatim as 'backend-uri' to swtpm. No functional change intended, aside from supporting 'dir://' as optional prefix. The checks for lock-file accessibility are moved to check_access(), but that shouldn't affect anything AFAICT. Signed-off-by: Stefan Reiter <stefan@pimaker.at>
This commit is contained in:
parent
5d9edaf401
commit
81371f665f
@ -18,7 +18,8 @@ bin_PROGRAMS = \
|
||||
swtpm_setup_SOURCES = \
|
||||
swtpm.c \
|
||||
swtpm_setup.c \
|
||||
swtpm_setup_utils.c
|
||||
swtpm_setup_utils.c \
|
||||
swtpm_backend_dir.c
|
||||
|
||||
$(top_builddir)/src/utils/libswtpm_utils.la:
|
||||
$(MAKE) -C$(dir $@)
|
||||
|
||||
@ -56,7 +56,7 @@ struct tpm_resp_header {
|
||||
|
||||
static int swtpm_start(struct swtpm *self)
|
||||
{
|
||||
g_autofree gchar *tpmstate_dir = g_strdup_printf("dir=%s", self->state_path);
|
||||
g_autofree gchar *tpmstate = g_strdup_printf("backend-uri=%s", self->state_path);
|
||||
g_autofree gchar *pidfile_arg = NULL;
|
||||
g_autofree gchar *server_fd = NULL;
|
||||
g_autofree gchar *ctrl_fd = NULL;
|
||||
@ -81,7 +81,7 @@ static int swtpm_start(struct swtpm *self)
|
||||
argv = concat_arrays(self->swtpm_exec_l,
|
||||
(gchar*[]){
|
||||
"--flags", "not-need-init,startup-clear",
|
||||
"--tpmstate", tpmstate_dir,
|
||||
"--tpmstate", tpmstate,
|
||||
"--pid", pidfile_arg,
|
||||
#if 0
|
||||
"--log", "file=/tmp/log,level=20",
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#define SWTPM_SETUP_SWTPM_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
@ -93,4 +94,14 @@ struct swtpm2 *swtpm2_new(gchar **swtpm_prg_l, const gchar *tpm_state_path,
|
||||
|
||||
void swtpm_free(struct swtpm *);
|
||||
|
||||
/* backend-specific implementations */
|
||||
struct swtpm_backend_ops {
|
||||
void* (*parse_backend)(const gchar* uri);
|
||||
int (*check_access)(void *backend, int mode, const struct passwd *curr_user);
|
||||
int (*delete_state)(void *backend);
|
||||
void (*free_backend)(void *backend);
|
||||
};
|
||||
|
||||
extern struct swtpm_backend_ops swtpm_backend_dir;
|
||||
|
||||
#endif /* SWTPM_SETUP_SWTPM_H */
|
||||
|
||||
118
src/swtpm_setup/swtpm_backend_dir.c
Normal file
118
src/swtpm_setup/swtpm_backend_dir.c
Normal file
@ -0,0 +1,118 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* swtpm_backend_dir.c: storage backend specific functions for dir://
|
||||
*
|
||||
* Originally by: Stefan Berger, stefanb@linux.ibm.com
|
||||
* Refactored as module: Stefan Reiter, stefan@pimaker.at
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "swtpm.h"
|
||||
#include "swtpm_utils.h"
|
||||
|
||||
struct dir_state {
|
||||
gchar* dir;
|
||||
};
|
||||
|
||||
/* Parse a dir:// URI by removing the prefix if given. */
|
||||
static void *parse_dir_state(const gchar* uri) {
|
||||
struct dir_state *ret;
|
||||
|
||||
if (strncmp(uri, "dir://", 6) == 0) {
|
||||
uri += 6;
|
||||
}
|
||||
|
||||
ret = g_malloc(sizeof(struct dir_state));
|
||||
ret->dir = g_strdup(uri);
|
||||
|
||||
return (void*)ret;
|
||||
}
|
||||
|
||||
/* Check user access in 'mode' to directory specified in backend state. */
|
||||
static int check_access(void *state, int mode, const struct passwd *curr_user) {
|
||||
gchar *tpm_state_path = ((struct dir_state*)state)->dir;
|
||||
gchar *p;
|
||||
struct stat statbuf;
|
||||
char path[PATH_MAX];
|
||||
|
||||
/* check lockfile */
|
||||
p = pathjoin(path, sizeof(path), tpm_state_path, ".lock", NULL);
|
||||
if (!p)
|
||||
return 1;
|
||||
if (stat(p, &statbuf) == 0 && access(p, R_OK|W_OK) != 0) {
|
||||
logerr(gl_LOGFILE, "User %s cannot read/write lockfile %s.\n",
|
||||
curr_user ? curr_user->pw_name : "<unknown>", p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check access to state directory itself */
|
||||
return check_directory_access(tpm_state_path, mode, curr_user);
|
||||
}
|
||||
|
||||
/* Delete swtpm's state file. Those are the files with suffixes
|
||||
* 'permall', 'volatilestate', and 'savestate'.
|
||||
*/
|
||||
static int delete_statefiles(void *state)
|
||||
{
|
||||
gchar *tpm_state_path = ((struct dir_state*)state)->dir;
|
||||
GError *error = NULL;
|
||||
GDir *dir = g_dir_open(tpm_state_path, 0, &error);
|
||||
int ret = 1;
|
||||
|
||||
if (dir == NULL) {
|
||||
logerr(gl_LOGFILE, "%s\n", error->message);
|
||||
g_error_free(error);
|
||||
return 1;
|
||||
}
|
||||
while (1) {
|
||||
const gchar *fn = g_dir_read_name(dir);
|
||||
|
||||
if (fn == NULL) {
|
||||
if (errno != 0 && errno != ENOENT
|
||||
#ifdef __FreeBSD__
|
||||
&& errno != EINVAL
|
||||
#endif
|
||||
) {
|
||||
logerr(gl_LOGFILE, "Error getting next filename: %s\n", strerror(errno));
|
||||
break;
|
||||
} else {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (g_str_has_suffix(fn, "permall") ||
|
||||
g_str_has_suffix(fn, "volatilestate") ||
|
||||
g_str_has_suffix(fn, "savestate")) {
|
||||
g_autofree gchar *fullname = g_strjoin(G_DIR_SEPARATOR_S,
|
||||
tpm_state_path, fn, NULL);
|
||||
if (unlink(fullname) != 0) {
|
||||
logerr(gl_LOGFILE, "Could not remove %s: %s\n", fn, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Free an instance of dir_state. */
|
||||
static void free_dir_state(void *state) {
|
||||
if (state) {
|
||||
struct dir_state *dstate = (struct dir_state*)state;
|
||||
g_free(dstate->dir);
|
||||
g_free(dstate);
|
||||
}
|
||||
}
|
||||
|
||||
struct swtpm_backend_ops swtpm_backend_dir = {
|
||||
.parse_backend = parse_dir_state,
|
||||
.check_access = check_access,
|
||||
.delete_state = delete_statefiles,
|
||||
.free_backend = free_dir_state,
|
||||
};
|
||||
@ -703,14 +703,14 @@ static int check_state_overwrite(gchar **swtpm_prg_l, unsigned int flags,
|
||||
int exit_status = 0;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree gchar **argv = NULL;
|
||||
g_autofree gchar *dirop = g_strdup_printf("dir=%s", tpm_state_path);
|
||||
g_autofree gchar *statearg = g_strdup_printf("backend-uri=%s", tpm_state_path);
|
||||
g_autofree gchar *logop = NULL;
|
||||
g_autofree gchar **my_argv = NULL;
|
||||
|
||||
my_argv = concat_arrays((gchar*[]) {
|
||||
"--print-states",
|
||||
"--tpmstate",
|
||||
dirop,
|
||||
statearg,
|
||||
NULL
|
||||
}, NULL, FALSE);
|
||||
|
||||
@ -1081,53 +1081,6 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Delete swtpm's state file. Those are the files with suffixes
|
||||
* 'permall', 'volatilestate', and 'savestate'.
|
||||
*/
|
||||
static int delete_swtpm_statefiles(const gchar *tpm_state_path)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GDir *dir = g_dir_open(tpm_state_path, 0, &error);
|
||||
int ret = 1;
|
||||
|
||||
if (dir == NULL) {
|
||||
logerr(gl_LOGFILE, "%s\n", error->message);
|
||||
g_error_free(error);
|
||||
return 1;
|
||||
}
|
||||
while (1) {
|
||||
const gchar *fn = g_dir_read_name(dir);
|
||||
|
||||
if (fn == NULL) {
|
||||
if (errno != 0 && errno != ENOENT
|
||||
#ifdef __FreeBSD__
|
||||
&& errno != EINVAL
|
||||
#endif
|
||||
) {
|
||||
logerr(gl_LOGFILE, "Error getting next filename: %s\n", strerror(errno));
|
||||
break;
|
||||
} else {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (g_str_has_suffix(fn, "permall") ||
|
||||
g_str_has_suffix(fn, "volatilestate") ||
|
||||
g_str_has_suffix(fn, "savestate")) {
|
||||
g_autofree gchar *fullname = g_strjoin(G_DIR_SEPARATOR_S,
|
||||
tpm_state_path, fn, NULL);
|
||||
if (unlink(fullname) != 0) {
|
||||
logerr(gl_LOGFILE, "Coud not remove %s: %s\n", fn, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt, option_index = 0;
|
||||
@ -1174,6 +1127,8 @@ int main(int argc, char *argv[])
|
||||
unsigned long flags = 0;
|
||||
g_autofree gchar *swtpm_prg = NULL;
|
||||
g_autofree gchar *tpm_state_path = NULL;
|
||||
struct swtpm_backend_ops *backend_ops = &swtpm_backend_dir;
|
||||
void *backend_state = NULL;
|
||||
g_autofree gchar *config_file = NULL;
|
||||
g_autofree gchar *ownerpass = NULL;
|
||||
gboolean got_ownerpass = FALSE;
|
||||
@ -1201,10 +1156,7 @@ int main(int argc, char *argv[])
|
||||
const struct passwd *curr_user;
|
||||
struct group *curr_grp;
|
||||
char *endptr;
|
||||
char path[PATH_MAX];
|
||||
char *p;
|
||||
gboolean swtpm_has_tpm12, swtpm_has_tpm2;
|
||||
g_autofree gchar *lockfile = NULL;
|
||||
int fds_to_pass[1] = { -1 };
|
||||
unsigned n_fds_to_pass = 0;
|
||||
char tmpbuffer[200];
|
||||
@ -1228,7 +1180,12 @@ int main(int argc, char *argv[])
|
||||
switch (opt) {
|
||||
case 't': /* --tpmstate, --tpm-state */
|
||||
g_free(tpm_state_path);
|
||||
tpm_state_path = g_strdup(optarg);
|
||||
if (strncmp(optarg, "dir://", 6) == 0) {
|
||||
tpm_state_path = g_strdup(optarg);
|
||||
} else {
|
||||
/* always prefix with dir:// so we can pass verbatim to swtpm */
|
||||
tpm_state_path = g_strconcat("dir://", optarg, NULL);
|
||||
}
|
||||
break;
|
||||
case 'T': /* --tpm */
|
||||
g_free(swtpm_prg);
|
||||
@ -1446,7 +1403,12 @@ int main(int argc, char *argv[])
|
||||
logerr(gl_LOGFILE, "--tpm-state must be provided\n");
|
||||
goto error;
|
||||
}
|
||||
if (check_directory_access(tpm_state_path, R_OK|W_OK, curr_user) != 0)
|
||||
|
||||
backend_state = backend_ops->parse_backend(tpm_state_path);
|
||||
if (!backend_state)
|
||||
goto error;
|
||||
|
||||
if (backend_ops->check_access(backend_state, R_OK|W_OK, curr_user) != 0)
|
||||
goto error;
|
||||
|
||||
if ((flags & SETUP_WRITE_EK_CERT_FILES_F)) {
|
||||
@ -1478,20 +1440,10 @@ int main(int argc, char *argv[])
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = delete_swtpm_statefiles(tpm_state_path);
|
||||
ret = backend_ops->delete_state(backend_state);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
|
||||
p = pathjoin(path, sizeof(path), tpm_state_path, ".lock", NULL);
|
||||
if (!p)
|
||||
goto error;
|
||||
lockfile = g_strdup(p);
|
||||
if (stat(lockfile, &statbuf) == 0 && access(lockfile, R_OK|W_OK) != 0) {
|
||||
logerr(gl_LOGFILE, "User %s cannot read/write lockfile %s.\n",
|
||||
curr_user ? curr_user->pw_name : "<unknown>", lockfile);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (access(config_file, R_OK) != 0) {
|
||||
logerr(gl_LOGFILE, "User %s cannot read config file %s.\n",
|
||||
curr_user ? curr_user->pw_name : "<unknown>", config_file);
|
||||
@ -1608,7 +1560,7 @@ int main(int argc, char *argv[])
|
||||
logit(gl_LOGFILE, "Successfully authored TPM state.\n");
|
||||
} else {
|
||||
logerr(gl_LOGFILE, "An error occurred. Authoring the TPM state failed.\n");
|
||||
delete_swtpm_statefiles(tpm_state_path);
|
||||
backend_ops->delete_state(backend_state);
|
||||
}
|
||||
|
||||
now = time(NULL);
|
||||
@ -1625,6 +1577,8 @@ out:
|
||||
logerr(gl_LOGFILE, "Could not remove temporary directory for certs: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
if (backend_ops && backend_state)
|
||||
backend_ops->free_backend(backend_state);
|
||||
g_strfreev(swtpm_prg_l);
|
||||
g_free(gl_LOGFILE);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user