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)

Reply via email to