curl_sspi.c (5778B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 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 #ifdef USE_WINDOWS_SSPI 28 29 #include <curl/curl.h> 30 #include "curl_sspi.h" 31 #include "strdup.h" 32 #include "curlx/multibyte.h" 33 #include "system_win32.h" 34 #include "curlx/version_win32.h" 35 #include "curlx/warnless.h" 36 37 /* The last #include files should be: */ 38 #include "curl_memory.h" 39 #include "memdebug.h" 40 41 /* Pointer to SSPI dispatch table */ 42 PSecurityFunctionTable Curl_pSecFn = NULL; 43 44 /* 45 * Curl_sspi_global_init() 46 * 47 * This is used to load the Security Service Provider Interface (SSPI) 48 * dynamic link library portably across all Windows versions, without 49 * the need to directly link libcurl, nor the application using it, at 50 * build time. 51 * 52 * Once this function has been executed, Windows SSPI functions can be 53 * called through the Security Service Provider Interface dispatch table. 54 * 55 * Parameters: 56 * 57 * None. 58 * 59 * Returns CURLE_OK on success. 60 */ 61 CURLcode Curl_sspi_global_init(void) 62 { 63 /* If security interface is not yet initialized try to do this */ 64 if(!Curl_pSecFn) { 65 /* Get pointer to Security Service Provider Interface dispatch table */ 66 #ifdef __MINGW32CE__ 67 Curl_pSecFn = InitSecurityInterfaceW(); 68 #else 69 Curl_pSecFn = InitSecurityInterface(); 70 #endif 71 if(!Curl_pSecFn) 72 return CURLE_FAILED_INIT; 73 } 74 75 return CURLE_OK; 76 } 77 78 /* 79 * Curl_sspi_global_cleanup() 80 * 81 * This deinitializes the Security Service Provider Interface from libcurl. 82 * 83 * Parameters: 84 * 85 * None. 86 */ 87 void Curl_sspi_global_cleanup(void) 88 { 89 if(Curl_pSecFn) { 90 Curl_pSecFn = NULL; 91 } 92 } 93 94 /* 95 * Curl_create_sspi_identity() 96 * 97 * This is used to populate an SSPI identity structure based on the supplied 98 * username and password. 99 * 100 * Parameters: 101 * 102 * userp [in] - The username in the format User or Domain\User. 103 * passwdp [in] - The user's password. 104 * identity [in/out] - The identity structure. 105 * 106 * Returns CURLE_OK on success. 107 */ 108 CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, 109 SEC_WINNT_AUTH_IDENTITY *identity) 110 { 111 xcharp_u useranddomain; 112 xcharp_u user, dup_user; 113 xcharp_u domain, dup_domain; 114 xcharp_u passwd, dup_passwd; 115 size_t domlen = 0; 116 117 domain.const_tchar_ptr = TEXT(""); 118 119 /* Initialize the identity */ 120 memset(identity, 0, sizeof(*identity)); 121 122 useranddomain.tchar_ptr = curlx_convert_UTF8_to_tchar(userp); 123 if(!useranddomain.tchar_ptr) 124 return CURLE_OUT_OF_MEMORY; 125 126 user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\')); 127 if(!user.const_tchar_ptr) 128 user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/')); 129 130 if(user.tchar_ptr) { 131 domain.tchar_ptr = useranddomain.tchar_ptr; 132 domlen = user.tchar_ptr - useranddomain.tchar_ptr; 133 user.tchar_ptr++; 134 } 135 else { 136 user.tchar_ptr = useranddomain.tchar_ptr; 137 domain.const_tchar_ptr = TEXT(""); 138 domlen = 0; 139 } 140 141 /* Setup the identity's user and length */ 142 dup_user.tchar_ptr = _tcsdup(user.tchar_ptr); 143 if(!dup_user.tchar_ptr) { 144 curlx_unicodefree(useranddomain.tchar_ptr); 145 return CURLE_OUT_OF_MEMORY; 146 } 147 identity->User = dup_user.tbyte_ptr; 148 identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); 149 dup_user.tchar_ptr = NULL; 150 151 /* Setup the identity's domain and length */ 152 dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); 153 if(!dup_domain.tchar_ptr) { 154 curlx_unicodefree(useranddomain.tchar_ptr); 155 return CURLE_OUT_OF_MEMORY; 156 } 157 _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); 158 *(dup_domain.tchar_ptr + domlen) = TEXT('\0'); 159 identity->Domain = dup_domain.tbyte_ptr; 160 identity->DomainLength = curlx_uztoul(domlen); 161 dup_domain.tchar_ptr = NULL; 162 163 curlx_unicodefree(useranddomain.tchar_ptr); 164 165 /* Setup the identity's password and length */ 166 passwd.tchar_ptr = curlx_convert_UTF8_to_tchar(passwdp); 167 if(!passwd.tchar_ptr) 168 return CURLE_OUT_OF_MEMORY; 169 dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr); 170 if(!dup_passwd.tchar_ptr) { 171 curlx_unicodefree(passwd.tchar_ptr); 172 return CURLE_OUT_OF_MEMORY; 173 } 174 identity->Password = dup_passwd.tbyte_ptr; 175 identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); 176 dup_passwd.tchar_ptr = NULL; 177 178 curlx_unicodefree(passwd.tchar_ptr); 179 180 /* Setup the identity's flags */ 181 identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY; 182 183 return CURLE_OK; 184 } 185 186 /* 187 * Curl_sspi_free_identity() 188 * 189 * This is used to free the contents of an SSPI identifier structure. 190 * 191 * Parameters: 192 * 193 * identity [in/out] - The identity structure. 194 */ 195 void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity) 196 { 197 if(identity) { 198 Curl_safefree(identity->User); 199 Curl_safefree(identity->Password); 200 Curl_safefree(identity->Domain); 201 } 202 } 203 204 #endif /* USE_WINDOWS_SSPI */