#define TAG CLIENT_TAG("windows")
-static int wf_create_console(void)
+static BOOL wf_create_console(void)
{
if (!AttachConsole(ATTACH_PARENT_PROCESS))
- return 1;
+ return FALSE;
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
+
WLog_INFO(TAG, "Debug console created.");
- return 0;
+
+ return TRUE;
}
static BOOL wf_end_paint(rdpContext* context)
return TRUE;
}
-static BOOL wf_post_disconnect(freerdp* instance)
+static void wf_post_disconnect(freerdp* instance)
{
wfContext* wfc;
if (!instance || !instance->context || !instance->settings)
- return FALSE;
+ return;
wfc = (wfContext*) instance->context;
free(wfc->window_title);
- return TRUE;
}
static CREDUI_INFOA wfUiInfo =
ZeroMemory(Password, sizeof(Password));
dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES;
status = CredUIPromptForCredentialsA(&wfUiInfo, title, NULL, 0,
- UserName, CREDUI_MAX_USERNAME_LENGTH + 1,
- Password, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
+ UserName, CREDUI_MAX_USERNAME_LENGTH + 1,
+ Password, CREDUI_MAX_PASSWORD_LENGTH + 1, &fSave, dwFlags);
if (status != NO_ERROR)
{
return wf_authenticate_raw(instance, tmp, username, password, domain);
}
-static DWORD wf_verify_certificate(freerdp* instance,
- const char* common_name,
- const char* subject,
- const char* issuer,
- const char* fingerprint,
- BOOL host_mismatch)
+static WCHAR* wf_format_text(const WCHAR* fmt, ...)
{
-#if 0
- DWORD mode;
- int read_size;
- DWORD read_count;
- TCHAR answer[2];
- TCHAR* read_buffer;
- HANDLE input_handle;
-#endif
- WLog_INFO(TAG, "Certificate details:");
- WLog_INFO(TAG, "\tCommonName: %s", common_name);
- WLog_INFO(TAG, "\tSubject: %s", subject);
- WLog_INFO(TAG, "\tIssuer: %s", issuer);
- WLog_INFO(TAG, "\tThumbprint: %s", fingerprint);
- WLog_INFO(TAG, "\tHostMismatch: %s", host_mismatch ? "Yes" : "No");
- WLog_INFO(TAG,
- "The above X.509 certificate could not be verified, possibly because you do not have "
- "the CA certificate in your certificate store, or the certificate has expired. "
- "Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
- /* TODO: ask for user validation */
-#if 0
- input_handle = GetStdHandle(STD_INPUT_HANDLE);
- GetConsoleMode(input_handle, &mode);
- mode |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT;
- SetConsoleMode(input_handle, mode);
-#endif
+ int rc;
+ size_t size = 1024;
+ WCHAR* buffer = calloc(size, sizeof(WCHAR));
+ if (!buffer)
+ return NULL;
+
+ do
+ {
+ WCHAR* tmp;
+ va_list ap;
+ va_start(ap, fmt);
+ rc = vswprintf_s(buffer, size, fmt, ap);
+ va_end(ap);
+ if (rc <= 0)
+ goto fail;
+
+ if ((size_t)rc < size)
+ return buffer;
+
+ size = (size_t)rc + 1;
+ tmp = realloc(buffer, size * sizeof(WCHAR));
+ if (!tmp)
+ goto fail;
+
+ buffer = tmp;
+ }
+ while(TRUE);
+
+fail:
+ free(buffer);
+ return NULL;
+}
+
+static DWORD wf_verify_certificate_ex(freerdp* instance,
+ const char* host,
+ UINT16 port,
+ const char* common_name,
+ const char* subject,
+ const char* issuer,
+ const char* fingerprint,
+ DWORD flags)
+{
+ WCHAR* buffer;
+ WCHAR* caption;
+ int what = IDCANCEL;
+
+ buffer = wf_format_text(L"Certificate details:\n"
+ L"\tCommonName: %S\n"
+ L"\tSubject: %S\n"
+ L"\tIssuer: %S\n"
+ L"\tThumbprint: %S\n"
+ L"\tHostMismatch: %S\n"
+ L"\n"
+ L"The above X.509 certificate could not be verified, possibly because you do not have "
+ L"the CA certificate in your certificate store, or the certificate has expired. "
+ L"Please look at the OpenSSL documentation on how to add a private CA to the store.\n"
+ L"\n"
+ L"YES\tAccept permanently\n"
+ L"NO\tAccept for this session only\n"
+ L"CANCEL\tAbort connection\n",
+ common_name, subject, issuer, fingerprint, flags & VERIFY_CERT_FLAG_MISMATCH ? "Yes" : "No");
+ caption = wf_format_text(L"Verify certificate for %S:%hu", host, port);
+
+ if (!buffer || !caption)
+ goto fail;
+
+ what = MessageBoxW(NULL, buffer, caption, MB_YESNOCANCEL);
+fail:
+ free(buffer);
+ free(caption);
+
/* return 1 to accept and store a certificate, 2 to accept
* a certificate only for this session, 0 otherwise */
- return 2;
+ switch(what)
+ {
+ case IDOK:
+ return 1;
+ case IDNO:
+ return 2;
+ default:
+ return 0;
+ }
}
-static DWORD wf_verify_changed_certificate(freerdp* instance,
- const char* common_name,
- const char* subject, const char* issuer,
- const char* fingerprint,
- const char* old_subject, const char* old_issuer,
- const char* old_fingerprint)
+static DWORD wf_verify_changed_certificate_ex(freerdp* instance,
+ const char* host,
+ UINT16 port,
+ const char* common_name,
+ const char* subject,
+ const char* issuer,
+ const char* new_fingerprint,
+ const char* old_subject,
+ const char* old_issuer,
+ const char* old_fingerprint,
+ DWORD flags)
{
- WLog_ERR(TAG, "!!! Certificate has changed !!!");
- WLog_ERR(TAG, "New Certificate details:");
- WLog_ERR(TAG, "\tSubject: %s", subject);
- WLog_ERR(TAG, "\tIssuer: %s", issuer);
- WLog_ERR(TAG, "\tThumbprint: %s", fingerprint);
- WLog_ERR(TAG, "Old Certificate details:");
- WLog_ERR(TAG, "\tSubject: %s", old_subject);
- WLog_ERR(TAG, "\tIssuer: %s", old_issuer);
- WLog_ERR(TAG, "\tThumbprint: %s", old_fingerprint);
- WLog_ERR(TAG,
- "The above X.509 certificate does not match the certificate used for previous connections. "
- "This may indicate that the certificate has been tampered with."
- "Please contact the administrator of the RDP server and clarify.");
- return 0;
+ WCHAR* buffer;
+ WCHAR* caption;
+ int what = IDCANCEL;
+
+ buffer = wf_format_text( L"New Certificate details:\n"
+ L"\tCommonName: %S\n"
+ L"\tSubject: %S\n"
+ L"\tIssuer: %S\n"
+ L"\tThumbprint: %S\n"
+ L"\tHostMismatch: %S\n"
+ L"\n"
+ L"Old Certificate details:\n"
+ L"\tSubject: %S\n"
+ L"\tIssuer: %S\n"
+ L"\tThumbprint: %S"
+ L"The above X.509 certificate could not be verified, possibly because you do not have "
+ L"the CA certificate in your certificate store, or the certificate has expired. "
+ L"Please look at the OpenSSL documentation on how to add a private CA to the store.\n"
+ L"\n"
+ L"YES\tAccept permanently\n"
+ L"NO\tAccept for this session only\n"
+ L"CANCEL\tAbort connection\n",
+ common_name, subject, issuer, new_fingerprint, flags & VERIFY_CERT_FLAG_MISMATCH ? "Yes" : "No",
+ old_subject, old_issuer, old_fingerprint);
+ caption = wf_format_text(L"Verify certificate change for %S:%hu", host, port);
+
+ if (!buffer || !caption)
+ goto fail;
+
+ what = MessageBoxW(NULL, buffer, caption, MB_YESNOCANCEL);
+fail:
+ free(buffer);
+ free(caption);
+
+ /* return 1 to accept and store a certificate, 2 to accept
+ * a certificate only for this session, 0 otherwise */
+ switch(what)
+ {
+ case IDOK:
+ return 1;
+ case IDNO:
+ return 2;
+ default:
+ return 0;
+ }
}
static DWORD WINAPI wf_input_thread(LPVOID arg)
WSAStartup(0x101, &wsaData);
- wf_create_console();
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
return TRUE;
}
static BOOL wfreerdp_client_new(freerdp* instance, rdpContext* context)
{
+ wfContext* wfc = (wfContext*)context;
+ if (!wfc)
+ return FALSE;
+
+ wfc->isConsole = wf_create_console();
+
if (!(wfreerdp_client_global_init()))
return FALSE;
instance->PostDisconnect = wf_post_disconnect;
instance->Authenticate = wf_authenticate;
instance->GatewayAuthenticate = wf_gw_authenticate;
- instance->VerifyCertificate = wf_verify_certificate;
- instance->VerifyChangedCertificate = wf_verify_changed_certificate;
+ instance->VerifyCertificateEx = wf_verify_certificate_ex;
+ instance->VerifyChangedCertificateEx = wf_verify_changed_certificate_ex;
+
return TRUE;
}