diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2024-03-07 18:38:22 +0100 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2024-03-08 15:18:49 +0100 |
commit | d7492813058bff81c17068feee0e4ba7627c17de (patch) | |
tree | 68543a3f3056223c5fef9f6eadd4eeecc3390c5b /ucb | |
parent | 218e4641c4e2e0f894afab40b0e789636e73ad4c (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.cxx | 63 |
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) |