tpm: Parse the capabilities supported by swtpm and swtpm_setup

Run 'swtpm socket --print-capabilities' and
'swtpm_setup --print-capabilities' to get the JSON object of the
features the programs are supporting and parse them into a bitmap.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Stefan Berger 2019-07-25 14:22:05 -04:00 committed by Daniel P. Berrangé
parent 01cf7a1bb9
commit 1f46dd4cba
5 changed files with 155 additions and 2 deletions

View File

@ -134,6 +134,8 @@ typedef enum {
VIR_FROM_FIREWALLD = 68, /* Error from firewalld */ VIR_FROM_FIREWALLD = 68, /* Error from firewalld */
VIR_FROM_DOMAIN_CHECKPOINT = 69, /* Error from domain checkpoint */ VIR_FROM_DOMAIN_CHECKPOINT = 69, /* Error from domain checkpoint */
VIR_FROM_TPM = 70, /* Error from TPM */
# ifdef VIR_ENUM_SENTINELS # ifdef VIR_ENUM_SENTINELS
VIR_ERR_DOMAIN_LAST VIR_ERR_DOMAIN_LAST
# endif # endif

View File

@ -3181,6 +3181,8 @@ virTPMEmulatorInit;
virTPMGetSwtpm; virTPMGetSwtpm;
virTPMGetSwtpmIoctl; virTPMGetSwtpmIoctl;
virTPMGetSwtpmSetup; virTPMGetSwtpmSetup;
virTPMSwtpmFeatureTypeFromString;
virTPMSwtpmSetupFeatureTypeFromString;
# util/virtypedparam.h # util/virtypedparam.h

View File

@ -142,6 +142,8 @@ VIR_ENUM_IMPL(virErrorDomain,
"Resource control", "Resource control",
"FirewallD", "FirewallD",
"Domain Checkpoint", "Domain Checkpoint",
"TPM", /* 70 */
); );

View File

