*
***************************************************************************/
-#include "setup.h"
+#include "curl_setup.h"
#ifdef USE_WINDOWS_SSPI
#include <curl/mprintf.h>
#include "curl_memory.h"
+#include "curl_multibyte.h"
+#include "warnless.h"
+
/* The last #include file should be: */
#include "memdebug.h"
-
/* We use our own typedef here since some headers might lack these */
-typedef PSecurityFunctionTableA (APIENTRY *INITSECURITYINTERFACE_FN_A)(VOID);
+typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID);
+
+/* See definition of SECURITY_ENTRYPOINT in sspi.h */
+#ifdef UNICODE
+# ifdef _WIN32_WCE
+# define SECURITYENTRYPOINT L"InitSecurityInterfaceW"
+# else
+# define SECURITYENTRYPOINT "InitSecurityInterfaceW"
+# endif
+#else
+# define SECURITYENTRYPOINT "InitSecurityInterfaceA"
+#endif
/* Handle of security.dll or secur32.dll, depending on Windows version */
HMODULE s_hSecDll = NULL;
/* Pointer to SSPI dispatch table */
-PSecurityFunctionTableA s_pSecFn = NULL;
-
+PSecurityFunctionTable s_pSecFn = NULL;
/*
* Curl_sspi_global_init()
* Once this function has been executed, Windows SSPI functions can be
* called through the Security Service Provider Interface dispatch table.
*/
-
-CURLcode
-Curl_sspi_global_init(void)
+CURLcode Curl_sspi_global_init(void)
{
- OSVERSIONINFO osver;
- INITSECURITYINTERFACE_FN_A pInitSecurityInterface;
+ bool securityDll = FALSE;
+ INITSECURITYINTERFACE_FN pInitSecurityInterface;
/* If security interface is not yet initialized try to do this */
- if(s_hSecDll == NULL) {
+ if(!s_hSecDll) {
+ /* Security Service Provider Interface (SSPI) functions are located in
+ * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
+ * have both these DLLs (security.dll forwards calls to secur32.dll) */
+ DWORD majorVersion = 4;
+ DWORD platformId = VER_PLATFORM_WIN32_NT;
+
+#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
+ (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
+ OSVERSIONINFO osver;
- /* Find out Windows version */
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
- if(! GetVersionEx(&osver))
+
+ /* Find out Windows version */
+ if(!GetVersionEx(&osver))
return CURLE_FAILED_INIT;
- /* Security Service Provider Interface (SSPI) functions are located in
- * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
- * have both these DLLs (security.dll forwards calls to secur32.dll) */
+ /* Verify the major version number == 4 and platform id == WIN_NT */
+ if(osver.dwMajorVersion == majorVersion &&
+ osver.dwPlatformId == platformId)
+ securityDll = TRUE;
+#else
+ ULONGLONG majorVersionMask;
+ ULONGLONG platformIdMask;
+ OSVERSIONINFOEX osver;
+
+ memset(&osver, 0, sizeof(osver));
+ osver.dwOSVersionInfoSize = sizeof(osver);
+ osver.dwMajorVersion = majorVersion;
+ osver.dwPlatformId = platformId;
+ majorVersionMask = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
+ platformIdMask = VerSetConditionMask(0, VER_PLATFORMID, VER_EQUAL);
+
+ /* Verify the major version number == 4 and platform id == WIN_NT */
+ if(VerifyVersionInfo(&osver, VER_MAJORVERSION, majorVersionMask) &&
+ VerifyVersionInfo(&osver, VER_PLATFORMID, platformIdMask))
+ securityDll = TRUE;
+#endif
/* Load SSPI dll into the address space of the calling process */
- if(osver.dwPlatformId == VER_PLATFORM_WIN32_NT
- && osver.dwMajorVersion == 4)
- s_hSecDll = LoadLibrary("security.dll");
+ if(securityDll)
+ s_hSecDll = LoadLibrary(TEXT("security.dll"));
else
- s_hSecDll = LoadLibrary("secur32.dll");
- if(! s_hSecDll)
+ s_hSecDll = LoadLibrary(TEXT("secur32.dll"));
+ if(!s_hSecDll)
return CURLE_FAILED_INIT;
/* Get address of the InitSecurityInterfaceA function from the SSPI dll */
- pInitSecurityInterface = (INITSECURITYINTERFACE_FN_A)
- GetProcAddress(s_hSecDll, "InitSecurityInterfaceA");
- if(! pInitSecurityInterface)
+ pInitSecurityInterface = (INITSECURITYINTERFACE_FN)
+ GetProcAddress(s_hSecDll, SECURITYENTRYPOINT);
+ if(!pInitSecurityInterface)
return CURLE_FAILED_INIT;
/* Get pointer to Security Service Provider Interface dispatch table */
s_pSecFn = pInitSecurityInterface();
- if(! s_pSecFn)
+ if(!s_pSecFn)
return CURLE_FAILED_INIT;
-
}
+
return CURLE_OK;
}
-
/*
* Curl_sspi_global_cleanup()
*
* This deinitializes the Security Service Provider Interface from libcurl.
*/
-void
-Curl_sspi_global_cleanup(void)
+void Curl_sspi_global_cleanup(void)
{
if(s_hSecDll) {
FreeLibrary(s_hSecDll);
}
}
-
/*
- * Curl_sspi_version()
+ * Curl_create_sspi_identity()
+ *
+ * This is used to populate a SSPI identity structure based on the supplied
+ * username and password.
*
- * This function returns the SSPI library version information.
+ * Parameters:
+ *
+ * userp [in] - The user name in the format User or Domain\User.
+ * passdwp [in] - The user's password.
+ * identity [in/out] - The identity structure.
+ *
+ * Returns CURLE_OK on success.
*/
-CURLcode Curl_sspi_version(int *major, int *minor, int *build, int *special)
+CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
+ SEC_WINNT_AUTH_IDENTITY *identity)
{
- CURLcode result = CURLE_OK;
- VS_FIXEDFILEINFO *version_info = NULL;
- LPTSTR path = NULL;
- LPVOID data = NULL;
- DWORD size, handle;
+ xcharp_u useranddomain;
+ xcharp_u user, dup_user;
+ xcharp_u domain, dup_domain;
+ xcharp_u passwd, dup_passwd;
+ size_t domlen = 0;
+
+ domain.const_tchar_ptr = TEXT("");
- if(!s_hSecDll)
- return CURLE_FAILED_INIT;
+ /* Initialize the identity */
+ memset(identity, 0, sizeof(*identity));
- path = (char *) malloc(MAX_PATH);
- if(!path)
+ useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp);
+ if(!useranddomain.tchar_ptr)
return CURLE_OUT_OF_MEMORY;
- if(GetModuleFileName(s_hSecDll, path, MAX_PATH)) {
- size = GetFileVersionInfoSize(path, &handle);
- if(size) {
- data = malloc(size);
- if(data) {
- if(GetFileVersionInfo(path, handle, size, data)) {
- if(!VerQueryValue(data, "\\", &version_info, &handle))
- result = CURLE_OUT_OF_MEMORY;
- }
- else
- result = CURLE_OUT_OF_MEMORY;
- }
- else
- result = CURLE_OUT_OF_MEMORY;
- }
- else
- result = CURLE_OUT_OF_MEMORY;
+ user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\'));
+ if(!user.const_tchar_ptr)
+ user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/'));
+
+ if(user.tchar_ptr) {
+ domain.tchar_ptr = useranddomain.tchar_ptr;
+ domlen = user.tchar_ptr - useranddomain.tchar_ptr;
+ user.tchar_ptr++;
}
- else
- result = CURLE_OUT_OF_MEMORY;
-
- /* Set the out parameters */
- if(!result) {
- if(major)
- *major = (version_info->dwProductVersionMS >> 16) & 0xffff;
-
- if(minor)
- *minor = (version_info->dwProductVersionMS >> 0) & 0xffff;
-
- if(build)
- *build = (version_info->dwProductVersionLS >> 16) & 0xffff;
-
- if(special)
- *special = (version_info->dwProductVersionLS >> 0) & 0xffff;
+ else {
+ user.tchar_ptr = useranddomain.tchar_ptr;
+ domain.const_tchar_ptr = TEXT("");
+ domlen = 0;
}
- Curl_safefree(data);
- Curl_safefree(path);
-
- return result;
-}
+ /* Setup the identity's user and length */
+ dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
+ if(!dup_user.tchar_ptr) {
+ Curl_unicodefree(useranddomain.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ identity->User = dup_user.tbyte_ptr;
+ identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr));
+ dup_user.tchar_ptr = NULL;
+
+ /* Setup the identity's domain and length */
+ dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
+ if(!dup_domain.tchar_ptr) {
+ Curl_unicodefree(useranddomain.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
+ *(dup_domain.tchar_ptr + domlen) = TEXT('\0');
+ identity->Domain = dup_domain.tbyte_ptr;
+ identity->DomainLength = curlx_uztoul(domlen);
+ dup_domain.tchar_ptr = NULL;
+ Curl_unicodefree(useranddomain.tchar_ptr);
-/*
- * Curl_sspi_status(SECURIY_STATUS status)
- *
- * This function returns a string representing an SSPI status.
- * It will in any case return a usable string pointer which needs to be freed.
- */
-char*
-Curl_sspi_status(SECURITY_STATUS status)
-{
- const char* status_const;
-
- switch(status) {
- case SEC_I_COMPLETE_AND_CONTINUE:
- status_const = "SEC_I_COMPLETE_AND_CONTINUE";
- break;
- case SEC_I_COMPLETE_NEEDED:
- status_const = "SEC_I_COMPLETE_NEEDED";
- break;
- case SEC_I_CONTINUE_NEEDED:
- status_const = "SEC_I_CONTINUE_NEEDED";
- break;
- case SEC_I_CONTEXT_EXPIRED:
- status_const = "SEC_I_CONTEXT_EXPIRED";
- break;
- case SEC_I_INCOMPLETE_CREDENTIALS:
- status_const = "SEC_I_INCOMPLETE_CREDENTIALS";
- break;
- case SEC_I_RENEGOTIATE:
- status_const = "SEC_I_RENEGOTIATE";
- break;
- case SEC_E_BUFFER_TOO_SMALL:
- status_const = "SEC_E_BUFFER_TOO_SMALL";
- break;
- case SEC_E_CONTEXT_EXPIRED:
- status_const = "SEC_E_CONTEXT_EXPIRED";
- break;
- case SEC_E_CRYPTO_SYSTEM_INVALID:
- status_const = "SEC_E_CRYPTO_SYSTEM_INVALID";
- break;
- case SEC_E_INCOMPLETE_MESSAGE:
- status_const = "SEC_E_INCOMPLETE_MESSAGE";
- break;
- case SEC_E_INSUFFICIENT_MEMORY:
- status_const = "SEC_E_INSUFFICIENT_MEMORY";
- break;
- case SEC_E_INTERNAL_ERROR:
- status_const = "SEC_E_INTERNAL_ERROR";
- break;
- case SEC_E_INVALID_HANDLE:
- status_const = "SEC_E_INVALID_HANDLE";
- break;
- case SEC_E_INVALID_TOKEN:
- status_const = "SEC_E_INVALID_TOKEN";
- break;
- case SEC_E_LOGON_DENIED:
- status_const = "SEC_E_LOGON_DENIED";
- break;
- case SEC_E_MESSAGE_ALTERED:
- status_const = "SEC_E_MESSAGE_ALTERED";
- break;
- case SEC_E_NO_AUTHENTICATING_AUTHORITY:
- status_const = "SEC_E_NO_AUTHENTICATING_AUTHORITY";
- break;
- case SEC_E_NO_CREDENTIALS:
- status_const = "SEC_E_NO_CREDENTIALS";
- break;
- case SEC_E_NOT_OWNER:
- status_const = "SEC_E_NOT_OWNER";
- break;
- case SEC_E_OK:
- status_const = "SEC_E_OK";
- break;
- case SEC_E_OUT_OF_SEQUENCE:
- status_const = "SEC_E_OUT_OF_SEQUENCE";
- break;
- case SEC_E_QOP_NOT_SUPPORTED:
- status_const = "SEC_E_QOP_NOT_SUPPORTED";
- break;
- case SEC_E_SECPKG_NOT_FOUND:
- status_const = "SEC_E_SECPKG_NOT_FOUND";
- break;
- case SEC_E_TARGET_UNKNOWN:
- status_const = "SEC_E_TARGET_UNKNOWN";
- break;
- case SEC_E_UNKNOWN_CREDENTIALS:
- status_const = "SEC_E_UNKNOWN_CREDENTIALS";
- break;
- case SEC_E_UNSUPPORTED_FUNCTION:
- status_const = "SEC_E_UNSUPPORTED_FUNCTION";
- break;
- case SEC_E_WRONG_PRINCIPAL:
- status_const = "SEC_E_WRONG_PRINCIPAL";
- break;
- default:
- status_const = "Unknown error";
+ /* Setup ntlm identity's password and length */
+ passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp);
+ if(!passwd.tchar_ptr)
+ return CURLE_OUT_OF_MEMORY;
+ dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
+ if(!dup_passwd.tchar_ptr) {
+ Curl_unicodefree(passwd.tchar_ptr);
+ return CURLE_OUT_OF_MEMORY;
}
+ identity->Password = dup_passwd.tbyte_ptr;
+ identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
+ dup_passwd.tchar_ptr = NULL;
- return curl_maprintf("%s (0x%04X%04X)", status_const,
- (status>>16)&0xffff, status&0xffff);
-}
+ Curl_unicodefree(passwd.tchar_ptr);
+ /* Setup the identity's flags */
+ identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;
-/*
- * Curl_sspi_status_msg(SECURITY_STATUS status)
- *
- * This function returns a message representing an SSPI status.
- * It will in any case return a usable string pointer which needs to be freed.
- */
+ return CURLE_OK;
+}
-char*
-Curl_sspi_status_msg(SECURITY_STATUS status)
+void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
{
- LPSTR format_msg = NULL;
- char *status_msg = NULL, *status_const = NULL;
- int status_len = 0;
-
- status_len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, status, 0, (LPTSTR)&format_msg, 0, NULL);
-
- if(status_len > 0 && format_msg) {
- status_msg = strdup(format_msg);
- LocalFree(format_msg);
-
- /* remove trailing CR+LF */
- if(status_len > 0) {
- if(status_msg[status_len-1] == '\n') {
- status_msg[status_len-1] = '\0';
- if(status_len > 1) {
- if(status_msg[status_len-2] == '\r') {
- status_msg[status_len-2] = '\0';
- }
- }
- }
- }
- }
-
- status_const = Curl_sspi_status(status);
- if(status_msg) {
- status_msg = curl_maprintf("%s [%s]", status_msg, status_const);
- free(status_const);
+ if(identity) {
+ Curl_safefree(identity->User);
+ Curl_safefree(identity->Password);
+ Curl_safefree(identity->Domain);
}
- else {
- status_msg = status_const;
- }
-
- return status_msg;
}
#endif /* USE_WINDOWS_SSPI */