0

I'm trying to implement an SSL handshake in C++ x64 unicode in Windows using winsock, schannel, security etc. Example host is google.com.

I created a SOCKET and could connect via WSAConnectByNameW.

I'm setting my SCHANNEL parameters as followed:

SCHANNEL_CRED *cred = new SCHANNEL_CRED;
cred->dwVersion = SCHANNEL_CRED_VERSION;
cred->dwFlags = SCH_USE_STRONG_CRYPTO | SCH_CRED_AUTO_CRED_VALIDATION| SCH_CRED_NO_DEFAULT_CREDS;
cred->grbitEnabledProtocols = SP_PROT_TLS1_2;

I want to get the handle using AcquireCredentialsHandleW (passing UNISP_NAME):

SECURITY_STATUS secstatus = AcquireCredentialsHandleW(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &handle, NULL);

Which fails for some reason due to incompatible data types:

""const wchar_t *"" --> ""LPWSTR""

Btw. Handle is just a CredHandle here.

I'm using unicode so I thought I could use UNISP_NAME since it's a 0 terminated string. I tried converting the string into an LPWSTR. Which is just an pointer to a 0 terminated string, right?

std::wstring service = L"Microsoft Unified Security Protocol Provider";
LPWSTR servicePtr = &service[0];

And pass it to the function:

SECURITY_STATUS secstatus = AcquireCredentialsHandleW(NULL, servicePtr, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &handle, NULL);

But it doesn't seem to work. I don't get it. What's my problem here? Why can't I get the handle? Why does the function (AcquireCredentialsHandleW) does not accept its own pre-coded parameters even in the correct encoding?

Thanks in advance.

PS.: I want to try it without openssl or curl as far as I can make it ^^

Tried switching to multibyte. Same problem but not for wchar but chars. Tried converting the string to a pointer tried switching schannel parameter with differently encoded parameter.

0x38
  • 11
  • 6

1 Answers1

0

The second parameter of AcquireCredentialsHandle() expects a pointer to a non-const string (why non-const? who knows).

UNISP_NAME is just a #define for a string literal:

#define UNISP_NAME_A    "Microsoft Unified Security Protocol Provider"
#define UNISP_NAME_W    L"Microsoft Unified Security Protocol Provider"

#ifdef UNICODE

#define UNISP_NAME  UNISP_NAME_W
...

#else

#define UNISP_NAME  UNISP_NAME_A
...

#endif

In C++, a string literal is a const string (in this case, a const wchar_t[], which decays into a const wchar_t*).

So, you will have to cast away the const in C++, eg:

AcquireCredentialsHandleW(..., const_cast<LPWSTR>(UNISP_NAME), ...);

Alternatively, you can use a string literal to initialize a non-const character buffer, eg:

WCHAR szPackage[] = UNISP_NAME;
AcquireCredentialsHandleW(..., szPackage, ...);

Your wstring::operator[] approach should work fine in C++11 and later, where the internal memory buffer of std::wstring is guaranteed to be null-terminated, eg:

std::wstring package = UNISP_NAME_W;
AcquireCredentialsHandleW(..., &package[0], ...);

Or, you can cast away the const from the pointer returned by wstring::c_str(), eg:

std::wstring package = UNISP_NAME_W;
AcquireCredentialsHandleW(..., const_cast<LPWSTR>(package.c_str()), ...);

Or, in C++17 and later, wstring::data() has an overload to return a non-const pointer, eg:

std::wstring package = UNISP_NAME_W;
AcquireCredentialsHandleW(..., package.data(), ...);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you very much for your answer. I've checked and you're right. The pointer isn't the problem at all. Theres something wrong with my SCHANNEL_CRED. I can NULL that parameter and it works perfectly and let's me retrieve infos from the server to start the ssl handshake, but I can't add any paramters with SCHANNEL_CRED at the moment. – 0x38 May 25 '23 at 07:38
  • @0x38 the [`AcquireCredentialsHandle()` documentation](https://learn.microsoft.com/en-us/windows/win32/secauthn/acquirecredentialshandle--schannel) says to use [`SCH_CREDENTIALS`](https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-sch_credentials), not `SCHANNEL_CRED`. Even the [`SCHANNEL_CRED` documentation](https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-schannel_cred) says so. – Remy Lebeau May 25 '23 at 08:03