@ -27,8 +27,24 @@
#include "viralloc.h" #include "viralloc.h"
#include "virfile.h" #include "virfile.h"
#include "virtpm.h" #include "virtpm.h"
#include "vircommand.h"
#include "virbitmap.h"
#include "virjson.h"
#include "virlog.h"
#define VIR_FROM_THIS VIR_FROM_NONE #define VIR_FROM_THIS VIR_FROM_TPM
VIR_LOG_INIT("util.tpm");
VIR_ENUM_IMPL(virTPMSwtpmFeature,
VIR_TPM_SWTPM_FEATURE_LAST,
"cmdarg-pwd-fd",
);
VIR_ENUM_IMPL(virTPMSwtpmSetupFeature,
VIR_TPM_SWTPM_SETUP_FEATURE_LAST,
"cmdarg-pwdfile-fd",
);
/** /**
* virTPMCreateCancelPath: * virTPMCreateCancelPath:
@ -74,18 +90,23 @@ virTPMCreateCancelPath(const char *devpath)
} }
/* /*
* executables for the swtpm; to be found on the host * executables for the swtpm; to be found on the host along with
* capabilties bitmap
*/ */
static virMutex swtpm_tools_lock = VIR_MUTEX_INITIALIZER; static virMutex swtpm_tools_lock = VIR_MUTEX_INITIALIZER;
static char *swtpm_path; static char *swtpm_path;
static struct stat swtpm_stat; static struct stat swtpm_stat;
static virBitmapPtr swtpm_caps;
static char *swtpm_setup; static char *swtpm_setup;
static struct stat swtpm_setup_stat; static struct stat swtpm_setup_stat;
static virBitmapPtr swtpm_setup_caps;
static char *swtpm_ioctl; static char *swtpm_ioctl;
static struct stat swtpm_ioctl_stat; static struct stat swtpm_ioctl_stat;
typedef int (*TypeFromStringFn)(const char *);
char * char *
virTPMGetSwtpm(void) virTPMGetSwtpm(void)
{ {
@ -131,6 +152,101 @@ virTPMGetSwtpmIoctl(void)
return s; return s;
} }
/* virTPMExecGetCaps
*
* Execute the prepared command and parse the returned JSON object
* to get the capabilities supported by the executable.
* A JSON object like this is expected:
*
* {
* "type": "swtpm",
* "features": [
* "cmdarg-seccomp",
* "cmdarg-key-fd",
* "cmdarg-pwd-fd"
* ]
* }
*/
static virBitmapPtr
virTPMExecGetCaps(virCommandPtr cmd,
TypeFromStringFn typeFromStringFn)
{
int exitstatus;
virBitmapPtr bitmap;
VIR_AUTOFREE(char *) outbuf = NULL;
VIR_AUTOPTR(virJSONValue) json = NULL;
virJSONValuePtr featureList;
virJSONValuePtr item;
size_t idx;
const char *str;
int typ;
virCommandSetOutputBuffer(cmd, &outbuf);
if (virCommandRun(cmd, &exitstatus) < 0)
return NULL;
if (!(bitmap = virBitmapNewEmpty()))
return NULL;
/* older version does not support --print-capabilties -- that's fine */
if (exitstatus != 0) {
VIR_DEBUG("Found swtpm that doesn't support --print-capabilities");
return bitmap;
}
json = virJSONValueFromString(outbuf);
if (!json)
goto error_bad_json;
featureList = virJSONValueObjectGetArray(json, "features");
if (!featureList)
goto error_bad_json;
if (!virJSONValueIsArray(featureList))
goto error_bad_json;
for (idx = 0; idx < virJSONValueArraySize(featureList); idx++) {
item = virJSONValueArrayGet(featureList, idx);
if (!item)
continue;
str = virJSONValueGetString(item);
if (!str)
goto error_bad_json;
typ = typeFromStringFn(str);
if (typ < 0)
continue;
if (virBitmapSetBitExpand(bitmap, typ) < 0)
goto cleanup;
}
cleanup:
return bitmap;
error_bad_json:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected JSON format: %s"), outbuf);
goto cleanup;
}
static virBitmapPtr
virTPMGetCaps(TypeFromStringFn typeFromStringFn,
const char *exec, const char *param1)
{
VIR_AUTOPTR(virCommand) cmd = NULL;
if (!(cmd = virCommandNew(exec)))
return NULL;
if (param1)
virCommandAddArg(cmd, param1);
virCommandAddArg(cmd, "--print-capabilities");
virCommandClearCaps(cmd);
return virTPMExecGetCaps(cmd, typeFromStringFn);
}
/* /*
* virTPMEmulatorInit * virTPMEmulatorInit
* *
@ -145,16 +261,24 @@ virTPMEmulatorInit(void)
const char *name; const char *name;
char **path; char **path;
struct stat *stat; struct stat *stat;
const char *parm;
virBitmapPtr *caps;
TypeFromStringFn typeFromStringFn;
} prgs[] = { } prgs[] = {
{ {
.name = "swtpm", .name = "swtpm",
.path = &swtpm_path, .path = &swtpm_path,
.stat = &swtpm_stat, .stat = &swtpm_stat,
.parm = "socket",
.caps = &swtpm_caps,
.typeFromStringFn = virTPMSwtpmFeatureTypeFromString,
}, },
{ {
.name = "swtpm_setup", .name = "swtpm_setup",
.path = &swtpm_setup, .path = &swtpm_setup,
.stat = &swtpm_setup_stat, .stat = &swtpm_setup_stat,
.caps = &swtpm_setup_caps,
.typeFromStringFn = virTPMSwtpmSetupFeatureTypeFromString,
}, },
{ {
.name = "swtpm_ioctl", .name = "swtpm_ioctl",
@ -206,6 +330,14 @@ virTPMEmulatorInit(void)
goto cleanup; goto cleanup;
} }
*prgs[i].path = path; *prgs[i].path = path;
if (prgs[i].caps) {
*prgs[i].caps = virTPMGetCaps(prgs[i].typeFromStringFn,
path, prgs[i].parm);
path = NULL;
if (!*prgs[i].caps)
goto cleanup;
}
path = NULL; path = NULL;
} }
} }

View File

@ -26,3 +26,18 @@ char *virTPMGetSwtpm(void);
char *virTPMGetSwtpmSetup(void); char *virTPMGetSwtpmSetup(void);
char *virTPMGetSwtpmIoctl(void); char *virTPMGetSwtpmIoctl(void);
int virTPMEmulatorInit(void); int virTPMEmulatorInit(void);
typedef enum {
VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD,
VIR_TPM_SWTPM_FEATURE_LAST
} virTPMSwtpmFeature;
typedef enum {
VIR_TPM_SWTPM_SETUP_FEATURE_CMDARG_PWDFILE_FD,
VIR_TPM_SWTPM_SETUP_FEATURE_LAST
} virTPMSwtpmSetupFeature;
VIR_ENUM_DECL(virTPMSwtpmFeature);
VIR_ENUM_DECL(virTPMSwtpmSetupFeature);