]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
tpm: Parse the capabilities supported by swtpm and swtpm_setup
authorStefan Berger <stefanb@linux.vnet.ibm.com>
Thu, 25 Jul 2019 18:22:05 +0000 (14:22 -0400)
committerDaniel P. Berrangé <berrange@redhat.com>
Fri, 26 Jul 2019 09:30:46 +0000 (10:30 +0100)
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>
include/libvirt/virterror.h
src/libvirt_private.syms
src/util/virerror.c
src/util/virtpm.c
src/util/virtpm.h

index 102a2573bf828d109c78839b1287984086b84eda..6f4110185a2406676a7c575e6009bc077f4e1e84 100644 (file)
@@ -134,6 +134,8 @@ typedef enum {
     VIR_FROM_FIREWALLD = 68,    /* Error from firewalld */
     VIR_FROM_DOMAIN_CHECKPOINT = 69, /* Error from domain checkpoint */
 
+    VIR_FROM_TPM = 70,          /* Error from TPM */
+
 # ifdef VIR_ENUM_SENTINELS
     VIR_ERR_DOMAIN_LAST
 # endif
index 4cdbb8059621581cba92cb92967c29fe8541614b..cf80ea3e44fa148deabd0b7ab5dcbccdc1cdb0d2 100644 (file)
@@ -3181,6 +3181,8 @@ virTPMEmulatorInit;
 virTPMGetSwtpm;
 virTPMGetSwtpmIoctl;
 virTPMGetSwtpmSetup;
+virTPMSwtpmFeatureTypeFromString;
+virTPMSwtpmSetupFeatureTypeFromString;
 
 
 # util/virtypedparam.h
index dfba8c5712384126888b884e94b668cbda1eb5e7..77f76a9abf48f4b5133fe505d7602749fa77eeeb 100644 (file)
@@ -142,6 +142,8 @@ VIR_ENUM_IMPL(virErrorDomain,
               "Resource control",
               "FirewallD",
               "Domain Checkpoint",
+
+              "TPM", /* 70 */
 );
 
 
index 6228f3187df03a3cfb5edc0c8b59ae74e2e12bc5..2745c54f816f66893276fc185336f1f8bc1c4be7 100644 (file)
 #include "viralloc.h"
 #include "virfile.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:
@@ -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 char *swtpm_path;
 static struct stat swtpm_stat;
+static virBitmapPtr swtpm_caps;
 
 static char *swtpm_setup;
 static struct stat swtpm_setup_stat;
+static virBitmapPtr swtpm_setup_caps;
 
 static char *swtpm_ioctl;
 static struct stat swtpm_ioctl_stat;
 
+typedef int (*TypeFromStringFn)(const char *);
+
 char *
 virTPMGetSwtpm(void)
 {
@@ -131,6 +152,101 @@ virTPMGetSwtpmIoctl(void)
     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
  *
@@ -145,16 +261,24 @@ virTPMEmulatorInit(void)
         const char *name;
         char **path;
         struct stat *stat;
+        const char *parm;
+        virBitmapPtr *caps;
+        TypeFromStringFn typeFromStringFn;
     } prgs[] = {
         {
             .name = "swtpm",
             .path = &swtpm_path,
             .stat = &swtpm_stat,
+            .parm = "socket",
+            .caps = &swtpm_caps,
+            .typeFromStringFn = virTPMSwtpmFeatureTypeFromString,
         },
         {
             .name = "swtpm_setup",
             .path = &swtpm_setup,
             .stat = &swtpm_setup_stat,
+            .caps = &swtpm_setup_caps,
+            .typeFromStringFn = virTPMSwtpmSetupFeatureTypeFromString,
         },
         {
             .name = "swtpm_ioctl",
@@ -206,6 +330,14 @@ virTPMEmulatorInit(void)
                 goto cleanup;
             }
             *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;
         }
     }
index 2311f04ae572e4c36dc23ba7566b929c047dd5ca..157b43ff177a595b1c2ffd7fe27e3f1ad6bb62a2 100644 (file)
@@ -26,3 +26,18 @@ char *virTPMGetSwtpm(void);
 char *virTPMGetSwtpmSetup(void);
 char *virTPMGetSwtpmIoctl(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);