Fixed URI parsing

Function xmlParseURI does not remove square brackets around IPv6
address when parsing. One of the solutions is making wrappers around
functions working with xmlURI*. This assures that uri->server will be
always properly assigned and it doesn't have to be changed when used
on some new place in the code.
For this purpose, functions virParseURI and virSaveURI were
added. These function are wrappers around xmlParseURI and xmlSaveUri
respectively.
Also there is one new syntax check function to prohibit these functions
anywhere else.

File changes:
 - src/util/viruri.h        -- declaration
 - src/util/viruri.c        -- definition
 - src/libvirt_private.syms -- symbol export
 - src/Makefile.am          -- added source and header files
 - cfg.mk                   -- added sc_prohibit_xmlURI
 - all others               -- ID name and include fixes
This commit is contained in:
Martin Kletzander 2012-02-24 19:48:55 +01:00 committed by Eric Blake
parent 801a60ff88
commit 9f748277bb
30 changed files with 181 additions and 49 deletions

8
cfg.mk
View File

@ -457,6 +457,12 @@ sc_prohibit_xmlGetProp:
halt='use virXMLPropString, not xmlGetProp' \
$(_sc_search_regexp)
# xml(ParseURI|SaveUri) doesn't handle IPv6 URIs well
sc_prohibit_xmlURI:
@prohibit='\<xml(ParseURI|SaveUri) *\(' \
halt='use virURI(Parse|Format), not xml(ParseURI|SaveUri)' \
$(_sc_search_regexp)
# ATTRIBUTE_UNUSED should only be applied in implementations, not
# header declarations
sc_avoid_attribute_unused_in_header:
@ -758,6 +764,8 @@ exclude_file_name_regexp--sc_prohibit_strncpy = \
exclude_file_name_regexp--sc_prohibit_xmlGetProp = ^src/util/xml\.c$$
exclude_file_name_regexp--sc_prohibit_xmlURI = ^src/util/viruri\.c$$
exclude_file_name_regexp--sc_require_config_h = ^examples/
exclude_file_name_regexp--sc_require_config_h_first = ^examples/

View File

@ -104,7 +104,8 @@ UTIL_SOURCES = \
util/virnetlink.c util/virnetlink.h \
util/virrandom.h util/virrandom.c \
util/virsocketaddr.h util/virsocketaddr.c \
util/virtime.h util/virtime.c
util/virtime.h util/virtime.c \
util/viruri.h util/viruri.c
EXTRA_DIST += $(srcdir)/util/virkeymaps.h $(srcdir)/util/keymaps.csv \
$(srcdir)/util/virkeycode-mapgen.py

View File

