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

📄 clientconnection.cpp

📁 tightvnc源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    WriteExact(pv, sz_rfbProtocolVersionMsg);

	if (m_connDlg != NULL)
		m_connDlg->SetStatus("Protocol version negotiated");

	vnclog.Print(0, _T("Connected to RFB server, using protocol version 3.%d\n"),
				 m_minorVersion);
}

//
// Negotiate authentication scheme and authenticate if necessary
//

void ClientConnection::PerformAuthentication()
{
	int secType;
	if (m_minorVersion >= 7) {
		secType = SelectSecurityType();
	} else {
		secType = ReadSecurityType();
	}

	switch (secType) {
    case rfbSecTypeNone:
		Authenticate(rfbAuthNone);
		m_authScheme = rfbAuthNone;
		break;
    case rfbSecTypeVncAuth:
		Authenticate(rfbAuthVNC);
		m_authScheme = rfbAuthVNC;
		break;
    case rfbSecTypeTight:
		m_tightVncProtocol = true;
		InitCapabilities();
		SetupTunneling();
		PerformAuthenticationTight();
		break;
	default:	// should never happen
		vnclog.Print(0, _T("Internal error: Invalid security type\n"));
		throw ErrorException("Internal error: Invalid security type");
    }
}

//
// Read security type from the server (protocol 3.3)
//

int ClientConnection::ReadSecurityType()
{
	// Read the authentication scheme.
	CARD32 secType;
	ReadExact((char *)&secType, sizeof(secType));
	secType = Swap32IfLE(secType);

    if (secType == rfbSecTypeInvalid)
		throw WarningException(ReadFailureReason());

	if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) {
		vnclog.Print(0, _T("Unknown security type from RFB server: %d\n"),
					 (int)secType);
		throw ErrorException("Unknown security type requested!");
    }

	if (m_connDlg != NULL)
		m_connDlg->SetStatus("Security type received");

	return (int)secType;
}

//
// Select security type from the server's list (protocol 3.7 and above)
//

int ClientConnection::SelectSecurityType()
{
	// Read the list of secutiry types.
	CARD8 nSecTypes;
	ReadExact((char *)&nSecTypes, sizeof(nSecTypes));
	if (nSecTypes == 0)
		throw WarningException(ReadFailureReason());

	char *secTypeNames[] = {"None", "VncAuth"};
	CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
	int nKnownSecTypes = sizeof(knownSecTypes);
	CARD8 *secTypes = new CARD8[nSecTypes];
	ReadExact((char *)secTypes, nSecTypes);
	CARD8 secType = rfbSecTypeInvalid;

	if (m_connDlg != NULL)
		m_connDlg->SetStatus("List of security types received");

	// Find out if the server supports TightVNC protocol extensions
	int j;
	for (j = 0; j < (int)nSecTypes; j++) {
		if (secTypes[j] == rfbSecTypeTight) {
			secType = rfbSecTypeTight;
			WriteExact((char *)&secType, sizeof(secType));
			if (m_connDlg != NULL)
				m_connDlg->SetStatus("TightVNC protocol extensions enabled");
			vnclog.Print(8, _T("Enabling TightVNC protocol extensions\n"));
			return rfbSecTypeTight;
		}
	}

	// Find first supported security type
	for (j = 0; j < (int)nSecTypes; j++) {
		for (int i = 0; i < nKnownSecTypes; i++) {
			if (secTypes[j] == knownSecTypes[i]) {
				secType = secTypes[j];
				WriteExact((char *)&secType, sizeof(secType));
				if (m_connDlg != NULL)
					m_connDlg->SetStatus("Security type requested");
				vnclog.Print(8, _T("Choosing security type %s(%d)\n"),
							 secTypeNames[i], (int)secType);
				break;
			}
		}
		if (secType != rfbSecTypeInvalid) break;
    }

    if (secType == rfbSecTypeInvalid) {
		vnclog.Print(0, _T("Server did not offer supported security type\n"));
		throw ErrorException("Server did not offer supported security type!");
	}

	return (int)secType;
}

//
// Setup tunneling (protocol 3.7t, 3.8t)
//

void ClientConnection::SetupTunneling()
{
	rfbTunnelingCapsMsg caps;
	ReadExact((char *)&caps, sz_rfbTunnelingCapsMsg);
	caps.nTunnelTypes = Swap32IfLE(caps.nTunnelTypes);

	if (caps.nTunnelTypes) {
		ReadCapabilityList(&m_tunnelCaps, caps.nTunnelTypes);
		if (m_connDlg != NULL)
			m_connDlg->SetStatus("List of tunneling capabilities received");

		// We cannot do tunneling yet.
		CARD32 tunnelType = Swap32IfLE(rfbNoTunneling);
		WriteExact((char *)&tunnelType, sizeof(tunnelType));
		if (m_connDlg != NULL)
			m_connDlg->SetStatus("Tunneling type requested");
	}
}

