提交 3b076391 编写于 作者: P Peter Krempa

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: NPeter Krempa <pkrempa@redhat.com>
Reviewed-by: NJán Tomko <jtomko@redhat.com>
上级 25481e25
......@@ -2849,6 +2849,9 @@
&lt;driver name='qemu' type='raw'/&gt;
&lt;source protocol="http" name="url_path"&gt;
&lt;host name="hostname" port="80"/&gt;
&lt;cookies&gt;
&lt;cookie name="test"&gt;somevalue&lt;/cookie&gt;
&lt;/cookies&gt;
&lt;/source&gt;
&lt;target dev='hde' bus='ide' tray='open'/&gt;
&lt;readonly/&gt;
......@@ -3392,6 +3395,13 @@
certificate validation. Supported values are <code>yes</code> and
<code>no</code>. <span class="since">Since 6.2.0</span>
</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>
<p>
......
......@@ -1817,6 +1817,24 @@
</element>
</define>
<define name="diskSourceNetworkProtocolHTTPCookies">
<element name="cookies">
<oneOrMore>
<element name="cookie">
<attribute name="name">
<data type="string">
<param name="pattern">[!#$%&amp;'*+\-.0-9A-Z\^_`a-z|~]+</param>
</data>
</attribute>
<data type="string">
<param name="pattern">[!#$%&amp;'()*+\-./0-9:&gt;=&lt;?@A-Z\^_`\[\]a-z|~]+</param>
</data>
</element>
</oneOrMore>
<empty/>
</element>
</define>
<define name="diskSourceNetworkProtocolHTTPS">
<element name="source">
<attribute name="protocol">
......@@ -1833,6 +1851,9 @@
<optional>
<ref name="diskSourceNetworkProtocolSSLVerify"/>
</optional>
<optional>
<ref name="diskSourceNetworkProtocolHTTPCookies"/>
</optional>
</element>
</define>
......@@ -1849,6 +1870,9 @@
<optional>
<ref name="encryption"/>
</optional>
<optional>
<ref name="diskSourceNetworkProtocolHTTPCookies"/>
</optional>
</element>
</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
virDomainDiskSourceNetworkParse(xmlNodePtr node,
xmlXPathContextPtr ctxt,
......@@ -9351,6 +9407,7 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
g_autofree char *haveTLS = NULL;
g_autofree char *tlsCfg = NULL;
g_autofree char *sslverifystr = NULL;
xmlNodePtr tmpnode;
if (!(protocol = virXMLPropString(node, "protocol"))) {
virReportError(VIR_ERR_XML_ERROR, "%s",
......@@ -9436,6 +9493,13 @@ virDomainDiskSourceNetworkParse(xmlNodePtr node,
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;
}
......@@ -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
virDomainDiskSourceFormatNetwork(virBufferPtr attrBuf,
virBufferPtr childBuf,
......@@ -24550,6 +24630,8 @@ virDomainDiskSourceFormatNetwork(virBufferPtr attrBuf,
virTristateBoolTypeToString(src->sslverify));
}
virDomainDiskSourceFormatNetworkCookies(childBuf, src);
return 0;
}
......
......@@ -3147,6 +3147,7 @@ virStorageSourceIsEmpty;
virStorageSourceIsLocalStorage;
virStorageSourceIsRelative;
virStorageSourceIsSameLocation;
virStorageSourceNetCookiesValidate;
virStorageSourceNetworkAssignDefaultPorts;
virStorageSourceNew;
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
virStorageTimestampsCopy(const virStorageTimestamps *src)
{
......@@ -2299,6 +2411,8 @@ virStorageSourceCopy(const virStorageSource *src,
def->nhosts = src->nhosts;
}
virStorageSourceNetCookiesCopy(def, src);
if (src->srcpool &&
!(def->srcpool = virStorageSourcePoolDefCopy(src->srcpool)))
return NULL;
......@@ -2560,6 +2674,7 @@ virStorageSourceClear(virStorageSourcePtr def)
VIR_FREE(def->volume);
VIR_FREE(def->snapshot);
VIR_FREE(def->configFile);
virStorageSourceNetCookiesClear(def);
virStorageSourcePoolDefFree(def->srcpool);
virBitmapFree(def->features);
VIR_FREE(def->compat);
......
......@@ -161,6 +161,17 @@ struct _virStorageNetHostDef {
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 */
/*
......@@ -275,6 +286,8 @@ struct _virStorageSource {
the source definition */
size_t nhosts;
virStorageNetHostDefPtr hosts;
size_t ncookies;
virStorageNetCookieDefPtr *cookies;
virStorageSourcePoolDefPtr srcpool;
virStorageAuthDefPtr auth;
bool authInherited;
......@@ -476,6 +489,8 @@ int virStorageSourceUpdateCapacity(virStorageSourcePtr src,
int virStorageSourceNewFromBacking(virStorageSourcePtr parent,
virStorageSourcePtr *backing);
int virStorageSourceNetCookiesValidate(virStorageSourcePtr src);
virStorageSourcePtr virStorageSourceCopy(const virStorageSource *src,
bool backingChain)
ATTRIBUTE_NONNULL(1);
......
......@@ -33,6 +33,10 @@
<driver name='qemu' type='raw'/>
<source protocol='http' name='test3.img'>
<host name='example.org' port='1234'/>
<cookies>
<cookie name='test'>testcookievalue</cookie>
<cookie name='test2'>blurb</cookie>
</cookies>
</source>
<target dev='vdc' bus='virtio'/>
</disk>
......@@ -41,6 +45,10 @@
<source protocol='https' name='test4.img'>
<host name='example.org' port='1234'/>
<ssl verify='yes'/>
<cookies>
<cookie name='test'>testcookievalue</cookie>
<cookie name='test2'>blurb</cookie>
</cookies>
</source>
<target dev='vdd' bus='virtio'/>
</disk>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册