@ -151,7 +151,7 @@ struct _virConnect {
*/
unsigned int magic; /* specific value to check */
unsigned int flags; /* a set of connection flags */
xmlURIPtr uri; /* connection URI */
virURIPtr uri; /* connection URI */
/* The underlying hypervisor driver and network driver. */
virDriverPtr driver;

View File

@ -9,9 +9,9 @@
# include "config.h"
# include <unistd.h>
# include <libxml/uri.h>
# include "internal.h"
# include "viruri.h"
/*
* List of registered drivers numbers
*/

View File

@ -44,6 +44,7 @@
#include "esx_vi.h"
#include "esx_vi_methods.h"
#include "esx_util.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_ESX
@ -3945,7 +3946,7 @@ esxDomainMigratePerform(virDomainPtr domain,
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
xmlURIPtr parsedUri = NULL;
virURIPtr parsedUri = NULL;
char *saveptr;
char *path_resourcePool;
char *path_hostSystem;
@ -3976,7 +3977,7 @@ esxDomainMigratePerform(virDomainPtr domain,
}
/* Parse migration URI */
parsedUri = xmlParseURI(uri);
parsedUri = virURIParse(uri);
if (parsedUri == NULL) {
virReportOOMError();

View File

@ -42,7 +42,7 @@
int
esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, xmlURIPtr uri)
esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, virURIPtr uri)
{
int result = -1;
struct qparam_set *queryParamSet = NULL;

View File

@ -22,9 +22,9 @@
#ifndef __ESX_UTIL_H__
# define __ESX_UTIL_H__
# include <libxml/uri.h>
# include <netdb.h>
# include "internal.h"
# include "viruri.h"
typedef struct _esxUtil_ParsedUri esxUtil_ParsedUri;
@ -40,7 +40,7 @@ struct _esxUtil_ParsedUri {
char *path;
};
int esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, xmlURIPtr uri);
int esxUtil_ParseUri(esxUtil_ParsedUri **parsedUri, virURIPtr uri);
void esxUtil_FreeParsedUri(esxUtil_ParsedUri **parsedUri);

View File

@ -37,7 +37,7 @@
int
hypervParseUri(hypervParsedUri **parsedUri, xmlURIPtr uri)
hypervParseUri(hypervParsedUri **parsedUri, virURIPtr uri)
{
int result = -1;
struct qparam_set *queryParamSet = NULL;

View File

@ -23,9 +23,8 @@
#ifndef __HYPERV_UTIL_H__
# define __HYPERV_UTIL_H__
# include <libxml/uri.h>
# include "internal.h"
# include "viruri.h"
typedef struct _hypervParsedUri hypervParsedUri;
@ -33,7 +32,7 @@ struct _hypervParsedUri {
char *transport;
};
int hypervParseUri(hypervParsedUri **parsedUri, xmlURIPtr uri);
int hypervParseUri(hypervParsedUri **parsedUri, virURIPtr uri);
void hypervFreeParsedUri(hypervParsedUri **parsedUri);

View File

@ -23,7 +23,6 @@
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/uri.h>
#include "getpass.h"
#ifdef HAVE_WINSOCK2_H
@ -44,6 +43,7 @@
#include "command.h"
#include "virnodesuspend.h"
#include "virrandom.h"
#include "viruri.h"
#ifndef WITH_DRIVER_MODULES
# ifdef WITH_TEST
@ -1127,7 +1127,7 @@ do_open (const char *name,
virConnectOpenResolveURIAlias(name, &alias) < 0)
goto failed;
ret->uri = xmlParseURI (alias ? alias : name);
ret->uri = virURIParse (alias ? alias : name);
if (!ret->uri) {
virLibConnError(VIR_ERR_INVALID_ARG,
_("could not parse connection URI %s"),
@ -1729,7 +1729,7 @@ virConnectGetURI (virConnectPtr conn)
return NULL;
}
name = (char *)xmlSaveUri(conn->uri);
name = virURIFormat(conn->uri);
if (!name) {
virReportOOMError();
goto error;
@ -4952,7 +4952,7 @@ virDomainMigratePeer2Peer (virDomainPtr domain,
const char *uri,
unsigned long bandwidth)
{
xmlURIPtr tempuri = NULL;
virURIPtr tempuri = NULL;
VIR_DOMAIN_DEBUG(domain, "xmlin=%s, flags=%lx, dname=%s, "
"dconnuri=%s, uri=%s, bandwidth=%lu",
NULLSTR(xmlin), flags, NULLSTR(dname),
@ -4964,7 +4964,7 @@ virDomainMigratePeer2Peer (virDomainPtr domain,
return -1;
}
tempuri = xmlParseURI(dconnuri);
tempuri = virURIParse(dconnuri);
if (!tempuri) {
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
virDispatchError(domain->conn);

View File

@ -1431,6 +1431,11 @@ virTypedParameterArrayValidate;
virTypedParameterAssign;
# viruri.h
virURIFormat;
virURIParse;
# xml.h
virXMLChildElementCount;
virXMLParseHelper;

View File

@ -44,6 +44,7 @@
#include "libxl_conf.h"
#include "xen_xm.h"
#include "virtypedparam.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_LIBXL
@ -1043,7 +1044,7 @@ libxlOpen(virConnectPtr conn,
if (libxl_driver == NULL)
return VIR_DRV_OPEN_DECLINED;
conn->uri = xmlParseURI("xen:///");
conn->uri = virURIParse("xen:///");
if (!conn->uri) {
virReportOOMError();
return VIR_DRV_OPEN_ERROR;

View File

@ -60,6 +60,7 @@
#include "virnodesuspend.h"
#include "virtime.h"
#include "virtypedparam.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_LXC
@ -139,7 +140,7 @@ static virDrvOpenStatus lxcOpen(virConnectPtr conn,
if (lxc_driver == NULL)
return VIR_DRV_OPEN_DECLINED;
conn->uri = xmlParseURI("lxc:///");
conn->uri = virURIParse("lxc:///");
if (!conn->uri) {
virReportOOMError();
return VIR_DRV_OPEN_ERROR;

View File

@ -56,6 +56,7 @@
#include "virfile.h"
#include "logging.h"
#include "command.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_OPENVZ
@ -1335,7 +1336,7 @@ static virDrvOpenStatus openvzOpen(virConnectPtr conn,
if (access("/proc/vz", W_OK) < 0)
return VIR_DRV_OPEN_DECLINED;
conn->uri = xmlParseURI("openvz:///system");
conn->uri = virURIParse("openvz:///system");
if (conn->uri == NULL) {
virReportOOMError();
return VIR_DRV_OPEN_ERROR;

View File

@ -857,7 +857,7 @@ static virDrvOpenStatus qemudOpen(virConnectPtr conn,
if (qemu_driver == NULL)
return VIR_DRV_OPEN_DECLINED;
conn->uri = xmlParseURI(qemu_driver->privileged ?
conn->uri = virURIParse(qemu_driver->privileged ?
"qemu:///system" :
"qemu:///session");
if (!conn->uri) {

View File

@ -1,7 +1,7 @@
/*
* qemu_migration.c: QEMU migration handling
*
* Copyright (C) 2006-2011 Red Hat, Inc.
* Copyright (C) 2006-2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -46,6 +46,7 @@
#include "locking/domain_lock.h"
#include "rpc/virnetsocket.h"
#include "storage_file.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@ -1792,7 +1793,7 @@ static int doNativeMigrate(struct qemud_driver *driver,
virConnectPtr dconn)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
xmlURIPtr uribits = NULL;
virURIPtr uribits = NULL;
int ret = -1;
qemuMigrationSpec spec;
@ -1808,10 +1809,10 @@ static int doNativeMigrate(struct qemud_driver *driver,
virReportOOMError();
return -1;
}
uribits = xmlParseURI(tmp);
uribits = virURIParse(tmp);
VIR_FREE(tmp);
} else {
uribits = xmlParseURI(uri);
uribits = virURIParse(uri);
}
if (!uribits) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,

View File

@ -26,8 +26,6 @@
#include <unistd.h>
#include <assert.h>
#include <libxml/uri.h>
#include "virnetclient.h"
#include "virnetclientprogram.h"
#include "virnetclientstream.h"
@ -47,6 +45,7 @@
#include "command.h"
#include "intprops.h"
#include "virtypedparam.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_REMOTE
@ -488,7 +487,7 @@ doRemoteOpen (virConnectPtr conn,
/* Allow remote serve to probe */
name = strdup("");
} else {
xmlURI tmpuri = {
virURI tmpuri = {
.scheme = conn->uri->scheme,
#ifdef HAVE_XMLURI_QUERY_RAW
.query_raw = qparam_get_query (vars),
@ -505,7 +504,7 @@ doRemoteOpen (virConnectPtr conn,
transport_str[-1] = '\0';
}
name = (char *) xmlSaveUri (&tmpuri);
name = virURIFormat(&tmpuri);
#ifdef HAVE_XMLURI_QUERY_RAW
VIR_FREE(tmpuri.query_raw);
@ -719,7 +718,7 @@ doRemoteOpen (virConnectPtr conn,
goto failed;
VIR_DEBUG("Auto-probed URI is %s", uriret.uri);
conn->uri = xmlParseURI(uriret.uri);
conn->uri = virURIParse(uriret.uri);
VIR_FREE(uriret.uri);
if (!conn->uri) {
virReportOOMError();

View File

@ -63,6 +63,7 @@
#include "configmake.h"
#include "virnetdevtap.h"
#include "virnodesuspend.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_UML
@ -1138,7 +1139,7 @@ static virDrvOpenStatus umlOpen(virConnectPtr conn,
if (uml_driver == NULL)
return VIR_DRV_OPEN_DECLINED;
conn->uri = xmlParseURI(uml_driver->privileged ?
conn->uri = virURIParse(uml_driver->privileged ?
"uml:///system" :
"uml:///session");
if (!conn->uri) {

View File

@ -26,12 +26,11 @@
#include <stdlib.h>
#include <stdarg.h>
#include <libxml/uri.h>
#include "virterror_internal.h"
#include "buf.h"
#include "memory.h"
#include "qparams.h"
#include "viruri.h"
#define VIR_FROM_THIS VIR_FROM_NONE

93
src/util/viruri.c Normal file
View File

@ -0,0 +1,93 @@
/*
* viruri.c: URI parsing wrappers for libxml2 functions
*
* Copyright (C) 2012 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*/
#include <config.h>
#include "viruri.h"
#include "memory.h"
#include "util.h"
/**
* virURIParse:
* @uri: URI to parse
*
* Wrapper for xmlParseURI
*
* Unfortunately there are few things that should be managed after
* parsing the URI. Fortunately there is only one thing now and its
* removing of square brackets around IPv6 addresses.
*
* @returns the parsed uri object with some fixes
*/
virURIPtr
virURIParse(const char *uri)
{
virURIPtr ret = xmlParseURI(uri);
/* First check: does it even make sense to jump inside */
if (ret != NULL &&
ret->server != NULL &&
ret->server[0] == '[') {
size_t length = strlen(ret->server);
/* We want to modify the server string only if there are
* square brackets on both ends and inside there is IPv6
* address. Otherwise we could make a mistake by modifying
* something other than an IPv6 address. */
if (ret->server[length - 1] == ']' && strchr(ret->server, ':')) {
memmove(&ret->server[0], &ret->server[1], length - 2);
ret->server[length - 2] = '\0';
}
/* Even after such modification, it is completely ok to free
* the uri with xmlFreeURI() */
}
return ret;
}
/**
* virURIFormat:
* @uri: URI to format
*
* Wrapper for xmlSaveUri
*
* This function constructs back everything that @ref virURIParse
* changes after parsing
*
* @returns the constructed uri as a string
*/
char *
virURIFormat(xmlURIPtr uri)
{
char *backupserver = NULL;
char *tmpserver = NULL;
char *ret;
/* First check: does it make sense to do anything */
if (uri != NULL &&
uri->server != NULL &&
strchr(uri->server, ':') != NULL) {
backupserver = uri->server;
if (virAsprintf(&tmpserver, "[%s]", uri->server) < 0)
return NULL;
uri->server = tmpserver;
}
ret = (char *) xmlSaveUri(uri);
/* Put the fixed version back */
if (tmpserver) {
uri->server = backupserver;
VIR_FREE(tmpserver);
}
return ret;
}

22
src/util/viruri.h Normal file
View File

@ -0,0 +1,22 @@
/*
* viruri.h: internal definitions used for URI parsing.
*
* Copyright (C) 2012 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*/
#ifndef __VIR_URI_H__
# define __VIR_URI_H__
# include <libxml/uri.h>
# include "internal.h"
typedef xmlURI virURI;
typedef xmlURIPtr virURIPtr;
virURIPtr virURIParse(const char *uri);
char *virURIFormat(virURIPtr uri);
#endif /* __VIR_URI_H__ */

View File

@ -56,6 +56,7 @@
#include "configmake.h"
#include "virfile.h"
#include "fdstream.h"
#include "viruri.h"
/* This one changes from version to version. */
#if VBOX_API_VERSION == 2002
@ -980,7 +981,7 @@ static virDrvOpenStatus vboxOpen(virConnectPtr conn,
virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
if (conn->uri == NULL) {
conn->uri = xmlParseURI(uid ? "vbox:///session" : "vbox:///system");
conn->uri = virURIParse(uid ? "vbox:///session" : "vbox:///system");
if (conn->uri == NULL) {
virReportOOMError();
return VIR_DRV_OPEN_ERROR;

View File

@ -24,7 +24,6 @@
#include <config.h>
#include <c-ctype.h>
#include <libxml/uri.h>
#include "internal.h"
#include "virterror_internal.h"
@ -33,6 +32,7 @@
#include "logging.h"
#include "uuid.h"
#include "vmx.h"
#include "viruri.h"
/*
@ -2525,7 +2525,7 @@ virVMXParseSerial(virVMXContext *ctx, virConfPtr conf, int port,
char network_endPoint_name[48] = "";
char *network_endPoint = NULL;
xmlURIPtr parsedUri = NULL;
virURIPtr parsedUri = NULL;
if (def == NULL || *def != NULL) {
VMX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
@ -2615,7 +2615,7 @@ virVMXParseSerial(virVMXContext *ctx, virConfPtr conf, int port,
(*def)->target.port = port;
(*def)->source.type = VIR_DOMAIN_CHR_TYPE_TCP;
parsedUri = xmlParseURI(fileName);
parsedUri = virURIParse(fileName);
if (parsedUri == NULL) {
virReportOOMError();

View File

@ -26,7 +26,6 @@
#include <sys/types.h>
#include <fcntl.h>
#include <xen/dom0_ops.h>
#include <libxml/uri.h>
#include "virterror_internal.h"
#include "logging.h"
@ -50,6 +49,7 @@
#include "uuid.h"
#include "fdstream.h"
#include "virfile.h"
#include "viruri.h"
#include "command.h"
#include "virnodesuspend.h"
@ -270,7 +270,7 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
if (!xenUnifiedProbe())
return VIR_DRV_OPEN_DECLINED;
conn->uri = xmlParseURI("xen:///");
conn->uri = virURIParse("xen:///");
if (!conn->uri) {
virReportOOMError();
return VIR_DRV_OPEN_ERROR;

View File

@ -11,11 +11,10 @@
#ifndef __VIR_XEN_INTERNAL_H__
# define __VIR_XEN_INTERNAL_H__
# include <libxml/uri.h>
# include "internal.h"
# include "capabilities.h"
# include "driver.h"
# include "viruri.h"
/* See xenHypervisorInit() for details. */
struct xenHypervisorVersions {

View File

@ -27,7 +27,6 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <libxml/uri.h>
#include <errno.h>
#include "virterror_internal.h"
@ -46,6 +45,7 @@
#include "memory.h"
#include "count-one-bits.h"
#include "virfile.h"
#include "viruri.h"
/* required for cpumap_t */
#include <xen/dom0_ops.h>
@ -3224,7 +3224,7 @@ xenDaemonDomainMigratePerform (virDomainPtr domain,
* "hostname", "hostname:port" or "xenmigr://hostname[:port]/".
*/
if (strstr (uri, "//")) { /* Full URI. */
xmlURIPtr uriptr = xmlParseURI (uri);
virURIPtr uriptr = virURIParse (uri);
if (!uriptr) {
virXendError(VIR_ERR_INVALID_ARG,
"%s", _("xenDaemonDomainMigrate: invalid URI"));

View File

@ -18,13 +18,13 @@
# include <sys/types.h>
# include <stdint.h>
# include <libxml/uri.h>
# include "internal.h"
# include "capabilities.h"
# include "domain_conf.h"
# include "driver.h"
# include "buf.h"
# include "viruri.h"
int
xenDaemonOpen_unix(virConnectPtr conn, const char *path);

View File

@ -25,7 +25,6 @@
#include <limits.h>
#include <stdint.h>
#include <string.h>
#include <libxml/uri.h>
#include <curl/curl.h>
#include <xen/api/xen_all.h>
#include "internal.h"
@ -37,6 +36,7 @@
#include "uuid.h"
#include "memory.h"
#include "buf.h"
#include "viruri.h"
#include "xenapi_driver.h"
#include "xenapi_driver_private.h"
#include "xenapi_utils.h"

View File

@ -25,7 +25,6 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <libxml/uri.h>
#include <xen/api/xen_all.h>
#include "internal.h"
#include "domain_conf.h"
@ -37,6 +36,7 @@
#include "buf.h"
#include "logging.h"
#include "qparams.h"
#include "viruri.h"
#include "xenapi_driver_private.h"
#include "xenapi_utils.h"
@ -94,7 +94,7 @@ xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
}
int
xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify)
xenapiUtil_ParseQuery(virConnectPtr conn, virURIPtr uri, int *noVerify)
{
int result = 0;
int i;

View File

@ -23,9 +23,9 @@
# define __VIR_XENAPI_UTILS__
# include <stdint.h>
# include <libxml/uri.h>
# include <xen/api/xen_all.h>
# include "internal.h"
# include "viruri.h"
# include "domain_conf.h"
# define NETWORK_DEVID_SIZE (12)
@ -40,7 +40,7 @@ xenapiUtil_RequestPassword(virConnectAuthPtr auth, const char *username,
const char *hostname);
int
xenapiUtil_ParseQuery(virConnectPtr conn, xmlURIPtr uri, int *noVerify);
xenapiUtil_ParseQuery(virConnectPtr conn, virURIPtr uri, int *noVerify);
enum xen_on_normal_exit
actionShutdownLibvirt2XenapiEnum(enum virDomainLifecycleAction action);