quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

vauth.c (7755B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 
     25 #include "../curl_setup.h"
     26 
     27 #include <curl/curl.h>
     28 
     29 #include "vauth.h"
     30 #include "../strdup.h"
     31 #include "../urldata.h"
     32 #include "../curlx/multibyte.h"
     33 #include "../curl_printf.h"
     34 #include "../url.h"
     35 
     36 /* The last #include files should be: */
     37 #include "../curl_memory.h"
     38 #include "../memdebug.h"
     39 
     40 /*
     41  * Curl_auth_build_spn()
     42  *
     43  * This is used to build an SPN string in the following formats:
     44  *
     45  * service/host@realm (Not currently used)
     46  * service/host       (Not used by GSS-API)
     47  * service@realm      (Not used by Windows SSPI)
     48  *
     49  * Parameters:
     50  *
     51  * service  [in] - The service type such as http, smtp, pop or imap.
     52  * host     [in] - The hostname.
     53  * realm    [in] - The realm.
     54  *
     55  * Returns a pointer to the newly allocated SPN.
     56  */
     57 #if !defined(USE_WINDOWS_SSPI)
     58 char *Curl_auth_build_spn(const char *service, const char *host,
     59                           const char *realm)
     60 {
     61   char *spn = NULL;
     62 
     63   /* Generate our SPN */
     64   if(host && realm)
     65     spn = aprintf("%s/%s@%s", service, host, realm);
     66   else if(host)
     67     spn = aprintf("%s/%s", service, host);
     68   else if(realm)
     69     spn = aprintf("%s@%s", service, realm);
     70 
     71   /* Return our newly allocated SPN */
     72   return spn;
     73 }
     74 #else
     75 TCHAR *Curl_auth_build_spn(const char *service, const char *host,
     76                            const char *realm)
     77 {
     78   char *utf8_spn = NULL;
     79   TCHAR *tchar_spn = NULL;
     80   TCHAR *dupe_tchar_spn = NULL;
     81 
     82   (void) realm;
     83 
     84   /* Note: We could use DsMakeSPN() or DsClientMakeSpnForTargetServer() rather
     85      than doing this ourselves but the first is only available in Windows XP
     86      and Windows Server 2003 and the latter is only available in Windows 2000
     87      but not Windows95/98/ME or Windows NT4.0 unless the Active Directory
     88      Client Extensions are installed. As such it is far simpler for us to
     89      formulate the SPN instead. */
     90 
     91   /* Generate our UTF8 based SPN */
     92   utf8_spn = aprintf("%s/%s", service, host);
     93   if(!utf8_spn)
     94     return NULL;
     95 
     96   /* Allocate and return a TCHAR based SPN. Since curlx_convert_UTF8_to_tchar
     97      must be freed by curlx_unicodefree we will dupe the result so that the
     98      pointer this function returns can be normally free'd. */
     99   tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn);
    100   free(utf8_spn);
    101   if(!tchar_spn)
    102     return NULL;
    103   dupe_tchar_spn = _tcsdup(tchar_spn);
    104   curlx_unicodefree(tchar_spn);
    105   return dupe_tchar_spn;
    106 }
    107 #endif /* USE_WINDOWS_SSPI */
    108 
    109 /*
    110  * Curl_auth_user_contains_domain()
    111  *
    112  * This is used to test if the specified user contains a Windows domain name as
    113  * follows:
    114  *
    115  * Domain\User (Down-level Logon Name)
    116  * Domain/User (curl Down-level format - for compatibility with existing code)
    117  * User@Domain (User Principal Name)
    118  *
    119  * Note: The username may be empty when using a GSS-API library or Windows
    120  * SSPI as the user and domain are either obtained from the credentials cache
    121  * when using GSS-API or via the currently logged in user's credentials when
    122  * using Windows SSPI.
    123  *
    124  * Parameters:
    125  *
    126  * user  [in] - The username.
    127  *
    128  * Returns TRUE on success; otherwise FALSE.
    129  */
    130 bool Curl_auth_user_contains_domain(const char *user)
    131 {
    132   bool valid = FALSE;
    133 
    134   if(user && *user) {
    135     /* Check we have a domain name or UPN present */
    136     char *p = strpbrk(user, "\\/@");
    137 
    138     valid = (p != NULL && p > user && p < user + strlen(user) - 1);
    139   }
    140 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    141   else
    142     /* User and domain are obtained from the GSS-API credentials cache or the
    143        currently logged in user from Windows */
    144     valid = TRUE;
    145 #endif
    146 
    147   return valid;
    148 }
    149 
    150 /*
    151  * Curl_auth_ollowed_to_host() tells if authentication, cookies or other
    152  * "sensitive data" can (still) be sent to this host.
    153  */
    154 bool Curl_auth_allowed_to_host(struct Curl_easy *data)
    155 {
    156   struct connectdata *conn = data->conn;
    157   return !data->state.this_is_a_follow ||
    158          data->set.allow_auth_to_other_hosts ||
    159          (data->state.first_host &&
    160           curl_strequal(data->state.first_host, conn->host.name) &&
    161           (data->state.first_remote_port == conn->remote_port) &&
    162           (data->state.first_remote_protocol == conn->handler->protocol));
    163 }
    164 
    165 #ifdef USE_NTLM
    166 
    167 static void ntlm_conn_dtor(void *key, size_t klen, void *entry)
    168 {
    169   struct ntlmdata *ntlm = entry;
    170   (void)key;
    171   (void)klen;
    172   DEBUGASSERT(ntlm);
    173   Curl_auth_cleanup_ntlm(ntlm);
    174   free(ntlm);
    175 }
    176 
    177 struct ntlmdata *Curl_auth_ntlm_get(struct connectdata *conn, bool proxy)
    178 {
    179   const char *key = proxy ? CURL_META_NTLM_PROXY_CONN :
    180                     CURL_META_NTLM_CONN;
    181   struct ntlmdata *ntlm = Curl_conn_meta_get(conn, key);
    182   if(!ntlm) {
    183     ntlm = calloc(1, sizeof(*ntlm));
    184     if(!ntlm ||
    185        Curl_conn_meta_set(conn, key, ntlm, ntlm_conn_dtor))
    186       return NULL;
    187   }
    188   return ntlm;
    189 }
    190 
    191 void Curl_auth_ntlm_remove(struct connectdata *conn, bool proxy)
    192 {
    193   Curl_conn_meta_remove(conn, proxy ?
    194     CURL_META_NTLM_PROXY_CONN : CURL_META_NTLM_CONN);
    195 }
    196 
    197 #endif /* USE_NTLM */
    198 
    199 #ifdef USE_KERBEROS5
    200 
    201 static void krb5_conn_dtor(void *key, size_t klen, void *entry)
    202 {
    203   struct kerberos5data *krb5 = entry;
    204   (void)key;
    205   (void)klen;
    206   DEBUGASSERT(krb5);
    207   Curl_auth_cleanup_gssapi(krb5);
    208   free(krb5);
    209 }
    210 
    211 struct kerberos5data *Curl_auth_krb5_get(struct connectdata *conn)
    212 {
    213   struct kerberos5data *krb5 = Curl_conn_meta_get(conn, CURL_META_KRB5_CONN);
    214   if(!krb5) {
    215     krb5 = calloc(1, sizeof(*krb5));
    216     if(!krb5 ||
    217        Curl_conn_meta_set(conn, CURL_META_KRB5_CONN, krb5, krb5_conn_dtor))
    218       return NULL;
    219   }
    220   return krb5;
    221 }
    222 
    223 #endif /* USE_KERBEROS5 */
    224 
    225 #ifdef USE_GSASL
    226 
    227 static void gsasl_conn_dtor(void *key, size_t klen, void *entry)
    228 {
    229   struct gsasldata *gsasl = entry;
    230   (void)key;
    231   (void)klen;
    232   DEBUGASSERT(gsasl);
    233   Curl_auth_gsasl_cleanup(gsasl);
    234   free(gsasl);
    235 }
    236 
    237 struct gsasldata *Curl_auth_gsasl_get(struct connectdata *conn)
    238 {
    239   struct gsasldata *gsasl = Curl_conn_meta_get(conn, CURL_META_GSASL_CONN);
    240   if(!gsasl) {
    241     gsasl = calloc(1, sizeof(*gsasl));
    242     if(!gsasl ||
    243        Curl_conn_meta_set(conn, CURL_META_GSASL_CONN, gsasl, gsasl_conn_dtor))
    244       return NULL;
    245   }
    246   return gsasl;
    247 }
    248 
    249 #endif /* USE_GSASL */
    250 
    251 #ifdef USE_SPNEGO
    252 
    253 static void nego_conn_dtor(void *key, size_t klen, void *entry)
    254 {
    255   struct negotiatedata *nego = entry;
    256   (void)key;
    257   (void)klen;
    258   DEBUGASSERT(nego);
    259   Curl_auth_cleanup_spnego(nego);
    260   free(nego);
    261 }
    262 
    263 struct negotiatedata *Curl_auth_nego_get(struct connectdata *conn, bool proxy)
    264 {
    265   const char *key = proxy ? CURL_META_NEGO_PROXY_CONN :
    266                     CURL_META_NEGO_CONN;
    267   struct negotiatedata *nego = Curl_conn_meta_get(conn, key);
    268   if(!nego) {
    269     nego = calloc(1, sizeof(*nego));
    270     if(!nego ||
    271        Curl_conn_meta_set(conn, key, nego, nego_conn_dtor))
    272       return NULL;
    273   }
    274   return nego;
    275 }
    276 
    277 #endif /* USE_SPNEGO */