Skip to content

Commit 2ffb651

Browse files
committed
Stubbing out winrt password encryption.
1 parent 6d7dd5c commit 2ffb651

File tree

5 files changed

+91
-46
lines changed

5 files changed

+91
-46
lines changed

Release/include/cpprest/web_utilities.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,30 @@ namespace web
3535

3636
namespace http { namespace client { namespace details {
3737
class winhttp_client;
38+
class winrt_client;
3839
}}}
40+
namespace experimental { namespace websockets { namespace client { namespace details {
41+
class winrt_client;
42+
}}}}
3943

4044
namespace details
4145
{
42-
#if defined(_MS_WINDOWS) && !defined(__cplusplus_winrt)
46+
#if defined(_MS_WINDOWS)
4347
class zero_memory_deleter
4448
{
4549
public:
4650
_ASYNCRTIMP void operator()(::utility::string_t *data) const;
4751
};
4852
typedef std::unique_ptr<std::wstring, zero_memory_deleter> password_string;
49-
53+
#if defined(__cplusplus_winrt)
54+
class winrt_encryption
55+
{
56+
public:
57+
winrt_encryption() {}
58+
_ASYNCRTIMP winrt_encryption(const std::wstring &data);
59+
_ASYNCRTIMP password_string decrypt() const;
60+
};
61+
#else
5062
class win32_encryption
5163
{
5264
public:
@@ -59,6 +71,7 @@ class win32_encryption
5971
size_t m_numCharacters;
6072
};
6173
#endif
74+
#endif
6275
}
6376

6477
/// <summary>
@@ -96,10 +109,10 @@ class credentials
96109
CASABLANCA_DEPRECATED("This API is deprecated for security reasons to avoid unnecessary password copies stored in plaintext.")
97110
utility::string_t password() const
98111
{
99-
#if defined(_MS_WINDOWS) && !defined(__cplusplus_winrt)
112+
#if defined(_MS_WINDOWS)
100113
return utility::string_t(*m_password.decrypt());
101114
#else
102-
return m_password;
115+
throw std::runtime_error("Credentials are not supported on this platform yet.");
103116
#endif
104117
}
105118

@@ -111,19 +124,23 @@ class credentials
111124

112125
private:
113126
friend class http::client::details::winhttp_client;
127+
friend class http::client::details::winrt_client;
128+
friend class experimental::websockets::client::details::winrt_client;
114129

115-
#if defined(_MS_WINDOWS) && !defined(__cplusplus_winrt)
130+
#if defined(_MS_WINDOWS)
116131
details::password_string decrypt() const
117132
{
118133
return m_password.decrypt();
119134
}
120135
#endif
121136

122137
::utility::string_t m_username;
123-
#if defined(_MS_WINDOWS) && !defined(__cplusplus_winrt)
124-
::web::details::win32_encryption m_password;
138+
#if defined(_MS_WINDOWS)
139+
#if defined(__cplusplus_winrt)
140+
details::winrt_encryption m_password;
125141
#else
126-
::utility::string_t m_password;
142+
details::win32_encryption m_password;
143+
#endif
127144
#endif
128145
};
129146

Release/src/http/client/http_win7.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -923,16 +923,20 @@ class winhttp_client : public _http_client_communicator
923923
{
924924
return false;
925925
}
926-
auto password = cred.decrypt();
927-
if (!WinHttpSetCredentials(
928-
hRequestHandle,
929-
dwAuthTarget,
930-
dwSelectedScheme,
931-
cred.username().c_str(),
932-
password->c_str(),
933-
nullptr))
926+
927+
// New scope to ensure plaintext password is cleared as soon as possible.
934928
{
935-
return false;
929+
auto password = cred.decrypt();
930+
if (!WinHttpSetCredentials(
931+
hRequestHandle,
932+
dwAuthTarget,
933+
dwSelectedScheme,
934+
cred.username().c_str(),
935+
password->c_str(),
936+
nullptr))
937+
{
938+
return false;
939+
}
936940
}
937941
}
938942

Release/src/http/client/http_win8.cpp

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ class winrt_client : public _http_client_communicator
355355
return;
356356
}
357357

358-
if ( msg.method() == http::methods::TRCE )
358+
if (msg.method() == http::methods::TRCE)
359359
{
360360
// Not supported by WinInet. Generate a more specific exception than what WinInet does.
361361
request->report_exception(http_exception(L"TRACE is not supported"));
@@ -377,7 +377,7 @@ class winrt_client : public _http_client_communicator
377377
CLSCTX_INPROC,
378378
__uuidof(IXMLHTTPRequest2),
379379
reinterpret_cast<void**>(winrt_context->m_hRequest.GetAddressOf()));
380-
if ( FAILED(hr) )
380+
if (FAILED(hr))
381381
{
382382
request->report_error(hr, L"Failure to create IXMLHTTPRequest2 instance");
383383
return;
@@ -395,35 +395,40 @@ class winrt_client : public _http_client_communicator
395395
return;
396396
}
397397

398-
utility::string_t username, password, proxy_username, proxy_password;
399-
if (client_cred.is_set())
400-
{
401-
username = client_cred.username();
402-
password = client_cred.password();
403-
}
404-
if (proxy_cred.is_set())
398+
// New scope to ensure plaintext password is cleared as soon as possible.
405399
{
406-
proxy_username = proxy_cred.username();
407-
proxy_password = proxy_cred.password();
408-
}
400+
utility::string_t username, proxy_username;
401+
::web::details::password_string password, proxy_password;
409402