//
// Negotiate authentication scheme (protocol 3.7t, 3.8t)
//

void ClientConnection::PerformAuthenticationTight()
{
	rfbAuthenticationCapsMsg caps;
	ReadExact((char *)&caps, sz_rfbAuthenticationCapsMsg);
	caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);

	if (m_connDlg != NULL)
		m_connDlg->SetStatus("Header of authentication capability list received");

	if (!caps.nAuthTypes) {
		vnclog.Print(0, _T("No authentication needed\n"));
		if (m_connDlg != NULL)
			m_connDlg->SetStatus("No authentication needed");
		Authenticate(rfbAuthNone);
		m_authScheme = rfbAuthNone;
	} else {
		ReadCapabilityList(&m_authCaps, caps.nAuthTypes);
		if (m_connDlg != NULL)
			m_connDlg->SetStatus("Authentication capability list received");
		if (!m_authCaps.NumEnabled()) {
			vnclog.Print(0, _T("No suitable authentication schemes offered by the server\n"));
			throw ErrorException("No suitable authentication schemes offered by the server");
		}

		// Use server's preferred authentication scheme.
		CARD32 authScheme = m_authCaps.GetByOrder(0);
		authScheme = Swap32IfLE(authScheme);
		WriteExact((char *)&authScheme, sizeof(authScheme));
		authScheme = Swap32IfLE(authScheme);	// convert it back
		if (m_connDlg != NULL)
			m_connDlg->SetStatus("Authentication scheme requested");
		Authenticate(authScheme);
		m_authScheme = authScheme;
	}
}

// The definition of a function implementing some authentication scheme.
// For an example, see ClientConnection::AuthenticateVNC, below.

typedef bool (ClientConnection::*AuthFunc)(char *, int);

// A wrapper function for different authentication schemes.

void ClientConnection::Authenticate(CARD32 authScheme)
{
	AuthFunc authFuncPtr;

	// Uncomment this if the "Connecting..." dialog box should be
	// closed prior to authentication.
	/***
	if (m_connDlg != NULL) {
		delete m_connDlg;
		m_connDlg = NULL;
	}
	***/

	switch(authScheme) {
	case rfbAuthNone:
		authFuncPtr = &ClientConnection::AuthenticateNone;
		break;
	case rfbAuthVNC:
		authFuncPtr = &ClientConnection::AuthenticateVNC;
		break;
	default:
		vnclog.Print(0, _T("Unknown authentication scheme: %d\n"),
					 (int)authScheme);
		throw ErrorException("Unknown authentication scheme!");
	}

	vnclog.Print(0, _T("Authentication scheme: %s\n"),
				 m_authCaps.GetDescription(authScheme));

	const int errorMsgSize = 256;
	CheckBufferSize(errorMsgSize);
	char *errorMsg = m_netbuf;
	bool wasError = !(this->*authFuncPtr)(errorMsg, errorMsgSize);

	// Report authentication error.
	if (wasError) {
		vnclog.Print(0, _T("%s\n"), errorMsg);
		if (m_connDlg != NULL)
			m_connDlg->SetStatus("Error during authentication");
		throw AuthException(errorMsg);
	}

	CARD32 authResult;
	if (authScheme == rfbAuthNone && m_minorVersion < 8) {
		// In protocol versions prior to 3.8, "no authentication" is a
		// special case - no "security result" is sent by the server.
		authResult = rfbAuthOK;
	} else {
		ReadExact((char *) &authResult, 4);
		authResult = Swap32IfLE(authResult);
	}

	switch (authResult) {
	case rfbAuthOK:
		if (m_connDlg != NULL)
			m_connDlg->SetStatus("Authentication successful");
		vnclog.Print(0, _T("Authentication successful\n"));
		return;
	case rfbAuthFailed:
		if (m_minorVersion >= 8) {
			errorMsg = ReadFailureReason();
		} else {
			errorMsg = "Authentication failure";
		}
		break;
	case rfbAuthTooMany:
		errorMsg = "Authentication failure, too many tries";
		break;
	default:
		_snprintf(m_netbuf, 256, "Unknown authentication result (%d)",
				 (int)authResult);
		errorMsg = m_netbuf;
		break;
	}

	// Report authentication failure.
	vnclog.Print(0, _T("%s\n"), errorMsg);
	if (m_connDlg != NULL)
		m_connDlg->SetStatus(errorMsg);
	throw AuthException(errorMsg);
}

// "Null" authentication.

bool ClientConnection::AuthenticateNone(char *errBuf, int errBufSize)
{
	return true;
}

// The standard VNC authentication.
//
// An authentication function should return false on error and true if
// the authentication process was successful. Note that returning true
// does not mean that authentication was passed by the server, the
// server's result will be received and analyzed later.
// If false is returned, then a text error message should be copied
// to errorBuf[], no more than errBufSize bytes should be copied into
// that buffer.

bool ClientConnection::AuthenticateVNC(char *errBuf, int errBufSize)
{
    CARD8 challenge[CHALLENGESIZE];
	ReadExact((char *)challenge, CHALLENGESIZE);

	char passwd[MAXPWLEN + 1];
	// Was the password already specified in a config file?
	if (strlen((const char *) m_encPasswd) > 0) {
		char *pw = vncDecryptPasswd(m_encPasswd);
		strcpy(passwd, pw);
		free(pw);
	} else {
		LoginAuthDialog ad(m_opts.m_display, "Standard VNC Authentication");
		ad.DoDialog();
#ifndef UNDER_CE
		strncpy(passwd, ad.m_passwd, MAXPWLEN);
		passwd[MAXPWLEN]= '\0';
#else
		// FIXME: Move wide-character translations to a separate class
		int origlen = _tcslen(ad.m_passwd);
		int newlen = WideCharToMultiByte(
			CP_ACP,    // code page
			0,         // performance and mapping flags
			ad.m_passwd, // address of wide-character string
			origlen,   // number of characters in string
			passwd,    // address of buffer for new string
			255,       // size of buffer
			NULL, NULL);

		passwd[newlen]= '\0';
#endif
		if (strlen(passwd) == 0) {
			_snprintf(errBuf, errBufSize, "Empty password");
			return false;
		}
		if (strlen(passwd) > 8) {
			passwd[8] = '\0';
		}
		vncEncryptPasswd(m_encPasswd, passwd);
	}				

	vncEncryptBytes(challenge, passwd);

	/* Lose the plain-text password from memory */
	memset(passwd, 0, strlen(passwd));

	WriteExact((char *) challenge, CHALLENGESIZE);

	return true;
}

void ClientConnection::SendClientInit()
{
    rfbClientInitMsg ci;
	ci.shared = m_opts.m_Shared;

    WriteExact((char *)&ci, sz_rfbClientInitMsg);

	if (m_connDlg != NULL)
		m_connDlg->SetStatus("Client initialization message sent");
}

void ClientConnection::ReadServerInit()
{
    ReadExact((char *)&m_si, sz_rfbServerInitMsg);
	
	if (m_connDlg != NULL)
		m_connDlg->SetStatus("Server initialization message received");

    m_si.framebufferWidth = Swap16IfLE(m_si.framebufferWidth);
    m_si.framebufferHeight = Swap16IfLE(m_si.framebufferHeight);
    m_si.format.redMax = Swap16IfLE(m_si.format.redMax);
    m_si.format.greenMax = Swap16IfLE(m_si.format.greenMax);
    m_si.format.blueMax = Swap16IfLE(m_si.format.blueMax);
    m_si.nameLength = Swap32IfLE(m_si.nameLength);
	
    m_desktopName = new TCHAR[m_si.nameLength + 2];

#ifdef UNDER_CE
    char *deskNameBuf = new char[m_si.nameLength + 2];

	ReadString(deskNameBuf, m_si.nameLength);
    
	MultiByteToWideChar( CP_ACP,   MB_PRECOMPOSED, 
			     deskNameBuf, m_si.nameLength,
			     m_desktopName, m_si.nameLength+1);
    delete deskNameBuf;
#else
    ReadString(m_desktopName, m_si.nameLength);
#endif
    
	SetWindowText(m_hwnd1, m_desktopName);	

	vnclog.Print(0, _T("Desktop name \"%s\"\n"),m_desktopName);
	vnclog.Print(1, _T("Geometry %d x %d depth %d\n"),
		m_si.framebufferWidth, m_si.framebufferHeight, m_si.format.depth );
	SetWindowText(m_hwnd1, m_desktopName);	

	SizeWindow(true);
}

//
// In protocols 3.7t/3.8t, the server informs us about supported
// protocol messages and encodings. Here we read this information.
//

void ClientConnection::ReadInteractionCaps()
{
	// Read the counts of list items following
	rfbInteractionCapsMsg intr_caps;
	ReadExact((char *)&intr_caps, sz_rfbInteractionCapsMsg);
	intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
	intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
	intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
	if (m_connDlg != NULL)
		m_connDlg->SetStatus("Interaction capability list header received");

	// Read the lists of server- and client-initiated messages
	ReadCapabilityList(&m_serverMsgCaps, intr_caps.nServerMessageTypes);
	ReadCapabilityList(&m_clientMsgCaps, intr_caps.nClientMessageTypes);
	ReadCapabilityList(&m_encodingCaps, intr_caps.nEncodingTypes);

⌨️ 快捷键说明

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