diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c new file mode 100644 index 000000000..b48c32348 --- /dev/null +++ b/lib/curl_multibyte.c @@ -0,0 +1,82 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "setup.h" + +#if defined(USE_WIN32_IDN) || \ + (defined(USE_WINDOWS_SSPI) && (defined(_WIN32_WCE) || defined(UNICODE))) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +#include "curl_multibyte.h" + +wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8) +{ + wchar_t *str_w = NULL; + + if(str_utf8) { + int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str_utf8, -1, NULL, 0); + if(str_w_len) { + str_w = malloc(str_w_len * sizeof(wchar_t)); + if(str_w) { + if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, + str_w_len) == 0) { + free(str_w); + str_w = NULL; + } + } + } + } + + return str_w; +} + +const char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) +{ + char *str_utf8 = NULL; + + if(str_w) { + size_t str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL, + 0, NULL, NULL); + if(str_utf8_len) { + str_utf8 = malloc(str_utf8_len * sizeof(wchar_t)); + if(str_utf8) { + if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len, + NULL, FALSE) == 0) { + (void) GetLastError(); + free((void *)str_utf8); + str_utf8 = NULL; + } + } + } + else { + (void) GetLastError(); + } + } + + return str_utf8; +} + +#endif /* USE_WIN32_IDN || (USE_WINDOWS_SSPI && (_WIN32_WCE || UNICODE)) */ diff --git a/lib/curl_multibyte.h b/lib/curl_multibyte.h new file mode 100644 index 000000000..015b9d418 --- /dev/null +++ b/lib/curl_multibyte.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_MULTIBYTE_H +#define HEADER_CURL_MULTIBYTE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "setup.h" + +#if defined(USE_WIN32_IDN) || \ + (defined(USE_WINDOWS_SSPI) && (defined(_WIN32_WCE) || defined(UNICODE))) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +#include + +wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); +const char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); + +#endif /* USE_WIN32_IDN || (USE_WINDOWS_SSPI && (_WIN32_WCE || UNICODE)) */ + +#endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/lib/curl_ntlm_msgs.c b/lib/curl_ntlm_msgs.c index 5789a24c7..0fd34cb80 100644 --- a/lib/curl_ntlm_msgs.c +++ b/lib/curl_ntlm_msgs.c @@ -89,6 +89,7 @@ #include "curl_base64.h" #include "curl_ntlm_core.h" #include "curl_gethostname.h" +#include "curl_multibyte.h" #include "curl_memory.h" #define BUILDING_CURL_NTLM_MSGS_C @@ -394,7 +395,6 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp, SecBufferDesc desc; SECURITY_STATUS status; ULONG attrs; - const char *dest = ""; const char *user; const char *domain = ""; size_t userlen = 0; @@ -431,12 +431,22 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp, */ ntlm->p_identity = &ntlm->identity; memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity)); +#ifdef UNICODE + if((ntlm->identity.User = Curl_convert_UTF8_to_wchar(user)) == NULL) + return CURLE_OUT_OF_MEMORY; +#else if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL) return CURLE_OUT_OF_MEMORY; +#endif ntlm->identity.UserLength = (unsigned long)userlen; +#ifdef UNICODE + if((ntlm->identity.Password = Curl_convert_UTF8_to_wchar(passwdp)) == NULL) + return CURLE_OUT_OF_MEMORY; +#else if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL) return CURLE_OUT_OF_MEMORY; +#endif ntlm->identity.PasswordLength = (unsigned long)passwdlen; if((ntlm->identity.Domain = malloc(domlen + 1)) == NULL) @@ -450,10 +460,10 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp, else ntlm->p_identity = NULL; - status = s_pSecFn->AcquireCredentialsHandleA(NULL, (void *)"NTLM", - SECPKG_CRED_OUTBOUND, NULL, - ntlm->p_identity, NULL, NULL, - &ntlm->handle, &tsDummy); + status = s_pSecFn->AcquireCredentialsHandle(NULL, TEXT("NTLM"), + SECPKG_CRED_OUTBOUND, NULL, + ntlm->p_identity, NULL, NULL, + &ntlm->handle, &tsDummy); if(status != SEC_E_OK) return CURLE_OUT_OF_MEMORY; @@ -464,15 +474,15 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp, buf.BufferType = SECBUFFER_TOKEN; buf.pvBuffer = ntlmbuf; - status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL, - (void *)dest, - ISC_REQ_CONFIDENTIALITY | - ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONNECTION, - 0, SECURITY_NETWORK_DREP, - NULL, 0, - &ntlm->c_handle, &desc, - &attrs, &tsDummy); + status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, NULL, + TEXT(""), + ISC_REQ_CONFIDENTIALITY | + ISC_REQ_REPLAY_DETECT | + ISC_REQ_CONNECTION, + 0, SECURITY_NETWORK_DREP, + NULL, 0, + &ntlm->c_handle, &desc, + &attrs, &tsDummy); if(status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) @@ -615,7 +625,6 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, size_t size; #ifdef USE_WINDOWS_SSPI - const char *dest = ""; SecBuffer type_2; SecBuffer type_3; SecBufferDesc type_2_desc; @@ -640,17 +649,17 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, type_3.pvBuffer = ntlmbuf; type_3.cbBuffer = NTLM_BUFSIZE; - status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, - &ntlm->c_handle, - (void *)dest, - ISC_REQ_CONFIDENTIALITY | - ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONNECTION, - 0, SECURITY_NETWORK_DREP, - &type_2_desc, - 0, &ntlm->c_handle, - &type_3_desc, - &attrs, &tsDummy); + status = s_pSecFn->InitializeSecurityContext(&ntlm->handle, + &ntlm->c_handle, + TEXT(""), + ISC_REQ_CONFIDENTIALITY | + ISC_REQ_REPLAY_DETECT | + ISC_REQ_CONNECTION, + 0, SECURITY_NETWORK_DREP, + &type_2_desc, + 0, &ntlm->c_handle, + &type_3_desc, + &attrs, &tsDummy); if(status != SEC_E_OK) return CURLE_RECV_ERROR; diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index c5793f956..ccb54a89f 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -36,6 +36,7 @@ #include "curl_ntlm_msgs.h" #include "curl_sasl.h" #include "warnless.h" +#include "curl_memory.h" #define _MPRINTF_REPLACE /* use our functions only */ #include diff --git a/lib/curl_schannel.c b/lib/curl_schannel.c index a2a5f381f..040133824 100644 --- a/lib/curl_schannel.c +++ b/lib/curl_schannel.c @@ -68,9 +68,11 @@ #include "strerror.h" #include "select.h" /* for the socket readyness */ #include "inet_pton.h" /* for IP addr SNI check */ +#include "curl_multibyte.h" #define _MPRINTF_REPLACE /* use our functions only */ #include + #include "curl_memory.h" /* The last #include file should be: */ #include "memdebug.h" @@ -98,6 +100,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif + LPTSTR host_name; infof(data, "schannel: connecting to %s:%hu (step 1/3)\n", conn->host.name, conn->remote_port); @@ -166,7 +169,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) failf(data, "schannel: SNI or certificate check failed: %s", Curl_sspi_strerror(conn, sspi_status)); else - failf(data, "schannel: AcquireCredentialsHandleA failed: %s", + failf(data, "schannel: AcquireCredentialsHandle failed: %s", Curl_sspi_strerror(conn, sspi_status)); free(connssl->cred); connssl->cred = NULL; @@ -196,18 +199,31 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) } memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt)); +#ifdef UNICODE + host_name = Curl_convert_UTF8_to_wchar(conn->host.name); + if(!host_name) + return CURLE_OUT_OF_MEMORY; +#else + host_name = conn->host.name; +#endif + /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */ + sspi_status = s_pSecFn->InitializeSecurityContext( - &connssl->cred->cred_handle, NULL, conn->host.name, + &connssl->cred->cred_handle, NULL, host_name, connssl->req_flags, 0, 0, NULL, 0, &connssl->ctxt->ctxt_handle, &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp); +#ifdef UNICODE + free(host_name); +#endif + if(sspi_status != SEC_I_CONTINUE_NEEDED) { if(sspi_status == SEC_E_WRONG_PRINCIPAL) failf(data, "schannel: SNI or certificate check failed: %s", Curl_sspi_strerror(conn, sspi_status)); else - failf(data, "schannel: initial InitializeSecurityContextA failed: %s", + failf(data, "schannel: initial InitializeSecurityContext failed: %s", Curl_sspi_strerror(conn, sspi_status)); free(connssl->ctxt); connssl->ctxt = NULL; @@ -247,6 +263,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) SecBuffer inbuf[2]; SecBufferDesc inbuf_desc; SECURITY_STATUS sspi_status = SEC_E_OK; + LPTSTR host_name; infof(data, "schannel: connecting to %s:%hu (step 2/3)\n", conn->host.name, conn->remote_port); @@ -319,12 +336,25 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) /* copy received handshake data into input buffer */ memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer, connssl->encdata_offset); +#ifdef UNICODE + host_name = Curl_convert_UTF8_to_wchar(conn->host.name); + if(!host_name) + return CURLE_OUT_OF_MEMORY; +#else + host_name = conn->host.name; +#endif + /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */ + sspi_status = s_pSecFn->InitializeSecurityContext( &connssl->cred->cred_handle, &connssl->ctxt->ctxt_handle, - conn->host.name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL, + host_name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL, &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp); +#ifdef UNICODE + free(host_name); +#endif + /* free buffer for received handshake data */ free(inbuf[0].pvBuffer); @@ -364,7 +394,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) failf(data, "schannel: SNI or certificate check failed: %s", Curl_sspi_strerror(conn, sspi_status)); else - failf(data, "schannel: next InitializeSecurityContextA failed: %s", + failf(data, "schannel: next InitializeSecurityContext failed: %s", Curl_sspi_strerror(conn, sspi_status)); return CURLE_SSL_CONNECT_ERROR; } diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c index cb83809b3..c3c41ec2f 100644 --- a/lib/curl_sspi.c +++ b/lib/curl_sspi.c @@ -36,13 +36,24 @@ #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() @@ -58,7 +69,7 @@ PSecurityFunctionTableA s_pSecFn = NULL; CURLcode Curl_sspi_global_init(void) { OSVERSIONINFO osver; - INITSECURITYINTERFACE_FN_A pInitSecurityInterface; + INITSECURITYINTERFACE_FN pInitSecurityInterface; /* If security interface is not yet initialized try to do this */ if(!s_hSecDll) { @@ -76,15 +87,15 @@ CURLcode Curl_sspi_global_init(void) /* 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"); + s_hSecDll = LoadLibrary(TEXT("security.dll")); else - s_hSecDll = LoadLibrary("secur32.dll"); + 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"); + pInitSecurityInterface = (INITSECURITYINTERFACE_FN) + GetProcAddress(s_hSecDll, SECURITYENTRYPOINT); if(!pInitSecurityInterface) return CURLE_FAILED_INIT; diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h index 4e7d4cfe6..c3e6d9760 100644 --- a/lib/curl_sspi.h +++ b/lib/curl_sspi.h @@ -46,7 +46,7 @@ void Curl_sspi_global_cleanup(void); /* Forward-declaration of global variables defined in curl_sspi.c */ extern HMODULE s_hSecDll; -extern PSecurityFunctionTableA s_pSecFn; +extern PSecurityFunctionTable s_pSecFn; /* Provide some definitions missing in old headers */ diff --git a/lib/getenv.c b/lib/getenv.c index 6b40dd68d..a2d69830e 100644 --- a/lib/getenv.c +++ b/lib/getenv.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -42,7 +42,7 @@ char *GetEnv(const char *variable) char *temp = getenv(variable); env[0] = '\0'; if(temp != NULL) - ExpandEnvironmentStrings(temp, env, sizeof(env)); + ExpandEnvironmentStringsA(temp, env, sizeof(env)); return (env[0] != '\0')?strdup(env):NULL; #else char *env = getenv(variable); diff --git a/lib/http_negotiate_sspi.c b/lib/http_negotiate_sspi.c index f1ab33d6d..ac197f6cf 100644 --- a/lib/http_negotiate_sspi.c +++ b/lib/http_negotiate_sspi.c @@ -33,6 +33,7 @@ #include "curl_base64.h" #include "http_negotiate.h" #include "curl_memory.h" +#include "curl_multibyte.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -90,7 +91,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, SecBuffer in_sec_buff; ULONG context_attributes; TimeStamp lifetime; - + LPTSTR sname; int ret; size_t len = 0, input_token_len = 0; bool gss = FALSE; @@ -137,7 +138,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, if(!neg_ctx->output_token) { PSecPkgInfo SecurityPackage; - ret = s_pSecFn->QuerySecurityPackageInfo((SEC_CHAR *)"Negotiate", + ret = s_pSecFn->QuerySecurityPackageInfo(TEXT("Negotiate"), &SecurityPackage); if(ret != SEC_E_OK) return -1; @@ -166,7 +167,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, return -1; neg_ctx->status = - s_pSecFn->AcquireCredentialsHandle(NULL, (SEC_CHAR *)"Negotiate", + s_pSecFn->AcquireCredentialsHandle(NULL, TEXT("Negotiate"), SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, neg_ctx->credentials, &lifetime); @@ -205,10 +206,18 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, in_sec_buff.pvBuffer = input_token; } +#ifdef UNICODE + sname = Curl_convert_UTF8_to_wchar(neg_ctx->server_name); + if(!wserver) + return CURLE_OUT_OF_MEMORY; +#else + sname = neg_ctx->server_name; +#endif + neg_ctx->status = s_pSecFn->InitializeSecurityContext( neg_ctx->credentials, input_token ? neg_ctx->context : 0, - neg_ctx->server_name, + sname, ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP, @@ -219,6 +228,10 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, &context_attributes, &lifetime); +#ifdef UNICODE + free(sname); +#endif + if(GSS_ERROR(neg_ctx->status)) return -1; diff --git a/lib/idn_win32.c b/lib/idn_win32.c index 70286c0fd..6351f791d 100644 --- a/lib/idn_win32.c +++ b/lib/idn_win32.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,7 +28,7 @@ #ifdef USE_WIN32_IDN -#include +#include "curl_multibyte.h" #ifdef WANT_IDN_PROTOTYPES WINBASEAPI int WINAPI IdnToAscii(DWORD, LPCWSTR, int, LPWSTR, int); @@ -37,57 +37,9 @@ WINBASEAPI int WINAPI IdnToUnicode(DWORD, LPCWSTR, int, LPWSTR, int); #define IDN_MAX_LENGTH 255 -static wchar_t *_curl_win32_UTF8_to_wchar(const char *str_utf8) -{ - wchar_t *str_w = NULL; - - if(str_utf8) { - int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, - str_utf8, -1, NULL, 0); - if(str_w_len) { - str_w = malloc(str_w_len * sizeof(wchar_t)); - if(str_w) { - if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, - str_w_len) == 0) { - free(str_w); - str_w = NULL; - } - } - } - } - - return str_w; -} - -static const char *_curl_win32_wchar_to_UTF8(const wchar_t *str_w) -{ - char *str_utf8 = NULL; - - if(str_w) { - size_t str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL, - 0, NULL, NULL); - if(str_utf8_len) { - str_utf8 = malloc(str_utf8_len * sizeof(wchar_t)); - if(str_utf8) { - if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len, - NULL, FALSE) == 0) { - (void) GetLastError(); - free((void *)str_utf8); - str_utf8 = NULL; - } - } - } - else { - (void) GetLastError(); - } - } - - return str_utf8; -} - int curl_win32_idn_to_ascii(const char *in, char **out) { - wchar_t *in_w = _curl_win32_UTF8_to_wchar(in); + wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); if(in_w) { wchar_t punycode[IDN_MAX_LENGTH]; if(IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH) == 0) { @@ -97,7 +49,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out) } free(in_w); - *out = (char *)_curl_win32_wchar_to_UTF8(punycode); + *out = (char *)Curl_convert_wchar_to_UTF8(punycode); if(!(*out)) { return 0; } @@ -115,7 +67,7 @@ int curl_win32_ascii_to_idn(const char *in, size_t in_len, char **out_utf8) return 0; } else { - const char *out_utf8 = _curl_win32_wchar_to_UTF8(unicode); + const char *out_utf8 = Curl_convert_wchar_to_UTF8(unicode); if(!out_utf8) { return 0; } diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index 61ef2f4a7..8bbaef101 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -32,6 +32,7 @@ #include "timeval.h" #include "socks.h" #include "curl_sspi.h" +#include "curl_multibyte.h" #include "warnless.h" #define _MPRINTF_REPLACE /* use the internal *printf() functions */ @@ -139,17 +140,17 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, cred_handle.dwLower = 0; cred_handle.dwUpper = 0; - status = s_pSecFn->AcquireCredentialsHandleA(NULL, - (char *)"Kerberos", - SECPKG_CRED_OUTBOUND, - NULL, - NULL, - NULL, - NULL, - &cred_handle, - &expiry); + status = s_pSecFn->AcquireCredentialsHandle(NULL, + TEXT("Kerberos"), + SECPKG_CRED_OUTBOUND, + NULL, + NULL, + NULL, + NULL, + &cred_handle, + &expiry); - if(check_sspi_err(conn, status, "AcquireCredentialsHandleA")) { + if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) { failf(data, "Failed to acquire credentials."); Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); @@ -159,22 +160,33 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, /* As long as we need to keep sending some context info, and there's no */ /* errors, keep sending it... */ for(;;) { + LPTSTR sname; +#ifdef UNICODE + sname = Curl_convert_UTF8_to_wchar(service_name); + if(!sname) + return CURLE_OUT_OF_MEMORY; +#else + sname = service_name; +#endif + status = s_pSecFn->InitializeSecurityContext(&cred_handle, + context_handle, + sname, + ISC_REQ_MUTUAL_AUTH | + ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_CONFIDENTIALITY | + ISC_REQ_REPLAY_DETECT, + 0, + SECURITY_NATIVE_DREP, + &input_desc, + 0, + &sspi_context, + &output_desc, + &sspi_ret_flags, + &expiry); - status = s_pSecFn->InitializeSecurityContextA(&cred_handle, - context_handle, - service_name, - ISC_REQ_MUTUAL_AUTH | - ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_CONFIDENTIALITY | - ISC_REQ_REPLAY_DETECT, - 0, - SECURITY_NATIVE_DREP, - &input_desc, - 0, - &sspi_context, - &output_desc, - &sspi_ret_flags, - &expiry); +#ifdef UNICODE + Curl_safefree(sname); +#endif if(sspi_recv_token.pvBuffer) { s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); @@ -182,7 +194,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, sspi_recv_token.cbBuffer = 0; } - if(check_sspi_err(conn, status, "InitializeSecurityContextA")) { + if(check_sspi_err(conn, status, "InitializeSecurityContext")) { Curl_safefree(service_name); s_pSecFn->FreeCredentialsHandle(&cred_handle); s_pSecFn->DeleteSecurityContext(&sspi_context); @@ -365,10 +377,10 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, memcpy(socksreq+2, &us_length, sizeof(short)); } else { - status = s_pSecFn->QueryContextAttributesA(&sspi_context, - SECPKG_ATTR_SIZES, - &sspi_sizes); - if(check_sspi_err(conn, status, "QueryContextAttributesA")) { + status = s_pSecFn->QueryContextAttributes(&sspi_context, + SECPKG_ATTR_SIZES, + &sspi_sizes); + if(check_sspi_err(conn, status, "QueryContextAttributes")) { s_pSecFn->DeleteSecurityContext(&sspi_context); failf(data, "Failed to query security context attributes."); return CURLE_COULDNT_CONNECT; diff --git a/lib/strerror.c b/lib/strerror.c index 84a900047..dd7d37565 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -635,7 +635,7 @@ const char *Curl_strerror(struct connectdata *conn, int err) strncpy(buf, strerror(err), max); else { if(!get_winsock_error(err, buf, max) && - !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, LANG_NEUTRAL, buf, (DWORD)max, NULL)) snprintf(buf, max, "Unknown error %d (%#x)", err, err); } @@ -788,7 +788,8 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) #ifndef CURL_DISABLE_VERBOSE_STRINGS char txtbuf[80]; char msgbuf[sizeof(conn->syserr_buf)]; - char *str, *msg = NULL; + char *p, *str, *msg = NULL; + bool msg_formatted = FALSE; int old_errno; #endif const char *txt; @@ -1057,11 +1058,29 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)", txt, (err >> 16) & 0xffff, err & 0xffff); txtbuf[sizeof(txtbuf)-1] = '\0'; - if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, LANG_NEUTRAL, - msgbuf, sizeof(msgbuf)-1, NULL)) { - char *p; + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) { + wcstombs(msgbuf,wbuf,sizeof(msgbuf)-1); + msg_formatted = TRUE; + } + } +#else + if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + msgbuf, sizeof(msgbuf)-1, NULL)) { + msg_formatted = TRUE; + } +#endif + if(msg_formatted) { msgbuf[sizeof(msgbuf)-1] = '\0'; /* strip trailing '\r\n' or '\n' */ if((p = strrchr(msgbuf,'\n')) != NULL && (p - msgbuf) >= 2) diff --git a/lib/telnet.c b/lib/telnet.c index 26fa3ac67..1c294e2ab 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -1341,7 +1341,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) /* OK, so we have WinSock 2.0. We need to dynamically */ /* load ws2_32.dll and get the function pointers we need. */ - wsock2 = LoadLibrary("WS2_32.DLL"); + wsock2 = LoadLibrary(TEXT("WS2_32.DLL")); if(wsock2 == NULL) { failf(data,"failed to load WS2_32.DLL (%d)", ERRNO); return CURLE_FAILED_INIT;