xref: /aosp_15_r20/external/curl/lib/vauth/vauth.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Steve Holme, <[email protected]>.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker 
25*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker 
27*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
28*6236dae4SAndroid Build Coastguard Worker 
29*6236dae4SAndroid Build Coastguard Worker #include "vauth.h"
30*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
31*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
32*6236dae4SAndroid Build Coastguard Worker #include "curl_multibyte.h"
33*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
34*6236dae4SAndroid Build Coastguard Worker 
35*6236dae4SAndroid Build Coastguard Worker /* The last #include files should be: */
36*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
37*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
38*6236dae4SAndroid Build Coastguard Worker 
39*6236dae4SAndroid Build Coastguard Worker /*
40*6236dae4SAndroid Build Coastguard Worker  * Curl_auth_build_spn()
41*6236dae4SAndroid Build Coastguard Worker  *
42*6236dae4SAndroid Build Coastguard Worker  * This is used to build a SPN string in the following formats:
43*6236dae4SAndroid Build Coastguard Worker  *
44*6236dae4SAndroid Build Coastguard Worker  * service/host@realm (Not currently used)
45*6236dae4SAndroid Build Coastguard Worker  * service/host       (Not used by GSS-API)
46*6236dae4SAndroid Build Coastguard Worker  * service@realm      (Not used by Windows SSPI)
47*6236dae4SAndroid Build Coastguard Worker  *
48*6236dae4SAndroid Build Coastguard Worker  * Parameters:
49*6236dae4SAndroid Build Coastguard Worker  *
50*6236dae4SAndroid Build Coastguard Worker  * service  [in] - The service type such as http, smtp, pop or imap.
51*6236dae4SAndroid Build Coastguard Worker  * host     [in] - The hostname.
52*6236dae4SAndroid Build Coastguard Worker  * realm    [in] - The realm.
53*6236dae4SAndroid Build Coastguard Worker  *
54*6236dae4SAndroid Build Coastguard Worker  * Returns a pointer to the newly allocated SPN.
55*6236dae4SAndroid Build Coastguard Worker  */
56*6236dae4SAndroid Build Coastguard Worker #if !defined(USE_WINDOWS_SSPI)
Curl_auth_build_spn(const char * service,const char * host,const char * realm)57*6236dae4SAndroid Build Coastguard Worker char *Curl_auth_build_spn(const char *service, const char *host,
58*6236dae4SAndroid Build Coastguard Worker                           const char *realm)
59*6236dae4SAndroid Build Coastguard Worker {
60*6236dae4SAndroid Build Coastguard Worker   char *spn = NULL;
61*6236dae4SAndroid Build Coastguard Worker 
62*6236dae4SAndroid Build Coastguard Worker   /* Generate our SPN */
63*6236dae4SAndroid Build Coastguard Worker   if(host && realm)
64*6236dae4SAndroid Build Coastguard Worker     spn = aprintf("%s/%s@%s", service, host, realm);
65*6236dae4SAndroid Build Coastguard Worker   else if(host)
66*6236dae4SAndroid Build Coastguard Worker     spn = aprintf("%s/%s", service, host);
67*6236dae4SAndroid Build Coastguard Worker   else if(realm)
68*6236dae4SAndroid Build Coastguard Worker     spn = aprintf("%s@%s", service, realm);
69*6236dae4SAndroid Build Coastguard Worker 
70*6236dae4SAndroid Build Coastguard Worker   /* Return our newly allocated SPN */
71*6236dae4SAndroid Build Coastguard Worker   return spn;
72*6236dae4SAndroid Build Coastguard Worker }
73*6236dae4SAndroid Build Coastguard Worker #else
Curl_auth_build_spn(const char * service,const char * host,const char * realm)74*6236dae4SAndroid Build Coastguard Worker TCHAR *Curl_auth_build_spn(const char *service, const char *host,
75*6236dae4SAndroid Build Coastguard Worker                            const char *realm)
76*6236dae4SAndroid Build Coastguard Worker {
77*6236dae4SAndroid Build Coastguard Worker   char *utf8_spn = NULL;
78*6236dae4SAndroid Build Coastguard Worker   TCHAR *tchar_spn = NULL;
79*6236dae4SAndroid Build Coastguard Worker   TCHAR *dupe_tchar_spn = NULL;
80*6236dae4SAndroid Build Coastguard Worker 
81*6236dae4SAndroid Build Coastguard Worker   (void) realm;
82*6236dae4SAndroid Build Coastguard Worker 
83*6236dae4SAndroid Build Coastguard Worker   /* Note: We could use DsMakeSPN() or DsClientMakeSpnForTargetServer() rather
84*6236dae4SAndroid Build Coastguard Worker      than doing this ourselves but the first is only available in Windows XP
85*6236dae4SAndroid Build Coastguard Worker      and Windows Server 2003 and the latter is only available in Windows 2000
86*6236dae4SAndroid Build Coastguard Worker      but not Windows95/98/ME or Windows NT4.0 unless the Active Directory
87*6236dae4SAndroid Build Coastguard Worker      Client Extensions are installed. As such it is far simpler for us to
88*6236dae4SAndroid Build Coastguard Worker      formulate the SPN instead. */
89*6236dae4SAndroid Build Coastguard Worker 
90*6236dae4SAndroid Build Coastguard Worker   /* Generate our UTF8 based SPN */
91*6236dae4SAndroid Build Coastguard Worker   utf8_spn = aprintf("%s/%s", service, host);
92*6236dae4SAndroid Build Coastguard Worker   if(!utf8_spn)
93*6236dae4SAndroid Build Coastguard Worker     return NULL;
94*6236dae4SAndroid Build Coastguard Worker 
95*6236dae4SAndroid Build Coastguard Worker   /* Allocate and return a TCHAR based SPN. Since curlx_convert_UTF8_to_tchar
96*6236dae4SAndroid Build Coastguard Worker      must be freed by curlx_unicodefree we will dupe the result so that the
97*6236dae4SAndroid Build Coastguard Worker      pointer this function returns can be normally free'd. */
98*6236dae4SAndroid Build Coastguard Worker   tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn);
99*6236dae4SAndroid Build Coastguard Worker   free(utf8_spn);
100*6236dae4SAndroid Build Coastguard Worker   if(!tchar_spn)
101*6236dae4SAndroid Build Coastguard Worker     return NULL;
102*6236dae4SAndroid Build Coastguard Worker   dupe_tchar_spn = _tcsdup(tchar_spn);
103*6236dae4SAndroid Build Coastguard Worker   curlx_unicodefree(tchar_spn);
104*6236dae4SAndroid Build Coastguard Worker   return dupe_tchar_spn;
105*6236dae4SAndroid Build Coastguard Worker }
106*6236dae4SAndroid Build Coastguard Worker #endif /* USE_WINDOWS_SSPI */
107*6236dae4SAndroid Build Coastguard Worker 
108*6236dae4SAndroid Build Coastguard Worker /*
109*6236dae4SAndroid Build Coastguard Worker  * Curl_auth_user_contains_domain()
110*6236dae4SAndroid Build Coastguard Worker  *
111*6236dae4SAndroid Build Coastguard Worker  * This is used to test if the specified user contains a Windows domain name as
112*6236dae4SAndroid Build Coastguard Worker  * follows:
113*6236dae4SAndroid Build Coastguard Worker  *
114*6236dae4SAndroid Build Coastguard Worker  * Domain\User (Down-level Logon Name)
115*6236dae4SAndroid Build Coastguard Worker  * Domain/User (curl Down-level format - for compatibility with existing code)
116*6236dae4SAndroid Build Coastguard Worker  * User@Domain (User Principal Name)
117*6236dae4SAndroid Build Coastguard Worker  *
118*6236dae4SAndroid Build Coastguard Worker  * Note: The username may be empty when using a GSS-API library or Windows
119*6236dae4SAndroid Build Coastguard Worker  * SSPI as the user and domain are either obtained from the credentials cache
120*6236dae4SAndroid Build Coastguard Worker  * when using GSS-API or via the currently logged in user's credentials when
121*6236dae4SAndroid Build Coastguard Worker  * using Windows SSPI.
122*6236dae4SAndroid Build Coastguard Worker  *
123*6236dae4SAndroid Build Coastguard Worker  * Parameters:
124*6236dae4SAndroid Build Coastguard Worker  *
125*6236dae4SAndroid Build Coastguard Worker  * user  [in] - The username.
126*6236dae4SAndroid Build Coastguard Worker  *
127*6236dae4SAndroid Build Coastguard Worker  * Returns TRUE on success; otherwise FALSE.
128*6236dae4SAndroid Build Coastguard Worker  */
Curl_auth_user_contains_domain(const char * user)129*6236dae4SAndroid Build Coastguard Worker bool Curl_auth_user_contains_domain(const char *user)
130*6236dae4SAndroid Build Coastguard Worker {
131*6236dae4SAndroid Build Coastguard Worker   bool valid = FALSE;
132*6236dae4SAndroid Build Coastguard Worker 
133*6236dae4SAndroid Build Coastguard Worker   if(user && *user) {
134*6236dae4SAndroid Build Coastguard Worker     /* Check we have a domain name or UPN present */
135*6236dae4SAndroid Build Coastguard Worker     char *p = strpbrk(user, "\\/@");
136*6236dae4SAndroid Build Coastguard Worker 
137*6236dae4SAndroid Build Coastguard Worker     valid = (p != NULL && p > user && p < user + strlen(user) - 1);
138*6236dae4SAndroid Build Coastguard Worker   }
139*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
140*6236dae4SAndroid Build Coastguard Worker   else
141*6236dae4SAndroid Build Coastguard Worker     /* User and domain are obtained from the GSS-API credentials cache or the
142*6236dae4SAndroid Build Coastguard Worker        currently logged in user from Windows */
143*6236dae4SAndroid Build Coastguard Worker     valid = TRUE;
144*6236dae4SAndroid Build Coastguard Worker #endif
145*6236dae4SAndroid Build Coastguard Worker 
146*6236dae4SAndroid Build Coastguard Worker   return valid;
147*6236dae4SAndroid Build Coastguard Worker }
148*6236dae4SAndroid Build Coastguard Worker 
149*6236dae4SAndroid Build Coastguard Worker /*
150*6236dae4SAndroid Build Coastguard Worker  * Curl_auth_ollowed_to_host() tells if authentication, cookies or other
151*6236dae4SAndroid Build Coastguard Worker  * "sensitive data" can (still) be sent to this host.
152*6236dae4SAndroid Build Coastguard Worker  */
Curl_auth_allowed_to_host(struct Curl_easy * data)153*6236dae4SAndroid Build Coastguard Worker bool Curl_auth_allowed_to_host(struct Curl_easy *data)
154*6236dae4SAndroid Build Coastguard Worker {
155*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
156*6236dae4SAndroid Build Coastguard Worker   return (!data->state.this_is_a_follow ||
157*6236dae4SAndroid Build Coastguard Worker           data->set.allow_auth_to_other_hosts ||
158*6236dae4SAndroid Build Coastguard Worker           (data->state.first_host &&
159*6236dae4SAndroid Build Coastguard Worker            strcasecompare(data->state.first_host, conn->host.name) &&
160*6236dae4SAndroid Build Coastguard Worker            (data->state.first_remote_port == conn->remote_port) &&
161*6236dae4SAndroid Build Coastguard Worker            (data->state.first_remote_protocol == conn->handler->protocol)));
162*6236dae4SAndroid Build Coastguard Worker }
163