ucb/source/ucp/webdav-curl/CurlSession.cxx | 60 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 20 deletions(-)
New commits: commit c6df10ce7f91b3084255bfbbac95e865bbb3ce7b Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Mon Oct 10 15:40:41 2022 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Wed Oct 12 11:25:40 2022 +0200 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 fallback to NTLM auth in this case, if a first attempt with imported cookie didn't work. Note that the build config of libcurl on Linux is such that adding CURLAUTH_NEGOTIATE has no effect, but on WNT it causes the AuthMask to be ambiguous and prevents curl from trying NTLM. diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx index cc0a2368784f..b698026d16b6 100644 --- a/ucb/source/ucp/webdav-curl/CurlSession.cxx +++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx @@ -1380,29 +1380,38 @@ auto CurlProcessor::ProcessRequest( 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; + } if (cookies.isEmpty() // retry only once - could be expired... - && rSession.m_URI.GetScheme() == "https" // only encrypted - && it != headerMap.end() - && it->second.startsWith("917656;")) + && rSession.m_URI.GetScheme() == "https") // only encrypted { - cookies = TryImportCookies(rSession.m_xContext, rSession.m_URI.GetHost()); + cookies + = TryImportCookies(rSession.m_xContext, rSession.m_URI.GetHost()); if (!cookies.isEmpty()) { - CURLcode rc = curl_easy_setopt(rSession.m_pCurl.get(), CURLOPT_COOKIEFILE, ""); + CURLcode rc = curl_easy_setopt(rSession.m_pCurl.get(), + CURLOPT_COOKIEFILE, ""); assert(rc == CURLE_OK); - rc = curl_easy_setopt(rSession.m_pCurl.get(), CURLOPT_COOKIE, cookies.getStr()); + rc = curl_easy_setopt(rSession.m_pCurl.get(), CURLOPT_COOKIE, + cookies.getStr()); assert(rc == CURLE_OK); (void)rc; isRetry = true; + SAL_INFO("ucb.ucp.webdav.curl", "FedAuth cookie set"); + break; // try cookie once } } - break; + SAL_INFO("ucb.ucp.webdav.curl", "403 fallback authentication hack"); } + [[fallthrough]]; // SP, no cookie, or cookie failed: try NTLM case SC_UNAUTHORIZED: case SC_PROXY_AUTHENTICATION_REQUIRED: { - 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 " @@ -1410,22 +1419,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 hack: try NTLM auth + assert(authAvail == 0); + // note: this must be a single value! + // would need 2 iterations to try CURLAUTH_NEGOTIATE too + authAvail = CURLAUTH_NTLM; + } // only allow SystemCredentials once - the // PasswordContainer may have stored it in the // Config (TrySystemCredentialsFirst or @@ -1444,8 +1463,9 @@ auto CurlProcessor::ProcessRequest( auto const ret = pEnv->m_xAuthListener->authenticate( oRealm ? *oRealm : "", - statusCode == SC_UNAUTHORIZED ? rSession.m_URI.GetHost() - : rSession.m_Proxy.aName, + statusCode != SC_PROXY_AUTHENTICATION_REQUIRED + ? rSession.m_URI.GetHost() + : rSession.m_Proxy.aName, userName, passWord, isSystemCredSupported); if (ret == 0)