1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
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.haxx.se/docs/copyright.html.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef USE_WINDOWS_SSPI
27 #include <curl/curl.h>
28 #include "curl_sspi.h"
29 #include "curl_multibyte.h"
30 #include "system_win32.h"
33 /* The last #include files should be: */
34 #include "curl_memory.h"
37 /* We use our own typedef here since some headers might lack these */
38 typedef PSecurityFunctionTable (APIENTRY
*INITSECURITYINTERFACE_FN
)(VOID
);
40 /* See definition of SECURITY_ENTRYPOINT in sspi.h */
43 # define SECURITYENTRYPOINT L"InitSecurityInterfaceW"
45 # define SECURITYENTRYPOINT "InitSecurityInterfaceW"
48 # define SECURITYENTRYPOINT "InitSecurityInterfaceA"
51 /* Handle of security.dll or secur32.dll, depending on Windows version */
52 HMODULE s_hSecDll
= NULL
;
54 /* Pointer to SSPI dispatch table */
55 PSecurityFunctionTable s_pSecFn
= NULL
;
58 * Curl_sspi_global_init()
60 * This is used to load the Security Service Provider Interface (SSPI)
61 * dynamic link library portably across all Windows versions, without
62 * the need to directly link libcurl, nor the application using it, at
65 * Once this function has been executed, Windows SSPI functions can be
66 * called through the Security Service Provider Interface dispatch table.
68 CURLcode
Curl_sspi_global_init(void)
70 bool securityDll
= FALSE
;
71 INITSECURITYINTERFACE_FN pInitSecurityInterface
;
73 /* If security interface is not yet initialized try to do this */
75 /* Security Service Provider Interface (SSPI) functions are located in
76 * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
77 * have both these DLLs (security.dll forwards calls to secur32.dll) */
78 DWORD majorVersion
= 4;
79 DWORD platformId
= VER_PLATFORM_WIN32_NT
;
81 #if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
82 (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
85 memset(&osver
, 0, sizeof(osver
));
86 osver
.dwOSVersionInfoSize
= sizeof(osver
);
88 /* Find out Windows version */
89 if(!GetVersionEx(&osver
))
90 return CURLE_FAILED_INIT
;
92 /* Verify the major version number == 4 and platform id == WIN_NT */
93 if(osver
.dwMajorVersion
== majorVersion
&&
94 osver
.dwPlatformId
== platformId
)
98 OSVERSIONINFOEX osver
;
100 memset(&osver
, 0, sizeof(osver
));
101 osver
.dwOSVersionInfoSize
= sizeof(osver
);
102 osver
.dwMajorVersion
= majorVersion
;
103 osver
.dwPlatformId
= platformId
;
105 cm
= VerSetConditionMask(0, VER_MAJORVERSION
, VER_EQUAL
);
106 cm
= VerSetConditionMask(cm
, VER_MINORVERSION
, VER_GREATER_EQUAL
);
107 cm
= VerSetConditionMask(cm
, VER_SERVICEPACKMAJOR
, VER_GREATER_EQUAL
);
108 cm
= VerSetConditionMask(cm
, VER_SERVICEPACKMINOR
, VER_GREATER_EQUAL
);
109 cm
= VerSetConditionMask(cm
, VER_PLATFORMID
, VER_EQUAL
);
111 /* Verify the major version number == 4 and platform id == WIN_NT */
112 if(VerifyVersionInfo(&osver
, (VER_MAJORVERSION
| VER_MINORVERSION
|
113 VER_SERVICEPACKMAJOR
| VER_SERVICEPACKMINOR
|
119 /* Load SSPI dll into the address space of the calling process */
121 s_hSecDll
= Curl_load_library(TEXT("security.dll"));
123 s_hSecDll
= Curl_load_library(TEXT("secur32.dll"));
125 return CURLE_FAILED_INIT
;
127 /* Get address of the InitSecurityInterfaceA function from the SSPI dll */
128 pInitSecurityInterface
= (INITSECURITYINTERFACE_FN
)
129 GetProcAddress(s_hSecDll
, SECURITYENTRYPOINT
);
130 if(!pInitSecurityInterface
)
131 return CURLE_FAILED_INIT
;
133 /* Get pointer to Security Service Provider Interface dispatch table */
134 s_pSecFn
= pInitSecurityInterface();
136 return CURLE_FAILED_INIT
;
143 * Curl_sspi_global_cleanup()
145 * This deinitializes the Security Service Provider Interface from libcurl.
148 void Curl_sspi_global_cleanup(void)
151 FreeLibrary(s_hSecDll
);
158 * Curl_create_sspi_identity()
160 * This is used to populate a SSPI identity structure based on the supplied
161 * username and password.
165 * userp [in] - The user name in the format User or Domain\User.
166 * passdwp [in] - The user's password.
167 * identity [in/out] - The identity structure.
169 * Returns CURLE_OK on success.
171 CURLcode
Curl_create_sspi_identity(const char *userp
, const char *passwdp
,
172 SEC_WINNT_AUTH_IDENTITY
*identity
)
174 xcharp_u useranddomain
;
175 xcharp_u user
, dup_user
;
176 xcharp_u domain
, dup_domain
;
177 xcharp_u passwd
, dup_passwd
;
180 domain
.const_tchar_ptr
= TEXT("");
182 /* Initialize the identity */
183 memset(identity
, 0, sizeof(*identity
));
185 useranddomain
.tchar_ptr
= Curl_convert_UTF8_to_tchar((char *)userp
);
186 if(!useranddomain
.tchar_ptr
)
187 return CURLE_OUT_OF_MEMORY
;
189 user
.const_tchar_ptr
= _tcschr(useranddomain
.const_tchar_ptr
, TEXT('\\'));
190 if(!user
.const_tchar_ptr
)
191 user
.const_tchar_ptr
= _tcschr(useranddomain
.const_tchar_ptr
, TEXT('/'));
194 domain
.tchar_ptr
= useranddomain
.tchar_ptr
;
195 domlen
= user
.tchar_ptr
- useranddomain
.tchar_ptr
;
199 user
.tchar_ptr
= useranddomain
.tchar_ptr
;
200 domain
.const_tchar_ptr
= TEXT("");
204 /* Setup the identity's user and length */
205 dup_user
.tchar_ptr
= _tcsdup(user
.tchar_ptr
);
206 if(!dup_user
.tchar_ptr
) {
207 Curl_unicodefree(useranddomain
.tchar_ptr
);
208 return CURLE_OUT_OF_MEMORY
;
210 identity
->User
= dup_user
.tbyte_ptr
;
211 identity
->UserLength
= curlx_uztoul(_tcslen(dup_user
.tchar_ptr
));
212 dup_user
.tchar_ptr
= NULL
;
214 /* Setup the identity's domain and length */
215 dup_domain
.tchar_ptr
= malloc(sizeof(TCHAR
) * (domlen
+ 1));
216 if(!dup_domain
.tchar_ptr
) {
217 Curl_unicodefree(useranddomain
.tchar_ptr
);
218 return CURLE_OUT_OF_MEMORY
;
220 _tcsncpy(dup_domain
.tchar_ptr
, domain
.tchar_ptr
, domlen
);
221 *(dup_domain
.tchar_ptr
+ domlen
) = TEXT('\0');
222 identity
->Domain
= dup_domain
.tbyte_ptr
;
223 identity
->DomainLength
= curlx_uztoul(domlen
);
224 dup_domain
.tchar_ptr
= NULL
;
226 Curl_unicodefree(useranddomain
.tchar_ptr
);
228 /* Setup the identity's password and length */
229 passwd
.tchar_ptr
= Curl_convert_UTF8_to_tchar((char *)passwdp
);
230 if(!passwd
.tchar_ptr
)
231 return CURLE_OUT_OF_MEMORY
;
232 dup_passwd
.tchar_ptr
= _tcsdup(passwd
.tchar_ptr
);
233 if(!dup_passwd
.tchar_ptr
) {
234 Curl_unicodefree(passwd
.tchar_ptr
);
235 return CURLE_OUT_OF_MEMORY
;
237 identity
->Password
= dup_passwd
.tbyte_ptr
;
238 identity
->PasswordLength
= curlx_uztoul(_tcslen(dup_passwd
.tchar_ptr
));
239 dup_passwd
.tchar_ptr
= NULL
;
241 Curl_unicodefree(passwd
.tchar_ptr
);
243 /* Setup the identity's flags */
244 identity
->Flags
= SECFLAG_WINNT_AUTH_IDENTITY
;
249 void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY
*identity
)
252 Curl_safefree(identity
->User
);
253 Curl_safefree(identity
->Password
);
254 Curl_safefree(identity
->Domain
);
258 #endif /* USE_WINDOWS_SSPI */