[Libosinfo] [PATCH v3 58/60] loader: sanity check entity filenames when loading
Daniel P. Berrange
berrange at redhat.com
Mon Oct 12 17:11:19 UTC 2015
When we have loaded the id attribute of the entity, check it
against the entity filename to ensure its XML document was
held in a file with the modern naming.
This merely prints out a warning for now to avoid breaking
existing users, but in the future, files with non-compliant
names will not be loaded at all.
Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
osinfo/osinfo_loader.c | 105 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 97 insertions(+), 8 deletions(-)
diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c
index f7b841d..8a21a1b 100644
--- a/osinfo/osinfo_loader.c
+++ b/osinfo/osinfo_loader.c
@@ -30,6 +30,7 @@
#include <gio/gio.h>
#include <string.h>
+#include <ctype.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
@@ -487,7 +488,49 @@ static OsinfoInstallScript *osinfo_loader_get_install_script(OsinfoLoader *loade
return script;
}
+
+static gboolean osinfo_loader_check_id(const gchar *relpath,
+ const gchar *type,
+ const gchar *id)
+{
+ gchar *name;
+ gchar *suffix;
+ gboolean sep = FALSE;
+ gsize i;
+ if (g_str_has_prefix(id, "http://")) {
+ suffix = g_strdup(id + strlen("http://"));
+ } else {
+ suffix = g_strdup(id);
+ }
+ for (i = 0; suffix[i]; i++) {
+ if (suffix[i] == '/' && !sep) {
+ sep = TRUE;
+ } else if (!isalnum(suffix[i]) &&
+ suffix[i] != '-' &&
+ suffix[i] != '.' &&
+ suffix[i] != '_') {
+ suffix[i] = '-';
+ }
+ }
+ name = g_strdup_printf("/%s/%s.xml", type, suffix);
+ g_free(suffix);
+
+ if (!g_str_equal(relpath, name)) {
+ g_warning("Entity %s should be in file %s not %s",
+ id, name, relpath);
+ return TRUE; /* In future switch to FALSE to refuse
+ * to load non-compliant named files.
+ * Need a period of grace for backcompat
+ * first though... Switch ETA Jan 2017
+ */
+ }
+ g_free(name);
+ return TRUE;
+}
+
+
static void osinfo_loader_device(OsinfoLoader *loader,
+ const gchar *relpath,
xmlXPathContextPtr ctxt,
xmlNodePtr root,
GError **err)
@@ -508,6 +551,10 @@ static void osinfo_loader_device(OsinfoLoader *loader,
OSINFO_ERROR(err, _("Missing device id property"));
return;
}
+ if (!osinfo_loader_check_id(relpath, "device", id)) {
+ xmlFree(id);
+ return;
+ }
OsinfoDevice *device = osinfo_loader_get_device(loader, id);
g_hash_table_remove(loader->priv->entity_refs, id);
@@ -652,6 +699,7 @@ static void osinfo_loader_product(OsinfoLoader *loader,
}
static void osinfo_loader_platform(OsinfoLoader *loader,
+ const gchar *relpath,
xmlXPathContextPtr ctxt,
xmlNodePtr root,
GError **err)
@@ -661,6 +709,10 @@ static void osinfo_loader_platform(OsinfoLoader *loader,
OSINFO_ERROR(err, _("Missing platform id property"));
return;
}
+ if (!osinfo_loader_check_id(relpath, "platform", id)) {
+ xmlFree(id);
+ return;
+ }
OsinfoPlatform *platform = osinfo_loader_get_platform(loader, id);
g_hash_table_remove(loader->priv->entity_refs, id);
@@ -681,6 +733,7 @@ static void osinfo_loader_platform(OsinfoLoader *loader,
}
static void osinfo_loader_deployment(OsinfoLoader *loader,
+ const gchar *relpath,
xmlXPathContextPtr ctxt,
xmlNodePtr root,
GError **err)
@@ -690,6 +743,10 @@ static void osinfo_loader_deployment(OsinfoLoader *loader,
OSINFO_ERROR(err, _("Missing deployment id property"));
return;
}
+ if (!osinfo_loader_check_id(relpath, "deployment", id)) {
+ xmlFree(id);
+ return;
+ }
gchar *osid = osinfo_loader_string("string(./os/@id)", loader, ctxt, err);
if (!osid && 0) {
@@ -730,6 +787,7 @@ static void osinfo_loader_deployment(OsinfoLoader *loader,
}
static void osinfo_loader_datamap(OsinfoLoader *loader,
+ const gchar *relpath,
xmlXPathContextPtr ctxt,
xmlNodePtr root,
GError **err)
@@ -744,6 +802,10 @@ static void osinfo_loader_datamap(OsinfoLoader *loader,
OSINFO_ERROR(err, _("Missing os id property"));
return;
}
+ if (!osinfo_loader_check_id(relpath, "datamap", id)) {
+ xmlFree(id);
+ return;
+ }
OsinfoDatamap *map = osinfo_loader_get_datamap(loader, id);
g_hash_table_remove(loader->priv->entity_refs, id);
@@ -836,6 +898,7 @@ static OsinfoAvatarFormat *osinfo_loader_avatar_format(OsinfoLoader *loader,
}
static void osinfo_loader_install_script(OsinfoLoader *loader,
+ const gchar *relpath,
xmlXPathContextPtr ctxt,
xmlNodePtr root,
GError **err)
@@ -864,6 +927,10 @@ static void osinfo_loader_install_script(OsinfoLoader *loader,
return;
}
+ if (!osinfo_loader_check_id(relpath, "install-script", id)) {
+ xmlFree(id);
+ return;
+ }
OsinfoInstallScript *installScript = osinfo_loader_get_install_script(loader,
id);
g_hash_table_remove(loader->priv->entity_refs, id);
@@ -1291,6 +1358,7 @@ static OsinfoDeviceDriver *osinfo_loader_driver(OsinfoLoader *loader,
static void osinfo_loader_os(OsinfoLoader *loader,
+ const gchar *relpath,
xmlXPathContextPtr ctxt,
xmlNodePtr root,
GError **err)
@@ -1311,6 +1379,10 @@ static void osinfo_loader_os(OsinfoLoader *loader,
OSINFO_ERROR(err, _("Missing os id property"));
return;
}
+ if (!osinfo_loader_check_id(relpath, "os", id)) {
+ xmlFree(id);
+ return;
+ }
OsinfoOs *os = osinfo_loader_get_os(loader, id);
g_hash_table_remove(loader->priv->entity_refs, id);
@@ -1459,6 +1531,7 @@ cleanup:
}
static void osinfo_loader_root(OsinfoLoader *loader,
+ const gchar *relpath,
xmlXPathContextPtr ctxt,
xmlNodePtr root,
GError **err)
@@ -1494,22 +1567,22 @@ static void osinfo_loader_root(OsinfoLoader *loader,
ctxt->node = it;
if (xmlStrEqual(it->name, BAD_CAST "device"))
- osinfo_loader_device(loader, ctxt, it, err);
+ osinfo_loader_device(loader, relpath, ctxt, it, err);
else if (xmlStrEqual(it->name, BAD_CAST "platform"))
- osinfo_loader_platform(loader, ctxt, it, err);
+ osinfo_loader_platform(loader, relpath, ctxt, it, err);
else if (xmlStrEqual(it->name, BAD_CAST "os"))
- osinfo_loader_os(loader, ctxt, it, err);
+ osinfo_loader_os(loader, relpath, ctxt, it, err);
else if (xmlStrEqual(it->name, BAD_CAST "deployment"))
- osinfo_loader_deployment(loader, ctxt, it, err);
+ osinfo_loader_deployment(loader, relpath, ctxt, it, err);
else if (xmlStrEqual(it->name, BAD_CAST "install-script"))
- osinfo_loader_install_script(loader, ctxt, it, err);
+ osinfo_loader_install_script(loader, relpath, ctxt, it, err);
else if (xmlStrEqual(it->name, BAD_CAST "datamap"))
- osinfo_loader_datamap(loader, ctxt, it, err);
+ osinfo_loader_datamap(loader, relpath, ctxt, it, err);
ctxt->node = saved;
@@ -1536,6 +1609,7 @@ catchXMLError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
}
static void osinfo_loader_process_xml(OsinfoLoader *loader,
+ const gchar *relpath,
const gchar *xmlStr,
const gchar *src,
GError **err)
@@ -1580,7 +1654,7 @@ static void osinfo_loader_process_xml(OsinfoLoader *loader,
ctxt->node = root;
- osinfo_loader_root(loader, ctxt, root, err);
+ osinfo_loader_root(loader, relpath, ctxt, root, err);
cleanup:
xmlXPathFreeContext(ctxt);
@@ -1741,22 +1815,37 @@ osinfo_loader_process_file_reg_pci(OsinfoLoader *loader,
static void
osinfo_loader_process_file_reg_xml(OsinfoLoader *loader,
+ GFile *base,
GFile *file,
GError **err)
{
gchar *xml = NULL;
gsize xmlLen;
+ gchar *basepath, *filepath;
+ const gchar *relpath;
+
g_file_load_contents(file, NULL, &xml, &xmlLen, NULL, err);
if (error_is_set(err))
return;
+ basepath = g_file_get_path(base);
+ filepath = g_file_get_path(file);
+ if (g_str_has_prefix(filepath, basepath)) {
+ relpath = filepath + strlen(basepath);
+ } else {
+ relpath = filepath;
+ g_warning("File %s does not have prefix %s", filepath, basepath);
+ }
gchar *uri = g_file_get_uri(file);
osinfo_loader_process_xml(loader,
+ relpath,
xml,
uri,
err);
g_free(uri);
g_free(xml);
+ g_free(filepath);
+ g_free(basepath);
}
@@ -1838,7 +1927,7 @@ static void osinfo_loader_process_list(OsinfoLoader *loader,
tmp = files;
while (tmp) {
- osinfo_loader_process_file_reg_xml(loader, tmp->data, &lerr);
+ osinfo_loader_process_file_reg_xml(loader, *dirs, tmp->data, &lerr);
if (lerr) {
g_propagate_error(err, lerr);
break;
--
2.4.3
More information about the Libosinfo
mailing list