410-
hr = winrt_context->m_hRequest->Open(
411-
msg.method().c_str(),
412-
encoded_resource.c_str(),
413-
Make<HttpRequestCallback>(winrt_context).Get(),
414-
username.c_str(),
415-
password.c_str(),
416-
proxy_username.c_str(),
417-
proxy_password.c_str());
418-
if (FAILED(hr))
403+
if (client_cred.is_set())
404+
{
405+
username = client_cred.username();
406+
password = client_cred.decrypt();
407+
}
408+
if (proxy_cred.is_set())
409+
{
410+
proxy_username = proxy_cred.username();
411+
proxy_password = proxy_cred.decrypt();
412+
}
413+
414+
hr = winrt_context->m_hRequest->Open(
415+
msg.method().c_str(),
416+
encoded_resource.c_str(),
417+
Make<HttpRequestCallback>(winrt_context).Get(),
418+
username.c_str(),
419+
password->c_str(),
420+
proxy_username.c_str(),
421+
proxy_password->c_str());
422+
}
423+
if (FAILED(hr))
419424
{
420425
request->report_error(hr, L"Failure to open HTTP request");
421426
return;
422427
}
423428

424429
// Suppress automatic prompts for user credentials, since they are already provided.
425430
hr = winrt_context->m_hRequest->SetProperty(XHR_PROP_NO_CRED_PROMPT, TRUE);
426-
if(FAILED(hr))
431+
if (FAILED(hr))
427432
{
428433
request->report_error(hr, L"Failure to set no credentials prompt property");
429434
return;

Release/src/utilities/web_utilities.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,30 @@ namespace web
3535
{
3636
namespace details
3737
{
38-
#if defined(_MS_WINDOWS) && !defined(__cplusplus_winrt)
38+
#if defined(_MS_WINDOWS)
3939
void zero_memory_deleter::operator()(::utility::string_t *data) const
4040
{
41+
#if defined(__cplusplus_winrt)
4142
SecureZeroMemory(reinterpret_cast<void *>(const_cast<::utility::string_t::value_type *>(data->data())), data->size());
43+
#else
44+
// TODO
45+
#endif
4246
delete data;
4347
}
4448

49+
#if defined(__cplusplus_winrt)
50+
winrt_encryption::winrt_encryption(const std::wstring &data)
51+
{
52+
// TODO
53+
}
54+
55+
password_string winrt_encryption::decrypt() const
56+
{
57+
auto data = password_string(new std::wstring());
58+
// TODO
59+
return std::move(data);
60+
}
61+
#else
4562
win32_encryption::win32_encryption(const std::wstring &data) :
4663
m_numCharacters(data.size())
4764
{
@@ -81,6 +98,7 @@ password_string win32_encryption::decrypt() const
8198
return std::move(data);
8299
}
83100
#endif
101+
#endif
84102
}
85103

86104
}

Release/src/websockets/client/ws_winrt.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,10 @@ class winrt_client : public _websocket_client_impl, public std::enable_shared_fr
105105

106106
if (m_config.credentials().is_set())
107107
{
108+
auto password = m_config.credentials().decrypt();
108109
m_msg_websocket->Control->ServerCredential = ref new Windows::Security::Credentials::PasswordCredential("WebSocketClientCredentialResource",
109110
Platform::StringReference(m_config.credentials().username().c_str()),
110-
Platform::StringReference(m_config.credentials().password().c_str()));
111+
Platform::StringReference(password->c_str()));
111112
}
112113

113114
m_context = ref new ReceiveContext([=](websocket_incoming_message &msg)
@@ -178,12 +179,13 @@ class winrt_client : public _websocket_client_impl, public std::enable_shared_fr
178179
const auto &proxy_cred = proxy.credentials();
179180
if(proxy_cred.is_set())
180181
{
182+
auto password = proxy_cred.decrypt();
181183
m_msg_websocket->Control->ProxyCredential = ref new Windows::Security::Credentials::PasswordCredential("WebSocketClientProxyCredentialResource",
182-
ref new Platform::String(proxy_cred.username().c_str()),
183-
ref new Platform::String(proxy_cred.password().c_str()));
184+
Platform::StringReference(proxy_cred.username().c_str()),
185+
Platform::StringReference(password->c_str()));
184186
}
185187

186-
const auto uri = ref new Windows::Foundation::Uri(ref new Platform::String(m_uri.to_string().c_str()));
188+
const auto uri = ref new Windows::Foundation::Uri(Platform::StringReference(m_uri.to_string().c_str()));
187189

188190
m_msg_websocket->MessageReceived += ref new TypedEventHandler<MessageWebSocket^, MessageWebSocketMessageReceivedEventArgs^>(m_context, &ReceiveContext::OnReceive);
189191
m_msg_websocket->Closed += ref new TypedEventHandler<IWebSocket^, WebSocketClosedEventArgs^>(m_context, &ReceiveContext::OnClosed);
@@ -415,8 +417,7 @@ class winrt_client : public _websocket_client_impl, public std::enable_shared_fr
415417
pplx::task<void> close(websocket_close_status status, const utility::string_t &strreason=_XPLATSTR(""))
416418
{
417419
// Send a close frame to the server
418-
Platform::String^ reason = ref new Platform::String(strreason.data());
419-
m_msg_websocket->Close(static_cast<unsigned short>(status), reason);
420+
m_msg_websocket->Close(static_cast<unsigned short>(status), Platform::StringReference(strreason.c_str()));
420421
// Wait for the close response frame from the server.
421422
return pplx::create_task(m_close_tce);
422423
}

0 commit comments

Comments
 (0)