Skip to content

Commit

Permalink
SSPI related code: Unicode support for WinCE
Browse files Browse the repository at this point in the history
SSPI related code now compiles with ANSI and WCHAR versions of security
methods (WinCE requires WCHAR versions of methods).

Pulled UTF8 to WCHAR conversion methods out of idn_win32.c into their own file.

curl_sasl.c - include curl_memory.h to use correct memory functions.

getenv.c and telnet.c - WinCE compatibility fix

With some committer adjustments
  • Loading branch information
masali-hp authored and yangtse committed Jun 15, 2012
1 parent 16c725d commit 46480bb
Show file tree
Hide file tree
Showing 13 changed files with 307 additions and 138 deletions.
82 changes: 82 additions & 0 deletions lib/curl_multibyte.c
@@ -0,0 +1,82 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, 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)) */
40 changes: 40 additions & 0 deletions 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, <daniel@haxx.se>, 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 <tchar.h>

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 */
61 changes: 35 additions & 26 deletions lib/curl_ntlm_msgs.c
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down
1 change: 1 addition & 0 deletions lib/curl_sasl.c
Expand Up @@ -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 <curl/mprintf.h>
Expand Down
40 changes: 35 additions & 5 deletions lib/curl_schannel.c
Expand Up @@ -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 <curl/mprintf.h>

#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 46480bb

Please sign in to comment.