mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-02 04:15:46 +00:00
conf: Add support for cookies for HTTP based disks
Add possibility to specify one or more cookies for http based disks. This patch adds the config parser, storage and validation of the cookies. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
25481e25b1
commit
3b076391be
@ -2849,6 +2849,9 @@
|
|||||||
<driver name='qemu' type='raw'/>
|
<driver name='qemu' type='raw'/>
|
||||||
<source protocol="http" name="url_path">
|
<source protocol="http" name="url_path">
|
||||||
<host name="hostname" port="80"/>
|
<host name="hostname" port="80"/>
|
||||||
|
<cookies>
|
||||||
|
<cookie name="test">somevalue</cookie>
|
||||||
|
</cookies>
|
||||||
</source>
|
</source>
|
||||||
<target dev='hde' bus='ide' tray='open'/>
|
<target dev='hde' bus='ide' tray='open'/>
|
||||||
<readonly/>
|
<readonly/>
|
||||||
@ -3392,6 +3395,13 @@
|
|||||||
certificate validation. Supported values are <code>yes</code> and
|
certificate validation. Supported values are <code>yes</code> and
|
||||||
<code>no</code>. <span class="since">Since 6.2.0</span>
|
<code>no</code>. <span class="since">Since 6.2.0</span>
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><code>cookies</code></dt>
|
||||||
|
<dd>
|
||||||
|
For <code>http</code> and <code>https</code> accessed storage it's
|
||||||
|
possible to pass one or more cookies. The cookie name and value
|
||||||
|
must conform to the HTTP specification.
|
||||||
|
<span class="since">Since 6.2.0</span>
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -1817,6 +1817,24 @@
|
|||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<define name="diskSourceNetworkProtocolHTTPCookies">
|
||||||
|
<element name="cookies">
|
||||||
|
<oneOrMore>
|
||||||
|
<element name="cookie">
|
||||||
|
<attribute name="name">
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">[!#$%&'*+\-.0-9A-Z\^_`a-z|~]+</param>
|
||||||
|
</data>
|
||||||
|
</attribute>
|
||||||
|
<data type="string">
|
||||||
|
<param name="pattern">[!#$%&'()*+\-./0-9:>=<?@A-Z\^_`\[\]a-z|~]+</param>
|
||||||
|
</data>
|
||||||
|
</element>
|
||||||
|
</oneOrMore>
|
||||||
|
<empty/>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
<define name="diskSourceNetworkProtocolHTTPS">
|
<define name="diskSourceNetworkProtocolHTTPS">
|
||||||
<element name="source">
|
<element name="source">
|
||||||
<attribute name="protocol">
|
<attribute name="protocol">
|
||||||
@ -1833,6 +1851,9 @@
|
|||||||
<optional>
|
<optional>
|
||||||
<ref name="diskSourceNetworkProtocolSSLVerify"/>
|
<ref name="diskSourceNetworkProtocolSSLVerify"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="diskSourceNetworkProtocolHTTPCookies"/>
|
||||||
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
@ -1849,6 +1870,9 @@
|
|||||||
<optional>
|
<optional>
|
||||||
<ref name="encryption"/>
|
<ref name="encryption"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="diskSourceNetworkProtocolHTTPCookies"/>
|
||||||
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
@ -9340,6 +9340,62 @@ virDomainDiskSourcePoolDefParse(xmlNodePtr node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virStorageNetCookieDefPtr
|
||||||
|
virDomainStorageNetCookieParse(xmlNodePtr node,
|
||||||
|
xmlXPathContextPtr ctxt)
|
||||||
|
{
|
||||||
|
VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
||||||
|
g_autoptr(virStorageNetCookieDef) cookie = NULL;
|
||||||
|
|
||||||
|
ctxt->node = node;
|
||||||
|
|
||||||
|
cookie = g_new0(virStorageNetCookieDef, 1);
|
||||||
|
|
||||||
|
if (!(cookie->name = virXPathString("string(./@name)", ctxt))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s", _("missing cookie name"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(cookie->value = virXPathString("string(.)", ctxt))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, _("missing value for cookie '%s'"),
|
||||||
|
cookie->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_steal_pointer(&cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainStorageNetCookiesParse(xmlNodePtr node,
|
||||||
|
xmlXPathContextPtr ctxt,
|
||||||
|
virStorageSourcePtr src)
|
||||||
|
{
|
||||||
|
VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
||||||
|
g_autofree xmlNodePtr *nodes = NULL;
|
||||||
|
ssize_t nnodes;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
ctxt->node = node;
|
||||||
|
|
||||||
|
if ((nnodes = virXPathNodeSet("./cookie", ctxt, &nodes)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
src->cookies = g_new0(virStorageNetCookieDefPtr, nnodes);
|
||||||
|
src->ncookies = nnodes;
|
||||||
|
|
||||||
|
for (i = 0; i < nnodes; i++) {
|
||||||
|
if (!(src->cookies[i] = virDomainStorageNetCookieParse(nodes[i], ctxt)))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virStorageSourceNetCookiesValidate(src) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainDiskSourceNetworkParse(xmlNodePtr node,
|
virDomainDiskSourceNetworkParse(xmlNodePtr node,
|
||||||
xmlXPathContextPtr ctxt,
|
xmlXPathContextPtr ctxt,
|
||||||
@ -9351,6 +9407,7 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
|
|||||||
g_autofree char *haveTLS = NULL;
|
g_autofree char *haveTLS = NULL;
|
||||||
g_autofree char *tlsCfg = NULL;
|
g_autofree char *tlsCfg = NULL;
|
||||||
g_autofree char *sslverifystr = NULL;
|
g_autofree char *sslverifystr = NULL;
|
||||||
|
xmlNodePtr tmpnode;
|
||||||
|
|
||||||
if (!(protocol = virXMLPropString(node, "protocol"))) {
|
if (!(protocol = virXMLPropString(node, "protocol"))) {
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
@ -9436,6 +9493,13 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
|
|||||||
src->sslverify = verify;
|
src->sslverify = verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
|
||||||
|
src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS) &&
|
||||||
|
(tmpnode = virXPathNode("./cookies", ctxt))) {
|
||||||
|
if (virDomainStorageNetCookiesParse(tmpnode, ctxt, src) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24500,6 +24564,22 @@ virDomainSourceDefFormatSeclabel(virBufferPtr buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainDiskSourceFormatNetworkCookies(virBufferPtr buf,
|
||||||
|
virStorageSourcePtr src)
|
||||||
|
{
|
||||||
|
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < src->ncookies; i++) {
|
||||||
|
virBufferEscapeString(&childBuf, "<cookie name='%s'>", src->cookies[i]->name);
|
||||||
|
virBufferEscapeString(&childBuf, "%s</cookie>\n", src->cookies[i]->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
virXMLFormatElement(buf, "cookies", NULL, &childBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainDiskSourceFormatNetwork(virBufferPtr attrBuf,
|
virDomainDiskSourceFormatNetwork(virBufferPtr attrBuf,
|
||||||
virBufferPtr childBuf,
|
virBufferPtr childBuf,
|
||||||
@ -24550,6 +24630,8 @@ virDomainDiskSourceFormatNetwork(virBufferPtr attrBuf,
|
|||||||
virTristateBoolTypeToString(src->sslverify));
|
virTristateBoolTypeToString(src->sslverify));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virDomainDiskSourceFormatNetworkCookies(childBuf, src);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3147,6 +3147,7 @@ virStorageSourceIsEmpty;
|
|||||||
virStorageSourceIsLocalStorage;
|
virStorageSourceIsLocalStorage;
|
||||||
virStorageSourceIsRelative;
|
virStorageSourceIsRelative;
|
||||||
virStorageSourceIsSameLocation;
|
virStorageSourceIsSameLocation;
|
||||||
|
virStorageSourceNetCookiesValidate;
|
||||||
virStorageSourceNetworkAssignDefaultPorts;
|
virStorageSourceNetworkAssignDefaultPorts;
|
||||||
virStorageSourceNew;
|
virStorageSourceNew;
|
||||||
virStorageSourceNewFromBacking;
|
virStorageSourceNewFromBacking;
|
||||||
|
@ -2157,6 +2157,118 @@ virStorageSourceSeclabelsCopy(virStorageSourcePtr to,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
virStorageNetCookieDefFree(virStorageNetCookieDefPtr def)
|
||||||
|
{
|
||||||
|
if (!def)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_free(def->name);
|
||||||
|
g_free(def->value);
|
||||||
|
|
||||||
|
g_free(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virStorageSourceNetCookiesClear(virStorageSourcePtr src)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!src || !src->cookies)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < src->ncookies; i++)
|
||||||
|
virStorageNetCookieDefFree(src->cookies[i]);
|
||||||
|
|
||||||
|
g_clear_pointer(&src->cookies, g_free);
|
||||||
|
src->ncookies = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virStorageSourceNetCookiesCopy(virStorageSourcePtr to,
|
||||||
|
const virStorageSource *from)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (from->ncookies == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
to->cookies = g_new0(virStorageNetCookieDefPtr, from->ncookies);
|
||||||
|
to->ncookies = from->ncookies;
|
||||||
|
|
||||||
|
for (i = 0; i < from->ncookies; i++) {
|
||||||
|
to->cookies[i]->name = g_strdup(from->cookies[i]->name);
|
||||||
|
to->cookies[i]->value = g_strdup(from->cookies[i]->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* see https://tools.ietf.org/html/rfc6265#section-4.1.1 */
|
||||||
|
static const char virStorageSourceCookieValueInvalidChars[] =
|
||||||
|
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
|
||||||
|
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
|
||||||
|
" \",;\\";
|
||||||
|
|
||||||
|
/* in addition cookie name can't contain these */
|
||||||
|
static const char virStorageSourceCookieNameInvalidChars[] =
|
||||||
|
"()<>@:/[]?={}";
|
||||||
|
|
||||||
|
static int
|
||||||
|
virStorageSourceNetCookieValidate(virStorageNetCookieDefPtr def)
|
||||||
|
{
|
||||||
|
/* name must have at least 1 character */
|
||||||
|
if (*(def->name) == '\0') {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("cookie name must not be empty"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check invalid characters in name */
|
||||||
|
if (virStringHasChars(def->name, virStorageSourceCookieValueInvalidChars) ||
|
||||||
|
virStringHasChars(def->name, virStorageSourceCookieNameInvalidChars)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("cookie name '%s' contains invalid characters"),
|
||||||
|
def->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check invalid characters in value */
|
||||||
|
if (virStringHasChars(def->value, virStorageSourceCookieValueInvalidChars)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("value of cookie '%s' contains invalid characters"),
|
||||||
|
def->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
virStorageSourceNetCookiesValidate(virStorageSourcePtr src)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
for (i = 0; i < src->ncookies; i++) {
|
||||||
|
if (virStorageSourceNetCookieValidate(src->cookies[i]) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (j = i + 1; j < src->ncookies; j++) {
|
||||||
|
if (STREQ(src->cookies[i]->name, src->cookies[j]->name)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, _("duplicate cookie '%s'"),
|
||||||
|
src->cookies[i]->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virStorageTimestampsPtr
|
static virStorageTimestampsPtr
|
||||||
virStorageTimestampsCopy(const virStorageTimestamps *src)
|
virStorageTimestampsCopy(const virStorageTimestamps *src)
|
||||||
{
|
{
|
||||||
@ -2299,6 +2411,8 @@ virStorageSourceCopy(const virStorageSource *src,
|
|||||||
def->nhosts = src->nhosts;
|
def->nhosts = src->nhosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virStorageSourceNetCookiesCopy(def, src);
|
||||||
|
|
||||||
if (src->srcpool &&
|
if (src->srcpool &&
|
||||||
!(def->srcpool = virStorageSourcePoolDefCopy(src->srcpool)))
|
!(def->srcpool = virStorageSourcePoolDefCopy(src->srcpool)))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2560,6 +2674,7 @@ virStorageSourceClear(virStorageSourcePtr def)
|
|||||||
VIR_FREE(def->volume);
|
VIR_FREE(def->volume);
|
||||||
VIR_FREE(def->snapshot);
|
VIR_FREE(def->snapshot);
|
||||||
VIR_FREE(def->configFile);
|
VIR_FREE(def->configFile);
|
||||||
|
virStorageSourceNetCookiesClear(def);
|
||||||
virStorageSourcePoolDefFree(def->srcpool);
|
virStorageSourcePoolDefFree(def->srcpool);
|
||||||
virBitmapFree(def->features);
|
virBitmapFree(def->features);
|
||||||
VIR_FREE(def->compat);
|
VIR_FREE(def->compat);
|
||||||
|
@ -161,6 +161,17 @@ struct _virStorageNetHostDef {
|
|||||||
char *socket; /* path to unix socket */
|
char *socket; /* path to unix socket */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virStorageNetCookieDef virStorageNetCookieDef;
|
||||||
|
typedef virStorageNetCookieDef *virStorageNetCookieDefPtr;
|
||||||
|
struct _virStorageNetCookieDef {
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
void virStorageNetCookieDefFree(virStorageNetCookieDefPtr def);
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageNetCookieDef, virStorageNetCookieDefFree);
|
||||||
|
|
||||||
/* Information for a storage volume from a virStoragePool */
|
/* Information for a storage volume from a virStoragePool */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -275,6 +286,8 @@ struct _virStorageSource {
|
|||||||
the source definition */
|
the source definition */
|
||||||
size_t nhosts;
|
size_t nhosts;
|
||||||
virStorageNetHostDefPtr hosts;
|
virStorageNetHostDefPtr hosts;
|
||||||
|
size_t ncookies;
|
||||||
|
virStorageNetCookieDefPtr *cookies;
|
||||||
virStorageSourcePoolDefPtr srcpool;
|
virStorageSourcePoolDefPtr srcpool;
|
||||||
virStorageAuthDefPtr auth;
|
virStorageAuthDefPtr auth;
|
||||||
bool authInherited;
|
bool authInherited;
|
||||||
@ -476,6 +489,8 @@ int virStorageSourceUpdateCapacity(virStorageSourcePtr src,
|
|||||||
int virStorageSourceNewFromBacking(virStorageSourcePtr parent,
|
int virStorageSourceNewFromBacking(virStorageSourcePtr parent,
|
||||||
virStorageSourcePtr *backing);
|
virStorageSourcePtr *backing);
|
||||||
|
|
||||||
|
int virStorageSourceNetCookiesValidate(virStorageSourcePtr src);
|
||||||
|
|
||||||
virStorageSourcePtr virStorageSourceCopy(const virStorageSource *src,
|
virStorageSourcePtr virStorageSourceCopy(const virStorageSource *src,
|
||||||
bool backingChain)
|
bool backingChain)
|
||||||
ATTRIBUTE_NONNULL(1);
|
ATTRIBUTE_NONNULL(1);
|
||||||
|
@ -33,6 +33,10 @@
|
|||||||
<driver name='qemu' type='raw'/>
|
<driver name='qemu' type='raw'/>
|
||||||
<source protocol='http' name='test3.img'>
|
<source protocol='http' name='test3.img'>
|
||||||
<host name='example.org' port='1234'/>
|
<host name='example.org' port='1234'/>
|
||||||
|
<cookies>
|
||||||
|
<cookie name='test'>testcookievalue</cookie>
|
||||||
|
<cookie name='test2'>blurb</cookie>
|
||||||
|
</cookies>
|
||||||
</source>
|
</source>
|
||||||
<target dev='vdc' bus='virtio'/>
|
<target dev='vdc' bus='virtio'/>
|
||||||
</disk>
|
</disk>
|
||||||
@ -41,6 +45,10 @@
|
|||||||
<source protocol='https' name='test4.img'>
|
<source protocol='https' name='test4.img'>
|
||||||
<host name='example.org' port='1234'/>
|
<host name='example.org' port='1234'/>
|
||||||
<ssl verify='yes'/>
|
<ssl verify='yes'/>
|
||||||
|
<cookies>
|
||||||
|
<cookie name='test'>testcookievalue</cookie>
|
||||||
|
<cookie name='test2'>blurb</cookie>
|
||||||
|
</cookies>
|
||||||
</source>
|
</source>
|
||||||
<target dev='vdd' bus='virtio'/>
|
<target dev='vdd' bus='virtio'/>
|
||||||
</disk>
|
</disk>
|
||||||
|
Loading…
Reference in New Issue
Block a user