⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncclient.cpp

📁 这是一个比较复杂的远程控制工具,分为服务器与客户斋,让你了解socket编程的知识.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		// Send updates to the client - this implicitly clears
		// the supplied update tracker
		if (m_client->SendUpdate(update)) {
			updates_sent++;
			clipregion.clear();
		}

		yield();
	}

	vnclog.Print(LL_INTINFO, VNCLOG("stopping update thread\n"));
	
	vnclog.Print(LL_INTERR, "client sent %lu updates\n", updates_sent);
	return 0;
}

// vncClient thread class

class vncClientThread : public omni_thread
{
public:

	// Init
	virtual BOOL Init(vncClient *client,
		vncServer *server,
		VSocket *socket,
		BOOL auth,
		BOOL shared);

	// Sub-Init routines
	virtual BOOL InitVersion();
	virtual BOOL InitAuthenticate();

	// The main thread function
	virtual void run(void *arg);

protected:
	virtual ~vncClientThread();

	// Fields
protected:
	VSocket *m_socket;
	vncServer *m_server;
	vncClient *m_client;
	BOOL m_auth;
	BOOL m_shared;
	BOOL m_ms_logon;
};

vncClientThread::~vncClientThread()
{
	// If we have a client object then delete it
	if (m_client != NULL)
		delete m_client;
}

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;

	// Start the thread
	start();

	return TRUE;
}

BOOL
vncClientThread::InitVersion()
{
	rfbProtocolVersionMsg protocol_ver;
	protocol_ver[12] = 0;
	if (strcmp(m_client->ProtocolVersionMsg,"0.0.0.0")==NULL)
	{
		// 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 (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
	m_ms_logon = m_server->MSLogonRequired();
	vnclog.Print(LL_INTINFO, VNCLOG("m_ms_logon set to %s"), m_ms_logon ? "true" : "false");
	if (minor == 4 || minor == 6) m_client->SetUltraViewer(true); else m_client->SetUltraViewer(false); // sf@2005 - Fix Open TextChat from server bug 

	return TRUE;
}

BOOL
vncClientThread::InitAuthenticate()
{
	vnclog.Print(LL_INTINFO, "Entered InitAuthenticate");
	// Retrieve the local password
	char password[MAXPWLEN];
	char passwordMs[MAXMSPWLEN];
	m_server->GetPassword(password);
	vncPasswd::ToText plain(password);

	// Verify the peer host name against the AuthHosts string
	vncServer::AcceptQueryReject verified;
	if (m_auth) {
		verified = vncServer::aqrAccept;
	} else {
		verified = m_server->VerifyHost(m_socket->GetPeerName());
	}
	
	// If necessary, query the connection with a timed dialog
	char username[UNLEN+1];
	if (!vncService::CurrentUser(username, sizeof(username))) return false;
	if (strcmp(username, "") != 0)
		if (verified == vncServer::aqrQuery) {
			vncAcceptDialog *acceptDlg = new vncAcceptDialog(m_server->QueryTimeout(),m_server->QueryAccept(), m_socket->GetPeerName());
	
			if (acceptDlg == NULL) 
				{
					if (m_server->QueryAccept()==1) 
					{
						verified = vncServer::aqrAccept;
					}
					else 
					{
						verified = vncServer::aqrReject;
					}
				}
			else 
				{
					if ( !(acceptDlg->DoDialog()) ) verified = vncServer::aqrReject;
				}
		}

	if (verified == vncServer::aqrReject) {
		CARD32 auth_val = Swap32IfLE(rfbConnFailed);
		char *errmsg = "Your connection has been 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!
	if ((strlen(plain) == 0) && m_server->AuthRequired())
	{
		vnclog.Print(LL_CONNERR, VNCLOG("no password specified for server - client rejected\n"));

		// 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 (localname != NULL)
				free(localname);

			if (remotename != NULL)
				free(remotename);

			if (!ok)
			{
				vnclog.Print(LL_CONNERR, VNCLOG("loopback connection attempted - client rejected\n"));
				
				// 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));

				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;
			}
		}
	}
	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 (localname != NULL)
				free(localname);

			if (remotename != NULL)
				free(remotename);

			if (!ok)
			{
				vnclog.Print(LL_CONNERR, VNCLOG("loopback connection attempted - client accepted\n"));
				m_client->m_IsLoopback=true;
			}
		}

	}

	// Authenticate the connection, if required
	if (m_auth || (strlen(plain) == 0))
	{
		// 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 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, "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, "No user specified, mslogon not required");
					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 
				{
					vnclog.Print(LL_INTINFO, "User specified or mslogon required");
					int result=CheckUserGroupPasswordUni(user,plainmsPasswd,m_client->GetClientName());
					vnclog.Print(LL_INTINFO, "CheckUserGroupPasswordUni result=%i", result);
					if (result==0) auth_ok = FALSE;
					if (result==2)
					{
						m_client->EnableKeyboard(false);
						m_client->EnablePointer(false);
					}
				}
				if (plainmsPasswd) free(plainmsPasswd);
				plainmsPasswd=NULL;
			}
			else
			{
				vnclog.Print(LL_INTINFO, "password authentication");
				if (!m_socket->SendExact(challenge, sizeof(challenge)))
					return FALSE;


				// Read the response
				if (!m_socket->ReadExact(response, sizeof(response)))
					return FALSE;
				// Encrypt the challenge bytes
				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;
					}
				}
			}
		}

		// Did the authentication work?
		CARD32 authmsg;
		if (!auth_ok)
		{
			vnclog.Print(LL_CONNERR, VNCLOG("authentication failed\n"));
			//////////////////
			// LOG it also in the event
			//////////////////
			{
				typedef BOOL (*LogeventFn)(char *machine);
				LogeventFn Logevent = 0;
				char szCurrentDir[MAX_PATH];
				if (GetModuleFileName(NULL, szCurrentDir, MAX_PATH))
					{
						char* p = strrchr(szCurrentDir, '\\');
						*p = '\0';
						strcat (szCurrentDir,"\\logging.dll");
					}
				HMODULE hModule = LoadLibrary(szCurrentDir);
				if (hModule)
					{
						BOOL result=false;
						Logevent = (LogeventFn) GetProcAddress( hModule, "LOGFAILED" );
						Logevent((char *)m_client->GetClientName());
						FreeLibrary(hModule);
					}
			}

			authmsg = Swap32IfLE(rfbVncAuthFailed);
			m_socket->SendExact((char *)&authmsg, sizeof(authmsg));
			return FALSE;
		}
		else
		{
			// Tell the client we're ok
			authmsg = Swap32IfLE(rfbVncAuthOK);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -