sharing: URL-encode-aware backmap of REPORT/PROPPATCH hrefs
make_href percent-encodes hrefs (an '@' in an email principal becomes %40), but the backmap compared against the raw PathMapped, so the rewrite was skipped and the owner's real path leaked -- editing a shared collection then failed with 403. Compare and rewrite on the quoted form.
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
## 3.7.6.dev
|
## 3.7.6.dev
|
||||||
* Extension: item verification on commandline
|
* Extension: item verification on commandline
|
||||||
* Improvement: catch lack of support of PERIOD in vobject <= 0.9.9
|
* Improvement: catch lack of support of PERIOD in vobject <= 0.9.9
|
||||||
|
* Fix: sharing: backmap of REPORT/PROPPATCH hrefs is now URL-encode-aware (edit of a shared collection failed when the principal contains '@')
|
||||||
|
|
||||||
## 3.7.5
|
## 3.7.5
|
||||||
* Add: [sharing] conversion_bday_summary_template (customize summary)
|
* Add: [sharing] conversion_bday_summary_template (customize summary)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import socket
|
|||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from http import client
|
from http import client
|
||||||
from typing import Dict, Optional, Union, cast
|
from typing import Dict, Optional, Union, cast
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
import defusedxml.ElementTree as DefusedET
|
import defusedxml.ElementTree as DefusedET
|
||||||
|
|
||||||
@@ -49,8 +50,8 @@ def xml_proppatch(base_prefix: str, path: str,
|
|||||||
href = ET.Element(xmlutils.make_clark("D:href"))
|
href = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
href.text = xmlutils.make_href(base_prefix, path)
|
href.text = xmlutils.make_href(base_prefix, path)
|
||||||
if share:
|
if share:
|
||||||
# backmap
|
# backmap; quote so the encoded href and raw share path compare
|
||||||
href.text = href.text.replace(share['PathMapped'], share['PathOrToken'])
|
href.text = href.text.replace(quote(share['PathMapped']), quote(str(share['PathOrToken'])))
|
||||||
response.append(href)
|
response.append(href)
|
||||||
# Create D:propstat element for props with status 200 OK
|
# Create D:propstat element for props with status 200 OK
|
||||||
propstat = ET.Element(xmlutils.make_clark("D:propstat"))
|
propstat = ET.Element(xmlutils.make_clark("D:propstat"))
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import xml.etree.ElementTree as ET
|
|||||||
from http import client
|
from http import client
|
||||||
from typing import (Callable, Iterable, Iterator, List, Optional, Sequence,
|
from typing import (Callable, Iterable, Iterator, List, Optional, Sequence,
|
||||||
Tuple, Union)
|
Tuple, Union)
|
||||||
from urllib.parse import unquote, urlparse
|
from urllib.parse import quote, unquote, urlparse
|
||||||
|
|
||||||
import vobject
|
import vobject
|
||||||
import vobject.base
|
import vobject.base
|
||||||
@@ -741,9 +741,11 @@ def xml_item_response(base_prefix: str, href: str,
|
|||||||
href_element.text = xmlutils.make_href(base_prefix, href)
|
href_element.text = xmlutils.make_href(base_prefix, href)
|
||||||
logger.trace("REPORT/xml_report: href=%r base_prefix=%r", href_element.text, base_prefix)
|
logger.trace("REPORT/xml_report: href=%r base_prefix=%r", href_element.text, base_prefix)
|
||||||
if share:
|
if share:
|
||||||
# backmap
|
# backmap; quote so the encoded href and raw share path compare
|
||||||
if href_element.text.startswith(base_prefix + share['PathMapped']):
|
mapped = quote(share['PathMapped'])
|
||||||
href_element.text = base_prefix + str(share['PathOrToken']) + href_element.text.removeprefix(base_prefix + share['PathMapped'])
|
token = quote(str(share['PathOrToken']))
|
||||||
|
if href_element.text.startswith(base_prefix + mapped):
|
||||||
|
href_element.text = base_prefix + token + href_element.text.removeprefix(base_prefix + mapped)
|
||||||
if share_bday_automap and href_element.text.endswith(".vcf"):
|
if share_bday_automap and href_element.text.endswith(".vcf"):
|
||||||
href_element.text = href_element.text.removesuffix(".vcf") + ".ics"
|
href_element.text = href_element.text.removesuffix(".vcf") + ".ics"
|
||||||
logger.trace("REPORT/xml_report: href=%r (backmapped)", href_element.text)
|
logger.trace("REPORT/xml_report: href=%r (backmapped)", href_element.text)
|
||||||
|
|||||||
Reference in New Issue
Block a user