📄 vncclient.cpp
字号:
// Update the client palette if necessary
if (send_palette) {
m_client->SendPalette();
}
// Send updates to the client - this implicitly clears
// the supplied update tracker
if (m_client->SendUpdate(update)) {
updates_sent++;
clipregion.clear();
}
yield();
if (!m_active)
break;
//Pushprotokoll
if (m_client->m_thread && m_client->m_thread->m_autopush) // Ab 1.85 Pushprotokoll
{
rfb::Rect update;
update.tl.x = (m_client->m_SWOffsetx) * m_client->m_nScale;
update.tl.y = (m_client->m_SWOffsety) * m_client->m_nScale;
update.br.x = m_client->m_ScaledScreen.br.x - m_client->m_ScaledScreen.tl.x;
update.br.y = m_client->m_ScaledScreen.br.y - m_client->m_ScaledScreen.tl.y;
rfb::Region2D update_rgn = update;
//omni_mutex_lock l(m_client->GetUpdateLock());
m_client->m_incr_rgn = m_client->m_incr_rgn.union_(update_rgn);
m_client->m_encodemgr.m_buffer->m_desktop->TriggerUpdate();
m_client->TriggerUpdateThread();
}
if(m_client->m_encodemgr.m_buffer &&
m_client->m_encodemgr.m_buffer->m_desktop &&
m_client->m_encodemgr.m_buffer->m_desktop->m_stop_input_while_sw)
m_client->m_encodemgr.m_buffer->m_desktop->m_stop_input_while_sw = false;
}
#ifndef _DEBUG
}
catch(...)
{
vnclog.Print(LL_INTERR, VNCLOG("ClientUpdateThread.CATCH"));
}
#endif
vnclog.Print(LL_INTINFO, VNCLOG("stopping update thread"));
vnclog.Print(LL_INTERR, VNCLOG("client sent %lu updates"), updates_sent);
return 0;
}
vncClientThread::~vncClientThread()
{
// If we have a client object then delete it
if (m_client != NULL)
delete m_client;
if (m_tvinfo != NULL)
delete m_tvinfo;
}
BOOL
vncClientThread::Init(vncClient *client, vncServer *server, VSocket *socket, BOOL auth, BOOL shared)
{
// Save the server pointer and window handle
m_server = server;
m_socket = socket;
m_client = client;
m_auth = auth;
m_shared = shared;
m_autopush = false;
m_tvinfo = new TeamviewerInfo(TI_VNCCLIENT, this);
// Start the thread
start();
return TRUE;
}
BOOL
vncClientThread::InitConnectionMode()
{
rfbModeChangeMsg mcm;
if (!m_socket->ReadExact((char *)&mcm, sz_rfbModeChangeMsg))
return false;
if ( !(mcm.newmode & rfbMC_Servermodes))
{
// a client connection was requested, so directly switch to client mode
VNCviewerApp32 *app = VNCviewerApp32::Instance();
// connect with existing socket
app->NewConnection((SOCKET)m_socket->sock,mcm.newmode);
// Keep the socket
m_client->keepSocket=TRUE;
return false;
}
else
{
// set server mode
m_client->SetActiveMode(mcm.newmode);
// some special settings for different modes
switch (mcm.newmode)
{
case rfbMC_PresentationServer:
m_client->EnablePointer(FALSE);
m_client->EnableKeyboard(FALSE);
break;
}
return true;
}
}
BOOL
vncClientThread::InitVersion()
{
rfbProtocolVersionMsg protocol_ver;
protocol_ver[12] = 0;
if (strcmp(m_client->ProtocolVersionMsg,"0.0.0.0") == 0)
{
// Generate the server's protocol version
rfbProtocolVersionMsg protocolMsg;
sprintf((char *)protocolMsg,
rfbProtocolVersionFormat,
rfbProtocolMajorVersion,
rfbProtocolMinorVersion + (m_server->MSLogonRequired() ? 0 : 2)); // 4: mslogon+FT,
// 6: VNClogon+FT
// Send the protocol message
m_socket->SetTimeout(0);
if (!m_socket->SendExact((char *)&protocolMsg, sz_rfbProtocolVersionMsg))
return FALSE;
// Now, get the client's protocol version
if (!m_socket->ReadExact((char *)&protocol_ver, sz_rfbProtocolVersionMsg))
{
return FALSE;
}
}
else memcpy(protocol_ver,m_client->ProtocolVersionMsg,sz_rfbProtocolVersionMsg);
// Check viewer's the protocol version
int major, minor;
sscanf((char *)&protocol_ver, rfbProtocolVersionFormat, &major, &minor);
if (strncmp (protocol_ver,"TV ",3)==0) //TeamViewer 3
{
PostMessage(menu->GetHWND(),WM_REQUEST_UPDATE_TEAMVIEWER,0,0);
//throw QuietException("Connection failed - incompatible TeamViewer version!\r\n");
return FALSE;
}
if (major != rfbProtocolMajorVersion)
return FALSE;
// TODO: Maybe change this UltraVNC specific minor value because
// TightVNC viewer uses minor = 5 ...
// For now:
// UltraViewer always sends minor = 4 (sf@2005: or 6, as it returns the minor version received from the server)
// UltraServer sends minor = 4 or minor = 6
// m_ms_logon = false; // For all non-UltraVNC logon compatible viewers
//TR@2004: roVNC client=14, server=14 or 16
m_ms_logon = m_server->MSLogonRequired();
if ((minor == 4) || (minor == 6) || (minor == 14) || (minor == 16) || (minor%200 == 34) || (minor%200 == 36))
m_client->SetUltraViewer(true);
else
m_client->SetUltraViewer(false);
// Old TeamViewers aren't accepted any more
if ((minor == rfbProtocolMinorVersion) || (minor == rfbProtocolMinorVersion+2))
{
m_client->m_ClientKnowsModeChange = true;
m_tvinfo->partnerIsTeamviewer = true;
}
vnclog.Print(LL_INTINFO, VNCLOG("m_ms_logon set to %s"), m_ms_logon ? "true" : "false");
return TRUE;
}
BOOL
vncClientThread::InitAuthenticate()
{
vnclog.Print(LL_INTINFO, VNCLOG("Entered InitAuthenticate"));
// Retrieve the local password
char password[MAXPWLEN];
char passwordMs[MAXMSPWLEN];
m_server->GetPassword(password);
string plain;
if(strlen(SessionDialog::quickSupportPassword) > 0)
{
plain = string(SessionDialog::quickSupportPassword);
}
else
if(m_server->GetServerMode())
{
vncPasswd::ToText vncPassword(password);
plain=vncPassword;
}
else
{
plain=m_server->SessionPassword();
}
vncServer::AcceptQueryReject verified=vncServer::aqrAccept;
// If necessary, query the connection with a timed dialog
char username[UNLEN+1];
if (!vncService::CurrentUser(username, sizeof(username))) return false;
// Staudenmeyer@2005:
//if(m_server->GetIncomingConnections()==ConnectionViewerOpened && !sessionDialogShown)
//{
// return false;
//}
if (strcmp(username, "") != 0)
if (verified == vncServer::aqrQuery) {
vncAcceptDialog *acceptDlg = new vncAcceptDialog(m_client, m_server->QueryTimeout(),m_server->QueryAccept(), m_socket->GetPeerName());
if (acceptDlg == NULL)
{
if (m_server->QueryAccept()==1)
{
verified = vncServer::aqrAccept;
}
else
{
// No end dialog if Accept = no
verified = vncServer::aqrReject;
}
}
else
{
if ( !(acceptDlg->DoDialog()) ) verified = vncServer::aqrReject;
}
}
if (verified == vncServer::aqrReject) {
CARD32 auth_val = Swap32IfLE(rfbConnFailed);
char *errmsg = sz_IDS_CONNECTION_REJECTED;
CARD32 errlen = Swap32IfLE(strlen(errmsg));
if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
return FALSE;
if (!m_socket->SendExact((char *)&errlen, sizeof(errlen)))
return FALSE;
m_socket->SendExact(errmsg, strlen(errmsg));
return FALSE;
}
// By default we disallow passwordless workstations
// TR@2004: We require either password or query window
if ((plain.length() == 0) && m_server->AuthRequired() && m_server->QuerySetting()!=4)
{
vnclog.Print(LL_CONNERR, VNCLOG("no password specified for server - client rejected"));
// Send an error message to the client
CARD32 auth_val = Swap32IfLE(rfbConnFailed);
char *errmsg =
"This server does not have a valid password enabled. "
"Until a password is set, incoming connections cannot be accepted.";
CARD32 errlen = Swap32IfLE(strlen(errmsg));
if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
return FALSE;
if (!m_socket->SendExact((char *)&errlen, sizeof(errlen)))
return FALSE;
m_socket->SendExact(errmsg, strlen(errmsg));
return FALSE;
}
// By default we filter out local loop connections, because they're pointless
if (!m_server->LoopbackOk())
{
char *localname = strdup(m_socket->GetSockName());
char *remotename = strdup(m_socket->GetPeerName());
// Check that the local & remote names are different!
if ((localname != NULL) && (remotename != NULL))
{
BOOL ok = strcmp(localname, remotename) != 0;
if (!ok)
{
vnclog.Print(LL_CONNERR, VNCLOG("loopback connection attempted - client rejected"));
// Send an error message to the client
CARD32 auth_val = Swap32IfLE(rfbConnFailed);
char *errmsg = "Local loop-back connections are disabled.";
CARD32 errlen = Swap32IfLE(strlen(errmsg));
m_socket->SendExact((char *)&auth_val, sizeof(auth_val));
m_socket->SendExact((char *)&errlen, sizeof(errlen));
m_socket->SendExact(errmsg, strlen(errmsg));
if (localname != NULL)
free(localname);
if (remotename != NULL)
free(remotename);
return FALSE;
}
}
if (localname != NULL)
free(localname);
if (remotename != NULL)
free(remotename);
}
else
{
char *localname = strdup(m_socket->GetSockName());
char *remotename = strdup(m_socket->GetPeerName());
// Check that the local & remote names are different!
if ((localname != NULL) && (remotename != NULL))
{
BOOL ok = strcmp(localname, remotename) != 0;
if (!ok)
{
vnclog.Print(LL_CONNERR, VNCLOG("loopback connection attempted - client accepted"));
m_client->m_IsLoopback=true;
}
}
if (localname != NULL)
free(localname);
if (remotename != NULL)
free(remotename);
}
// Authenticate the connection, if required
if (m_auth || (plain.length() == 0))// || !m_server->GetServerMode())
{
// Send no-auth-required message
CARD32 auth_val = Swap32IfLE(rfbNoAuth);
if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
return FALSE;
}
else
{
// Send auth-required message
CARD32 auth_val = Swap32IfLE(rfbVncAuth);
if (!m_socket->SendExact((char *)&auth_val, sizeof(auth_val)))
return FALSE;
BOOL auth_ok = TRUE;
{
/*
// sf@2002 - DSMPlugin
// Use Plugin only from this point for the moment
if (m_server->GetDSMPluginPointer()->IsEnabled())
{
m_socket->EnableUsePlugin(true);
// TODO: Make a more secured challenge (with time stamp)
}
*/
// Now create a 16-byte challenge
char challenge[16];
char challenge2[16];
char challengems[64];
char response[16];
char responsems[64];
char *plainmsPasswd;
char user[256];
char domain[256];
vncRandomBytes((BYTE *)&challenge);
vncRandomBytesMs((BYTE *)&challengems);
// Send the challenge to the client
// m_ms_logon = false;
if (m_ms_logon)
{
vnclog.Print(LL_INTINFO, VNCLOG("MS-Logon authentication"));
if (!m_socket->SendExact(challengems, sizeof(challengems)))
return FALSE;
if (!m_socket->SendExact(challenge, sizeof(challenge)))
return FALSE;
if (!m_socket->ReadExact(user, sizeof(char)*256))
return FALSE;
if (!m_socket->ReadExact(domain, sizeof(char)*256))
return FALSE;
// Read the response
if (!m_socket->ReadExact(responsems, sizeof(responsems)))
return FALSE;
if (!m_socket->ReadExact(response, sizeof(response)))
return FALSE;
// TODO: Improve this...
for (int i = 0; i < 32 ;i++)
{
passwordMs[i] = challengems[i]^responsems[i];
}
// REM: Instead of the fixedkey, we could use VNC password
// -> the user needs to enter the VNC password on viewer's side.
plainmsPasswd = vncDecryptPasswdMs((char *)passwordMs);
// We let it as is right now for testing purpose.
if (strlen(user) == 0 && !m_server->MSLogonRequired())
{
vnclog.Print(LL_INTINFO, VNCLOG("No user specified, mslogon not required"));
vncEncryptBytes((BYTE *)&challenge, plain.c_str());
//vncEncryptBytes((BYTE *)&challenge, plain);
// Compare them to the response
for (int i=0; i<sizeof(challenge); i++)
{
if (challenge[i] != response[i])
{
auth_ok = FALSE;
break;
}
}
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -