summaryrefslogtreecommitdiff
path: root/ucb
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2024-03-07 18:38:22 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2024-03-08 15:18:49 +0100
commitd7492813058bff81c17068feee0e4ba7627c17de (patch)
tree68543a3f3056223c5fef9f6eadd4eeecc3390c5b /ucb
parent218e4641c4e2e0f894afab40b0e789636e73ad4c (diff)
ucb: webdav-curl: try fallback authentication on 403 error
Sharepoint reports lack of authentication with 403 status and additional X-MSDAVEXT_ERROR header value 0x000E0098. Try to add the magic header "X-FORMS_BASED_AUTH_ACCEPTED: f" and fallback to Negotiate auth in this case; this requires cookies to be enabled. Note that the build config of libcurl on Linux is such that adding CURLAUTH_NEGOTIATE has no effect, but on WNT having both NEGOTIATE and NTLM causes the AuthMask to be ambiguous and prevents curl from trying. Change-Id: I47dada2ef08b21a43cdfa3db9eb2fcdb4043a04f Change-Id: Ia3e31c994bde0f8db84a60931702323c94c02e0e (cherry picked from commit c6df10ce7f91b3084255bfbbac95e865bbb3ce7b) Change-Id: I93e0c8f95beafc30b94296430352f2ae54e65b11 (cherry picked from commit 37abfd767874441568d9f5ac499b2d93d34e10fe) Change-Id: I0018a9904857d7521895936dc27607a54523f300 (cherry picked from commit 388a702af2fe45b2c436e64eb8639f16c1e24b76) Change-Id: Iafa8bdd183ef8a514b656ec41a9b7a6fa1e3acb9 (cherry picked from commit e84c21aca4b72d9e86c856f717b3bf1b75f190af) Change-Id: I6dfcb3ba6e44bbb76bc403e30b4a7b6ee95296f5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164551 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'ucb')
-rw-r--r--ucb/source/ucp/webdav-curl/CurlSession.cxx63
1 files changed, 50 insertions, 13 deletions
diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx
index 4096115a40aa..342ba3669699 100644
--- a/ucb/source/ucp/webdav-curl/CurlSession.cxx
+++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx
@@ -1386,6 +1386,31 @@ auto CurlProcessor::ProcessRequest(
}
break;
}
+ case SC_FORBIDDEN:
+ {
+ ::std::map<OUString, OUString> const headerMap(
+ ProcessHeaders(headers.HeaderFields.back().first));
+ // X-MSDAVEXT_Error see [MS-WEBDAVE] 2.2.3.1.9
+ auto const it(headerMap.find("x-msdavext_error"));
+ if (it == headerMap.end() || !it->second.startsWith("917656;"))
+ {
+ break;
+ }
+ // fallback needs cookie engine enabled
+ CURLcode rc
+ = curl_easy_setopt(rSession.m_pCurl.get(), CURLOPT_COOKIEFILE, "");
+ assert(rc == CURLE_OK);
+ (void)rc;
+ SAL_INFO("ucb.ucp.webdav.curl", "403 fallback authentication");
+ // disable 302 redirect
+ pRequestHeaderList.reset(curl_slist_append(
+ pRequestHeaderList.release(), "X-FORMS_BASED_AUTH_ACCEPTED: f"));
+ if (!pRequestHeaderList)
+ {
+ throw uno::RuntimeException("curl_slist_append failed");
+ }
+ }
+ [[fallthrough]]; // SP, no cookie, or cookie failed: try NTLM/Negotiate
case SC_UNAUTHORIZED:
case SC_PROXY_AUTHENTICATION_REQUIRED:
{
@@ -1393,8 +1418,9 @@ auto CurlProcessor::ProcessRequest(
? rSession.m_isAuthenticated
: rSession.m_isAuthenticatedProxy)
= false; // any auth data in m_pCurl is invalid
- auto& rnAuthRequests(statusCode == SC_UNAUTHORIZED ? nAuthRequests
- : nAuthRequestsProxy);
+ auto& rnAuthRequests(statusCode != SC_PROXY_AUTHENTICATION_REQUIRED
+ ? nAuthRequests
+ : nAuthRequestsProxy);
if (rnAuthRequests == 10)
{
SAL_INFO("ucb.ucp.webdav.curl", "aborting authentication after "
@@ -1402,22 +1428,32 @@ auto CurlProcessor::ProcessRequest(
}
else if (pEnv && pEnv->m_xAuthListener)
{
- ::std::optional<OUString> const oRealm(ExtractRealm(
- headers, statusCode == SC_UNAUTHORIZED ? "WWW-Authenticate"
- : "Proxy-Authenticate"));
+ ::std::optional<OUString> const oRealm(
+ ExtractRealm(headers, statusCode != SC_PROXY_AUTHENTICATION_REQUIRED
+ ? "WWW-Authenticate"
+ : "Proxy-Authenticate"));
::std::optional<Auth>& roAuth(
- statusCode == SC_UNAUTHORIZED ? oAuth : oAuthProxy);
+ statusCode != SC_PROXY_AUTHENTICATION_REQUIRED ? oAuth
+ : oAuthProxy);
OUString userName(roAuth ? roAuth->UserName : OUString());
OUString passWord(roAuth ? roAuth->PassWord : OUString());
long authAvail(0);
- auto const rc = curl_easy_getinfo(rSession.m_pCurl.get(),
- statusCode == SC_UNAUTHORIZED
- ? CURLINFO_HTTPAUTH_AVAIL
- : CURLINFO_PROXYAUTH_AVAIL,
- &authAvail);
+ auto const rc
+ = curl_easy_getinfo(rSession.m_pCurl.get(),
+ statusCode != SC_PROXY_AUTHENTICATION_REQUIRED
+ ? CURLINFO_HTTPAUTH_AVAIL
+ : CURLINFO_PROXYAUTH_AVAIL,
+ &authAvail);
assert(rc == CURLE_OK);
(void)rc;
+ if (statusCode == SC_FORBIDDEN)
+ { // SharePoint fallback: try Negotiate auth
+ assert(authAvail == 0);
+ // note: this must be a single value!
+ // would need 2 iterations to try CURLAUTH_NTLM too
+ authAvail = CURLAUTH_NEGOTIATE;
+ }
// only allow SystemCredentials once - the
// PasswordContainer may have stored it in the
// Config (TrySystemCredentialsFirst or
@@ -1436,8 +1472,9 @@ auto CurlProcessor::ProcessRequest(
auto const ret = pEnv->m_xAuthListener->authenticate(
oRealm ? *oRealm : "",
- statusCode == SC_UNAUTHORIZED ? rSession.m_URI.GetHost()
- : rSession.m_Proxy,
+ statusCode != SC_PROXY_AUTHENTICATION_REQUIRED
+ ? rSession.m_URI.GetHost()
+ : rSession.m_Proxy,
userName, passWord, isSystemCredSupported);
if (ret == 0)