LCOV - code coverage report
Current view: top level - port - cpl_swift.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 236 291 81.1 %
Date: 2024-04-28 21:03:45 Functions: 18 19 94.7 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  * Project:  CPL - Common Portability Library
       3             :  * Purpose:  OpenStack Swift Object Storage routines
       4             :  * Author:   Even Rouault <even.rouault at spatialys.com>
       5             :  *
       6             :  **********************************************************************
       7             :  * Copyright (c) 2018, Even Rouault <even.rouault at spatialys.com>
       8             :  *
       9             :  * Permission is hereby granted, free of charge, to any person obtaining a
      10             :  * copy of this software and associated documentation files (the "Software"),
      11             :  * to deal in the Software without restriction, including without limitation
      12             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13             :  * and/or sell copies of the Software, and to permit persons to whom the
      14             :  * Software is furnished to do so, subject to the following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice shall be included
      17             :  * in all copies or substantial portions of the Software.
      18             :  *
      19             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      20             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      22             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      24             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      25             :  * DEALINSwift IN THE SOFTWARE.
      26             :  ****************************************************************************/
      27             : 
      28             : #include "cpl_swift.h"
      29             : #include "cpl_vsi_error.h"
      30             : #include "cpl_http.h"
      31             : #include "cpl_multiproc.h"
      32             : #include "cpl_json.h"
      33             : 
      34             : // HOWTO setup a Docker-based SWIFT server:
      35             : // https://github.com/MorrisJobke/docker-swift-onlyone
      36             : 
      37             : //! @cond Doxygen_Suppress
      38             : 
      39             : #ifdef HAVE_CURL
      40             : 
      41             : static CPLMutex *g_hMutex = nullptr;
      42             : static std::string g_osLastAuthURL;
      43             : static std::string g_osLastUser;
      44             : static std::string g_osLastKey;
      45             : static std::string g_osLastStorageURL;
      46             : static std::string g_osLastAuthToken;
      47             : 
      48             : /************************************************************************/
      49             : /*                          GetSwiftHeaders()                           */
      50             : /************************************************************************/
      51             : 
      52          40 : static struct curl_slist *GetSwiftHeaders(const std::string &osAuthToken)
      53             : {
      54          40 :     struct curl_slist *headers = nullptr;
      55          40 :     headers = curl_slist_append(headers, "Accept: application/json");
      56          40 :     headers = curl_slist_append(
      57             :         headers, CPLSPrintf("x-auth-token: %s", osAuthToken.c_str()));
      58          40 :     return headers;
      59             : }
      60             : 
      61             : /************************************************************************/
      62             : /*                     VSISwiftHandleHelper()                           */
      63             : /************************************************************************/
      64          67 : VSISwiftHandleHelper::VSISwiftHandleHelper(const std::string &osStorageURL,
      65             :                                            const std::string &osAuthToken,
      66             :                                            const std::string &osBucket,
      67          67 :                                            const std::string &osObjectKey)
      68             :     : m_osURL(BuildURL(osStorageURL, osBucket, osObjectKey)),
      69             :       m_osStorageURL(osStorageURL), m_osAuthToken(osAuthToken),
      70          67 :       m_osBucket(osBucket), m_osObjectKey(osObjectKey)
      71             : {
      72          67 : }
      73             : 
      74             : /************************************************************************/
      75             : /*                      ~VSISwiftHandleHelper()                         */
      76             : /************************************************************************/
      77             : 
      78         134 : VSISwiftHandleHelper::~VSISwiftHandleHelper()
      79             : {
      80         134 : }
      81             : 
      82             : /************************************************************************/
      83             : /*                        GetConfiguration()                            */
      84             : /************************************************************************/
      85             : 
      86          70 : bool VSISwiftHandleHelper::GetConfiguration(const std::string &osPathForOption,
      87             :                                             std::string &osStorageURL,
      88             :                                             std::string &osAuthToken)
      89             : {
      90             :     osStorageURL = VSIGetPathSpecificOption(osPathForOption.c_str(),
      91          70 :                                             "SWIFT_STORAGE_URL", "");
      92          70 :     if (!osStorageURL.empty())
      93             :     {
      94             :         osAuthToken = VSIGetPathSpecificOption(osPathForOption.c_str(),
      95          64 :                                                "SWIFT_AUTH_TOKEN", "");
      96          64 :         if (osAuthToken.empty())
      97             :         {
      98           1 :             const char *pszMsg = "Missing SWIFT_AUTH_TOKEN";
      99           1 :             CPLDebug("SWIFT", "%s", pszMsg);
     100           1 :             VSIError(VSIE_AWSInvalidCredentials, "%s", pszMsg);
     101           1 :             return false;
     102             :         }
     103          63 :         return true;
     104             :     }
     105             : 
     106             :     const std::string osAuthVersion = VSIGetPathSpecificOption(
     107          12 :         osPathForOption.c_str(), "OS_IDENTITY_API_VERSION", "");
     108           6 :     if (osAuthVersion == "3")
     109             :     {
     110             :         const std::string osAuthType = VSIGetPathSpecificOption(
     111           2 :             osPathForOption.c_str(), "OS_AUTH_TYPE", "");
     112           2 :         if (!CheckCredentialsV3(osPathForOption, osAuthType))
     113           0 :             return false;
     114           2 :         if (osAuthType == "v3applicationcredential")
     115             :         {
     116           1 :             if (GetCached(osPathForOption, "OS_AUTH_URL",
     117             :                           "OS_APPLICATION_CREDENTIAL_ID",
     118             :                           "OS_APPLICATION_CREDENTIAL_SECRET", osStorageURL,
     119             :                           osAuthToken))
     120           0 :                 return true;
     121             :         }
     122             :         else
     123             :         {
     124           1 :             if (GetCached(osPathForOption, "OS_AUTH_URL", "OS_USERNAME",
     125             :                           "OS_PASSWORD", osStorageURL, osAuthToken))
     126           0 :                 return true;
     127             :         }
     128           2 :         if (AuthV3(osPathForOption, osAuthType, osStorageURL, osAuthToken))
     129           2 :             return true;
     130             :     }
     131             :     else
     132             :     {
     133             :         const std::string osAuthV1URL = VSIGetPathSpecificOption(
     134           4 :             osPathForOption.c_str(), "SWIFT_AUTH_V1_URL", "");
     135           4 :         if (!osAuthV1URL.empty())
     136             :         {
     137           2 :             if (!CheckCredentialsV1(osPathForOption))
     138           0 :                 return false;
     139           2 :             if (GetCached(osPathForOption, "SWIFT_AUTH_V1_URL", "SWIFT_USER",
     140             :                           "SWIFT_KEY", osStorageURL, osAuthToken))
     141           1 :                 return true;
     142           1 :             if (AuthV1(osPathForOption, osStorageURL, osAuthToken))
     143           1 :                 return true;
     144             :         }
     145             :     }
     146             : 
     147           2 :     const char *pszMsg = "Missing SWIFT_STORAGE_URL+SWIFT_AUTH_TOKEN or "
     148             :                          "appropriate authentication options";
     149           2 :     CPLDebug("SWIFT", "%s", pszMsg);
     150           2 :     VSIError(VSIE_AWSInvalidCredentials, "%s", pszMsg);
     151             : 
     152           2 :     return false;
     153             : }
     154             : 
     155             : /************************************************************************/
     156             : /*                               AuthV1()                               */
     157             : /************************************************************************/
     158             : 
     159           1 : bool VSISwiftHandleHelper::AuthV1(const std::string &osPathForOption,
     160             :                                   std::string &osStorageURL,
     161             :                                   std::string &osAuthToken)
     162             : {
     163             :     std::string osAuthURL = VSIGetPathSpecificOption(osPathForOption.c_str(),
     164           2 :                                                      "SWIFT_AUTH_V1_URL", "");
     165             :     std::string osUser =
     166           2 :         VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_USER", "");
     167             :     std::string osKey =
     168           2 :         VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_KEY", "");
     169             :     char **papszHeaders =
     170           1 :         CSLSetNameValue(nullptr, "HEADERS",
     171             :                         CPLSPrintf("X-Auth-User: %s\r\n"
     172             :                                    "X-Auth-Key: %s",
     173             :                                    osUser.c_str(), osKey.c_str()));
     174           1 :     CPLHTTPResult *psResult = CPLHTTPFetch(osAuthURL.c_str(), papszHeaders);
     175           1 :     CSLDestroy(papszHeaders);
     176           1 :     if (psResult == nullptr)
     177           0 :         return false;
     178             :     osStorageURL =
     179           1 :         CSLFetchNameValueDef(psResult->papszHeaders, "X-Storage-Url", "");
     180             :     osAuthToken =
     181           1 :         CSLFetchNameValueDef(psResult->papszHeaders, "X-Auth-Token", "");
     182             :     std::string osErrorMsg =
     183           1 :         psResult->pabyData ? reinterpret_cast<const char *>(psResult->pabyData)
     184           2 :                            : "";
     185           1 :     CPLHTTPDestroyResult(psResult);
     186           1 :     if (osStorageURL.empty() || osAuthToken.empty())
     187             :     {
     188           0 :         CPLDebug("SWIFT", "Authentication failed: %s", osErrorMsg.c_str());
     189           0 :         VSIError(VSIE_AWSInvalidCredentials, "Authentication failed: %s",
     190             :                  osErrorMsg.c_str());
     191           0 :         return false;
     192             :     }
     193             : 
     194             :     // Cache credentials
     195             :     {
     196           2 :         CPLMutexHolder oHolder(&g_hMutex);
     197           1 :         g_osLastAuthURL = std::move(osAuthURL);
     198           1 :         g_osLastUser = std::move(osUser);
     199           1 :         g_osLastKey = std::move(osKey);
     200           1 :         g_osLastStorageURL = osStorageURL;
     201           1 :         g_osLastAuthToken = osAuthToken;
     202             :     }
     203             : 
     204           1 :     return true;
     205             : }
     206             : 
     207             : /************************************************************************/
     208             : /*                      CreateAuthV3RequestObject()                     */
     209             : /************************************************************************/
     210             : 
     211           2 : CPLJSONObject VSISwiftHandleHelper::CreateAuthV3RequestObject(
     212             :     const std::string &osPathForOption, const std::string &osAuthType)
     213             : {
     214           4 :     CPLJSONArray methods;
     215           4 :     CPLJSONObject identity;
     216           4 :     CPLJSONObject scope;
     217           2 :     if (osAuthType == "v3applicationcredential")
     218             :     {
     219             :         std::string osApplicationCredentialID = VSIGetPathSpecificOption(
     220           2 :             osPathForOption.c_str(), "OS_APPLICATION_CREDENTIAL_ID", "");
     221             :         std::string osApplicationCredentialSecret = VSIGetPathSpecificOption(
     222           2 :             osPathForOption.c_str(), "OS_APPLICATION_CREDENTIAL_SECRET", "");
     223           1 :         CPLJSONObject applicationCredential;
     224           1 :         applicationCredential.Add("id", osApplicationCredentialID);
     225           1 :         applicationCredential.Add("secret", osApplicationCredentialSecret);
     226           1 :         methods.Add("application_credential");
     227           1 :         identity.Add("application_credential", applicationCredential);
     228             :         // Application credentials cannot request a scope.
     229             :     }
     230             :     else
     231             :     {
     232             :         std::string osUser = VSIGetPathSpecificOption(osPathForOption.c_str(),
     233           2 :                                                       "OS_USERNAME", "");
     234             :         std::string osPassword = VSIGetPathSpecificOption(
     235           2 :             osPathForOption.c_str(), "OS_PASSWORD", "");
     236             : 
     237           2 :         CPLJSONObject user;
     238           1 :         user.Add("name", osUser);
     239           1 :         user.Add("password", osPassword);
     240             : 
     241             :         std::string osUserDomainName = VSIGetPathSpecificOption(
     242           2 :             osPathForOption.c_str(), "OS_USER_DOMAIN_NAME", "");
     243           1 :         if (!osUserDomainName.empty())
     244             :         {
     245           1 :             CPLJSONObject userDomain;
     246           1 :             userDomain.Add("name", osUserDomainName);
     247           1 :             user.Add("domain", userDomain);
     248             :         }
     249             : 
     250           2 :         CPLJSONObject password;
     251           1 :         password.Add("user", user);
     252           1 :         methods.Add("password");
     253           1 :         identity.Add("password", password);
     254             : 
     255             :         // Request a scope if one is specified in the configuration
     256             :         std::string osProjectName = VSIGetPathSpecificOption(
     257           2 :             osPathForOption.c_str(), "OS_PROJECT_NAME", "");
     258           1 :         if (!osProjectName.empty())
     259             :         {
     260           2 :             CPLJSONObject project;
     261           1 :             project.Add("name", osProjectName);
     262             : 
     263             :             std::string osProjectDomainName = VSIGetPathSpecificOption(
     264           1 :                 osPathForOption.c_str(), "OS_PROJECT_DOMAIN_NAME", "");
     265           1 :             if (!osProjectDomainName.empty())
     266             :             {
     267           1 :                 CPLJSONObject projectDomain;
     268           1 :                 projectDomain.Add("name", osProjectDomainName);
     269           1 :                 project.Add("domain", projectDomain);
     270             :             }
     271             : 
     272           1 :             scope.Add("project", project);
     273             :         }
     274             :     }
     275             : 
     276           2 :     identity.Add("methods", methods);
     277             : 
     278           4 :     CPLJSONObject auth;
     279           2 :     auth.Add("identity", identity);
     280           2 :     if (!scope.GetChildren().empty())
     281           1 :         auth.Add("scope", scope);
     282             : 
     283           2 :     CPLJSONObject obj;
     284           2 :     obj.Add("auth", auth);
     285           4 :     return obj;
     286             : }
     287             : 
     288             : /************************************************************************/
     289             : /*                      GetAuthV3StorageURL()                           */
     290             : /************************************************************************/
     291             : 
     292           2 : bool VSISwiftHandleHelper::GetAuthV3StorageURL(
     293             :     const std::string &osPathForOption, const CPLHTTPResult *psResult,
     294             :     std::string &storageURL)
     295             : {
     296           2 :     if (psResult->pabyData == nullptr)
     297           0 :         return false;
     298             : 
     299           4 :     CPLJSONDocument resultJson;
     300           2 :     resultJson.LoadMemory(psResult->pabyData);
     301           4 :     CPLJSONObject result(resultJson.GetRoot());
     302             : 
     303           6 :     CPLJSONObject token(result.GetObj("token"));
     304           2 :     if (!token.IsValid())
     305           0 :         return false;
     306             : 
     307           6 :     CPLJSONArray catalog(token.GetArray("catalog"));
     308           2 :     if (!catalog.IsValid())
     309           0 :         return false;
     310             : 
     311           4 :     CPLJSONArray endpoints;
     312           2 :     for (int i = 0; i < catalog.Size(); ++i)
     313             :     {
     314           2 :         CPLJSONObject item(catalog[i]);
     315           2 :         if (item.GetString("type") == "object-store")
     316             :         {
     317           2 :             endpoints = item.GetArray("endpoints");
     318           2 :             break;
     319             :         }
     320             :     }
     321             : 
     322           2 :     if (endpoints.Size() == 0)
     323           0 :         return false;
     324             : 
     325             :     std::string osRegionName =
     326           4 :         VSIGetPathSpecificOption(osPathForOption.c_str(), "OS_REGION_NAME", "");
     327           2 :     if (osRegionName.empty())
     328             :     {
     329           0 :         for (int i = 0; i < endpoints.Size(); ++i)
     330             :         {
     331           0 :             CPLJSONObject endpoint(endpoints[i]);
     332             :             std::string interfaceType =
     333           0 :                 endpoint.GetString("interface", "");  // internal, admin, public
     334           0 :             if (interfaceType.empty() || interfaceType == "public")
     335             :             {
     336           0 :                 storageURL = endpoint.GetString("url");
     337           0 :                 return true;
     338             :             }
     339             :         }
     340           0 :         return false;
     341             :     }
     342             : 
     343           6 :     for (int i = 0; i < endpoints.Size(); ++i)
     344             :     {
     345           6 :         CPLJSONObject endpoint(endpoints[i]);
     346           6 :         if (endpoint.GetString("region") == osRegionName)
     347             :         {
     348             :             std::string interfaceType =
     349          12 :                 endpoint.GetString("interface", "");  // internal, admin, public
     350           6 :             if (interfaceType.empty() || interfaceType == "public")
     351             :             {
     352           2 :                 storageURL = endpoint.GetString("url");
     353           2 :                 CPLDebug("SWIFT", "Storage URL '%s' for region '%s'",
     354             :                          storageURL.c_str(), osRegionName.c_str());
     355           2 :                 return true;
     356             :             }
     357             :         }
     358             :     }
     359             : 
     360           0 :     return false;
     361             : }
     362             : 
     363             : /************************************************************************/
     364             : /*                                AuthV3()                              */
     365             : /************************************************************************/
     366             : 
     367           2 : bool VSISwiftHandleHelper::AuthV3(const std::string &osPathForOption,
     368             :                                   const std::string &osAuthType,
     369             :                                   std::string &osStorageURL,
     370             :                                   std::string &osAuthToken)
     371             : {
     372           4 :     std::string osAuthID;
     373           4 :     std::string osAuthKey;
     374           2 :     if (osAuthType.empty() || osAuthType == "password")
     375             :     {
     376             :         osAuthID = VSIGetPathSpecificOption(osPathForOption.c_str(),
     377           1 :                                             "OS_USERNAME", "");
     378             :         osAuthKey = VSIGetPathSpecificOption(osPathForOption.c_str(),
     379           1 :                                              "OS_PASSWORD", "");
     380             :     }
     381           1 :     else if (osAuthType == "v3applicationcredential")
     382             :     {
     383             :         osAuthID = VSIGetPathSpecificOption(osPathForOption.c_str(),
     384           1 :                                             "OS_APPLICATION_CREDENTIAL_ID", "");
     385             :         osAuthKey = VSIGetPathSpecificOption(
     386           1 :             osPathForOption.c_str(), "OS_APPLICATION_CREDENTIAL_SECRET", "");
     387             :     }
     388             :     else
     389             :     {
     390           0 :         CPLDebug("SWIFT", "Unsupported OS SWIFT Auth Type: %s",
     391             :                  osAuthType.c_str());
     392           0 :         VSIError(VSIE_AWSInvalidCredentials, "%s", osAuthType.c_str());
     393           0 :         return false;
     394             :     }
     395             :     CPLJSONObject postObject(
     396           4 :         CreateAuthV3RequestObject(osPathForOption, osAuthType));
     397           4 :     std::string post = postObject.Format(CPLJSONObject::PrettyFormat::Plain);
     398             : 
     399             :     // coverity[tainted_data]
     400             :     std::string osAuthURL =
     401           4 :         VSIGetPathSpecificOption(osPathForOption.c_str(), "OS_AUTH_URL", "");
     402           4 :     std::string url = osAuthURL;
     403           2 :     if (!url.empty() && url.back() != '/')
     404           2 :         url += '/';
     405           2 :     url += "auth/tokens";
     406             : 
     407           2 :     char **papszOptions = CSLSetNameValue(nullptr, "POSTFIELDS", post.data());
     408           2 :     papszOptions = CSLSetNameValue(papszOptions, "HEADERS",
     409             :                                    "Content-Type: application/json");
     410           2 :     CPLHTTPResult *psResult = CPLHTTPFetchEx(url.c_str(), papszOptions, nullptr,
     411             :                                              nullptr, nullptr, nullptr);
     412           2 :     CSLDestroy(papszOptions);
     413             : 
     414           2 :     if (psResult == nullptr)
     415           0 :         return false;
     416             : 
     417             :     osAuthToken =
     418           2 :         CSLFetchNameValueDef(psResult->papszHeaders, "X-Subject-Token", "");
     419             : 
     420           2 :     if (!GetAuthV3StorageURL(osPathForOption, psResult, osStorageURL))
     421             :     {
     422           0 :         CPLHTTPDestroyResult(psResult);
     423           0 :         return false;
     424             :     }
     425             : 
     426           2 :     if (osStorageURL.empty() || osAuthToken.empty())
     427             :     {
     428             :         std::string osErrorMsg =
     429           0 :             reinterpret_cast<const char *>(psResult->pabyData);
     430           0 :         CPLDebug("SWIFT", "Authentication failed: %s", osErrorMsg.c_str());
     431           0 :         VSIError(VSIE_AWSInvalidCredentials, "Authentication failed: %s",
     432             :                  osErrorMsg.c_str());
     433           0 :         CPLHTTPDestroyResult(psResult);
     434           0 :         return false;
     435             :     }
     436             : 
     437           2 :     CPLHTTPDestroyResult(psResult);
     438             : 
     439             :     // Cache credentials
     440             :     {
     441           4 :         CPLMutexHolder oHolder(&g_hMutex);
     442           2 :         g_osLastAuthURL = std::move(osAuthURL);
     443           2 :         g_osLastUser = std::move(osAuthID);
     444           2 :         g_osLastKey = std::move(osAuthKey);
     445           2 :         g_osLastStorageURL = osStorageURL;
     446           2 :         g_osLastAuthToken = osAuthToken;
     447             :     }
     448           2 :     return true;
     449             : }
     450             : 
     451             : /************************************************************************/
     452             : /*                           Authenticate()                             */
     453             : /************************************************************************/
     454             : 
     455           0 : bool VSISwiftHandleHelper::Authenticate(const std::string &osPathForOption)
     456             : {
     457             :     std::string osAuthV1URL = VSIGetPathSpecificOption(osPathForOption.c_str(),
     458           0 :                                                        "SWIFT_AUTH_V1_URL", "");
     459           0 :     if (!osAuthV1URL.empty() &&
     460           0 :         AuthV1(osPathForOption, m_osStorageURL, m_osAuthToken))
     461             :     {
     462           0 :         RebuildURL();
     463           0 :         return true;
     464             :     }
     465             : 
     466             :     const std::string osAuthVersion = VSIGetPathSpecificOption(
     467           0 :         osPathForOption.c_str(), "OS_IDENTITY_API_VERSION", "");
     468             :     const std::string osAuthType =
     469           0 :         VSIGetPathSpecificOption(osPathForOption.c_str(), "OS_AUTH_TYPE", "");
     470           0 :     if (osAuthVersion == "3" &&
     471           0 :         AuthV3(osPathForOption, osAuthType, m_osStorageURL, m_osAuthToken))
     472             :     {
     473           0 :         RebuildURL();
     474           0 :         return true;
     475             :     }
     476             : 
     477           0 :     return false;
     478             : }
     479             : 
     480             : /************************************************************************/
     481             : /*                         CheckCredentialsV1()                         */
     482             : /************************************************************************/
     483             : 
     484           2 : bool VSISwiftHandleHelper::CheckCredentialsV1(
     485             :     const std::string &osPathForOption)
     486             : {
     487           2 :     const char *pszMissingKey = nullptr;
     488             :     std::string osUser =
     489           4 :         VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_USER", "");
     490             :     std::string osKey =
     491           4 :         VSIGetPathSpecificOption(osPathForOption.c_str(), "SWIFT_KEY", "");
     492           2 :     if (osUser.empty())
     493             :     {
     494           0 :         pszMissingKey = "SWIFT_USER";
     495             :     }
     496           2 :     else if (osKey.empty())
     497             :     {
     498           0 :         pszMissingKey = "SWIFT_KEY";
     499             :     }
     500             : 
     501           2 :     if (pszMissingKey)
     502             :     {
     503           0 :         CPLDebug("SWIFT", "Missing %s configuration option", pszMissingKey);
     504           0 :         VSIError(VSIE_AWSInvalidCredentials, "%s", pszMissingKey);
     505           0 :         return false;
     506             :     }
     507             : 
     508           2 :     return true;
     509             : }
     510             : 
     511             : /************************************************************************/
     512             : /*                         CheckCredentialsV3()                         */
     513             : /************************************************************************/
     514             : 
     515           2 : bool VSISwiftHandleHelper::CheckCredentialsV3(
     516             :     const std::string &osPathForOption, const std::string &osAuthType)
     517             : {
     518           2 :     const char *papszMandatoryOptionKeys[3] = {
     519             :         "OS_AUTH_URL",
     520             :         "",
     521             :         "",
     522             :     };
     523           2 :     if (osAuthType.empty() || osAuthType == "password")
     524             :     {
     525           1 :         papszMandatoryOptionKeys[1] = "OS_USERNAME";
     526           1 :         papszMandatoryOptionKeys[2] = "OS_PASSWORD";
     527             :     }
     528           1 :     else if (osAuthType == "v3applicationcredential")
     529             :     {
     530           1 :         papszMandatoryOptionKeys[1] = "OS_APPLICATION_CREDENTIAL_ID";
     531           1 :         papszMandatoryOptionKeys[2] = "OS_APPLICATION_CREDENTIAL_SECRET";
     532             :     }
     533             :     else
     534             :     {
     535           0 :         CPLDebug("SWIFT", "Unsupported OS SWIFT Auth Type: %s",
     536             :                  osAuthType.c_str());
     537           0 :         VSIError(VSIE_AWSInvalidCredentials, "%s", osAuthType.c_str());
     538           0 :         return false;
     539             :     }
     540           8 :     for (auto const *pszOptionKey : papszMandatoryOptionKeys)
     541             :     {
     542             :         std::string option =
     543           6 :             VSIGetPathSpecificOption(osPathForOption.c_str(), pszOptionKey, "");
     544           6 :         if (option.empty())
     545             :         {
     546           0 :             CPLDebug("SWIFT", "Missing %s configuration option", pszOptionKey);
     547           0 :             VSIError(VSIE_AWSInvalidCredentials, "%s", pszOptionKey);
     548           0 :             return false;
     549             :         }
     550             :     }
     551           2 :     return true;
     552             : }
     553             : 
     554             : /************************************************************************/
     555             : /*                            GetCached()                               */
     556             : /************************************************************************/
     557             : 
     558           4 : bool VSISwiftHandleHelper::GetCached(const std::string &osPathForOption,
     559             :                                      const char *pszURLKey,
     560             :                                      const char *pszUserKey,
     561             :                                      const char *pszPasswordKey,
     562             :                                      std::string &osStorageURL,
     563             :                                      std::string &osAuthToken)
     564             : {
     565             :     std::string osAuthURL =
     566           8 :         VSIGetPathSpecificOption(osPathForOption.c_str(), pszURLKey, "");
     567             :     std::string osUser =
     568           8 :         VSIGetPathSpecificOption(osPathForOption.c_str(), pszUserKey, "");
     569             :     std::string osKey =
     570           8 :         VSIGetPathSpecificOption(osPathForOption.c_str(), pszPasswordKey, "");
     571             : 
     572           8 :     CPLMutexHolder oHolder(&g_hMutex);
     573             :     // Re-use cached credentials if available
     574             :     // coverity[tainted_data]
     575           5 :     if (osAuthURL == g_osLastAuthURL && osUser == g_osLastUser &&
     576           1 :         osKey == g_osLastKey)
     577             :     {
     578           1 :         osStorageURL = g_osLastStorageURL;
     579           1 :         osAuthToken = g_osLastAuthToken;
     580           1 :         return true;
     581             :     }
     582           3 :     return false;
     583             : }
     584             : 
     585             : /************************************************************************/
     586             : /*                          BuildFromURI()                              */
     587             : /************************************************************************/
     588             : 
     589             : VSISwiftHandleHelper *
     590          70 : VSISwiftHandleHelper::BuildFromURI(const char *pszURI,
     591             :                                    const char * /*pszFSPrefix*/)
     592             : {
     593         140 :     std::string osPathForOption("/vsiswift/");
     594          70 :     osPathForOption += pszURI;
     595             : 
     596         140 :     std::string osStorageURL;
     597         140 :     std::string osAuthToken;
     598             : 
     599          70 :     if (!GetConfiguration(osPathForOption, osStorageURL, osAuthToken))
     600             :     {
     601           3 :         return nullptr;
     602             :     }
     603             : 
     604             :     // pszURI == bucket/object
     605         134 :     const std::string osBucketObject(pszURI);
     606         134 :     std::string osBucket(osBucketObject);
     607          67 :     std::string osObjectKey;
     608          67 :     size_t nSlashPos = osBucketObject.find('/');
     609          67 :     if (nSlashPos != std::string::npos)
     610             :     {
     611          36 :         osBucket = osBucketObject.substr(0, nSlashPos);
     612          36 :         osObjectKey = osBucketObject.substr(nSlashPos + 1);
     613             :     }
     614             : 
     615             :     return new VSISwiftHandleHelper(osStorageURL, osAuthToken, osBucket,
     616          67 :                                     osObjectKey);
     617             : }
     618             : 
     619             : /************************************************************************/
     620             : /*                            BuildURL()                                */
     621             : /************************************************************************/
     622             : 
     623         118 : std::string VSISwiftHandleHelper::BuildURL(const std::string &osStorageURL,
     624             :                                            const std::string &osBucket,
     625             :                                            const std::string &osObjectKey)
     626             : {
     627         118 :     std::string osURL = osStorageURL;
     628         118 :     if (!osBucket.empty())
     629         109 :         osURL += "/" + CPLAWSURLEncode(osBucket, false);
     630         118 :     if (!osObjectKey.empty())
     631          40 :         osURL += "/" + CPLAWSURLEncode(osObjectKey, false);
     632         118 :     return osURL;
     633             : }
     634             : 
     635             : /************************************************************************/
     636             : /*                           RebuildURL()                               */
     637             : /************************************************************************/
     638             : 
     639          51 : void VSISwiftHandleHelper::RebuildURL()
     640             : {
     641          51 :     m_osURL = BuildURL(m_osStorageURL, m_osBucket, m_osObjectKey);
     642          51 :     m_osURL += GetQueryString(false);
     643          51 : }
     644             : 
     645             : /************************************************************************/
     646             : /*                           GetCurlHeaders()                           */
     647             : /************************************************************************/
     648             : 
     649          40 : struct curl_slist *VSISwiftHandleHelper::GetCurlHeaders(
     650             :     const std::string &, const struct curl_slist *, const void *, size_t) const
     651             : {
     652          40 :     return GetSwiftHeaders(m_osAuthToken);
     653             : }
     654             : 
     655             : /************************************************************************/
     656             : /*                          CleanMutex()                                */
     657             : /************************************************************************/
     658             : 
     659         849 : void VSISwiftHandleHelper::CleanMutex()
     660             : {
     661         849 :     if (g_hMutex != nullptr)
     662         849 :         CPLDestroyMutex(g_hMutex);
     663         849 :     g_hMutex = nullptr;
     664         849 : }
     665             : 
     666             : /************************************************************************/
     667             : /*                          ClearCache()                                */
     668             : /************************************************************************/
     669             : 
     670        1095 : void VSISwiftHandleHelper::ClearCache()
     671             : {
     672        2190 :     CPLMutexHolder oHolder(&g_hMutex);
     673        1095 :     g_osLastAuthURL.clear();
     674        1095 :     g_osLastUser.clear();
     675        1095 :     g_osLastKey.clear();
     676        1095 :     g_osLastStorageURL.clear();
     677        1095 :     g_osLastAuthToken.clear();
     678        1095 : }
     679             : 
     680             : #endif
     681             : 
     682             : //! @endcond

Generated by: LCOV version 1.14