// Copyright (C) 2000 Tridia Corporation. All Rights Reserved. // Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. // // This file is part of the VNC system. // // The VNC system is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, // USA. // // TightVNC distribution homepage on the Web: http://www.tightvnc.com/ // // If the source code for the VNC system is not available from the place // whence you received this file, check http://www.uk.research.att.com/vnc or contact // the authors on vnc@uk.research.att.com for information on obtaining it. // vncServer.cpp // vncServer class implementation // Includes #include "stdhdrs.h" #include #include #include // Custom #include "vncServer.h" #include "vncSockConnect.h" #include "vncCorbaConnect.h" #include "vncClient.h" #include "vncService.h" // Constructor/destructor vncServer::vncServer() { ResetPasswordsValidityInfo(); // Initialise some important stuffs... m_socketConn = NULL; m_corbaConn = NULL; //m_httpConn = NULL; m_desktop = NULL; m_name = NULL; SetName(""); m_port = DISPLAY_TO_PORT(0); m_port_http = DISPLAY_TO_HPORT(0); m_autoportselect = TRUE; m_passwd_required = FALSE; m_beepConnect = FALSE; m_beepDisconnect = FALSE; m_auth_hosts = 0; m_blacklist = 0; //{ // vncPasswd::FromClear clearPWD; memcpy(m_password, "", MAXPWLEN); m_password_set = FALSE; memcpy(m_password_viewonly, "", MAXPWLEN); m_password_viewonly_set = FALSE; //} m_querysetting = 2; m_querytimeout = 10; m_queryaccept = FALSE; m_queryallownopass = FALSE; // Autolock settings m_lock_on_exit = 0; // Set the polling mode options m_poll_fullscreen = TRUE; m_poll_foreground = TRUE; m_poll_undercursor = TRUE; m_poll_oneventonly = FALSE; m_poll_consoleonly = FALSE; m_dont_set_hooks = FALSE; m_dont_use_driver = FALSE; m_driver_direct_access_en = TRUE; // General options m_loopbackOnly = TRUE; m_disableTrayIcon = TRUE; m_loopback_allowed = TRUE; m_httpd_enabled = FALSE; m_httpd_params_enabled = FALSE; m_lock_on_exit = 0; m_connect_pri = 0; // Set the input options m_enable_remote_inputs = TRUE; m_disable_local_inputs = FALSE; // Clear the client mapping table for (int x=0; xinfo, lpAgentContext->hCloseEvent ); // Try to allocate a client id... vncClientId clientid = m_nextid; do { clientid = (clientid+1) % MAX_CLIENTS; if (clientid == m_nextid) { delete socket; return -1; } } while (m_clientmap[clientid] != NULL); // Create a new client and add it to the relevant client list client = new vncClient(); if (client == NULL) { delete socket; return -1; } // Set the client's settings client->EnableKeyboard(TRUE && m_enable_remote_inputs); client->EnablePointer(TRUE && m_enable_remote_inputs); // Start the client if (!client->Init(this, socket, TRUE, TRUE, clientid, lpAgentContext )) { // The client will delete the socket for us... delete client; return -1; } m_clientmap[clientid] = client; // Add the client to unauth the client list m_unauthClients.push_back(clientid); // Notify anyone interested about this event //DoNotify(WM_SRV_CLIENT_CONNECT, 0, 0); return clientid; } BOOL vncServer::Authenticated(vncClientId clientid) { vncClientList::iterator i; BOOL authok = TRUE; omni_mutex_lock l1(m_desktopLock); omni_mutex_lock l2(m_clientsLock); // Search the unauthenticated client list for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { vncClient *client = GetClient(clientid); // Yes, so remove the client and add it to the auth list m_unauthClients.erase(i); // Create the screen handler if necessary if (m_desktop == NULL) { if (RemoveWallpaperEnabled()) { m_wallpaper_wait = TRUE; //DoNotify(WM_SRV_CLIENT_HIDEWALLPAPER, 0, 0); } m_desktop = new vncDesktop(); if (m_desktop == NULL) { client->Kill(); authok = FALSE; break; } if (!m_desktop->Init(this)) { client->Kill(); authok = FALSE; delete m_desktop; m_desktop = NULL; break; } } // Create a buffer object for this client vncBuffer *buffer = new vncBuffer(m_desktop); if (buffer == NULL) { client->Kill(); authok = FALSE; break; } // Tell the client about this new buffer client->SetBuffer(buffer); // Add the client to the auth list m_authClients.push_back(clientid); break; } } // Notify anyone interested of this event //DoNotify(WM_SRV_CLIENT_AUTHENTICATED, 0, 0); // If so configured, beep to indicate the new connection is // present. if (authok && GetBeepConnect()) { MessageBeep(MB_OK); } return authok; } void vncServer::KillClient(vncClientId clientid) { vncClientList::iterator i; BOOL done = FALSE; omni_mutex_lock l(m_clientsLock); // Find the client in one of the two lists for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { // Ask the client to die vncClient *client = GetClient(clientid); client->Kill(); done = TRUE; break; } } if (!done) { for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { // Yes, so kill it vncClient *client = GetClient(clientid); client->Kill(); done = TRUE; break; } } } } void vncServer::KillAuthClients() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Tell all the authorised clients to die! for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Kill the client GetClient(*i)->Kill(); } } void vncServer::KillUnauthClients() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Tell all the authorised clients to die! for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { // Kill the client GetClient(*i)->Kill(); } } size_t vncServer::AuthClientCount() { omni_mutex_lock l(m_clientsLock); return m_authClients.size(); } size_t vncServer::UnauthClientCount() { omni_mutex_lock l(m_clientsLock); return m_unauthClients.size(); } void vncServer::WaitUntilAuthEmpty() { omni_mutex_lock l(m_clientsLock); // Wait for all the clients to exit while (!m_authClients.empty()) { // Wait for a client to quit m_clientquitsig->wait(); } } void vncServer::WaitUntilUnauthEmpty() { omni_mutex_lock l(m_clientsLock); // Wait for all the clients to exit while (!m_unauthClients.empty()) { // Wait for a client to quit m_clientquitsig->wait(); } } BOOL vncServer::RemoteEventReceived() { vncClientList::iterator i; BOOL result = FALSE; omni_mutex_lock l(m_clientsLock); // Iterate over the authorised clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { result = result || GetClient(*i)->RemoteEventReceived(); } return result; } // Client info retrieval/setup vncClient* vncServer::GetClient(vncClientId clientid) { if ((clientid >= 0) && (clientid < MAX_CLIENTS)) return m_clientmap[clientid]; return NULL; } vncClientList vncServer::ClientList() { vncClientList clients; omni_mutex_lock l(m_clientsLock); clients = m_authClients; return clients; } void vncServer::BlockRemoteInput(BOOL block) { omni_mutex_lock l(m_clientsLock); vncClientList::iterator i; for (i = m_authClients.begin(); i != m_authClients.end(); i++) GetClient(*i)->BlockInput(block); } const char* vncServer::GetClientName(vncClientId clientid) { omni_mutex_lock l(m_clientsLock); vncClient *client = GetClient(clientid); if (client != NULL) return client->GetClientName(); return NULL; } // RemoveClient should ONLY EVER be used by the client to remove itself. void vncServer::RemoveClient(vncClientId clientid) { vncClientList::iterator i; BOOL done = FALSE; omni_mutex_lock l1(m_desktopLock); { omni_mutex_lock l2(m_clientsLock); // Find the client in one of the two lists for (i = m_unauthClients.begin(); i != m_unauthClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { // Yes, so remove the client and kill it m_unauthClients.erase(i); m_clientmap[clientid] = NULL; done = TRUE; break; } } if (!done) { for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Is this the right client? if ((*i) == clientid) { // Yes, so remove the client and kill it m_authClients.erase(i); m_clientmap[clientid] = NULL; done = TRUE; break; } } } // Signal that a client has quit m_clientquitsig->signal(); } // Unlock the clientLock // If so configured, beep to indicate the old connection is // gone. if (GetBeepDisconnect()) { MessageBeep(MB_OK); } // Are there any authorised clients connected? if (m_authClients.empty() && (m_desktop != NULL)) { // Are there locksettings set? if (LockSettings() == 1) { // Yes - lock the machine on disconnect! vncService::LockWorkstation(); } else if (LockSettings() > 1) { char username[UNLEN+1]; vncService::CurrentUser((char *)&username, sizeof(username)); if (strcmp(username, "") != 0) { // Yes - force a user logoff on disconnect! ExitWindowsEx(EWX_LOGOFF, 0); } } // Delete the screen server delete m_desktop; m_desktop = NULL; } // Notify anyone interested of the change //DoNotify(WM_SRV_CLIENT_DISCONNECT, 0, 0); } // NOTIFICATION HANDLING! // Connect/disconnect notification BOOL vncServer::AddNotify(HWND hwnd) { omni_mutex_lock l(m_clientsLock); // Add the window handle to the list m_notifyList.push_front(hwnd); return TRUE; } BOOL vncServer::RemNotify(HWND hwnd) { omni_mutex_lock l(m_clientsLock); // Remove the window handle from the list vncNotifyList::iterator i; for (i=m_notifyList.begin(); i!=m_notifyList.end(); i++) { if ((*i) == hwnd) { // Found the handle, so remove it m_notifyList.erase(i); return TRUE; } } return FALSE; } // Send a notification message void vncServer::DoNotify(UINT message, WPARAM wparam, LPARAM lparam) { omni_mutex_lock l(m_clientsLock); // Send the given message to all the notification windows vncNotifyList::iterator i; for (i=m_notifyList.begin(); i!=m_notifyList.end(); i++) { PostMessage((*i), message, wparam, lparam); } } // Client->Desktop update signalling void vncServer::RequestUpdate() { omni_mutex_lock l(m_desktopLock); if (m_desktop != NULL) { m_desktop->RequestUpdate(); } } // Update handling void vncServer::TriggerUpdate() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post this update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->TriggerUpdate(); } } void vncServer::UpdateRect(RECT &rect) { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post this update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->UpdateRect(rect); } } void vncServer::UpdateRegion(vncRegion ®ion) { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post this update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->UpdateRegion(region); } } void vncServer::CopyRect(RECT &dest, POINT &source) { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post this update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->CopyRect(dest, source); } } void vncServer::UpdateMouse() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post this mouse update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->UpdateMouse(); } } void vncServer::UpdateClipText(LPSTR text) { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post this update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->UpdateClipText(text); } } void vncServer::UpdatePalette() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post this update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->UpdatePalette(); } } void vncServer::UpdateLocalClipText(LPSTR text) { omni_mutex_lock l(m_desktopLock); if (m_desktop != NULL) m_desktop->SetClipText(text); } // Changing hook settings void vncServer::DontSetHooks(BOOL enable) { m_dont_set_hooks = enable; if (m_desktop != NULL) m_desktop->TryActivateHooks(); } // Changing use driver settings void vncServer::DontUseDriver(BOOL enable) { m_dont_use_driver = enable; } void vncServer::DriverDirectAccess(BOOL enable) { m_driver_direct_access_en = enable; } // Name and port number handling void vncServer::SetName(const char * name) { // Set the name of the desktop if (m_name != NULL) { free(m_name); m_name = NULL; } m_name = strdup(name); } void vncServer::SetPorts(const UINT port_rfb, const UINT port_http) { if (m_port != port_rfb || m_port_http != port_http) { // Set port numbers to use m_port = port_rfb; m_port_http = port_http; // If there is already a listening socket then close and re-open it... BOOL socketon = SockConnected(); SockConnect(FALSE); if (socketon) SockConnect(TRUE); } } void vncServer::SetPassword(BOOL activate, const char *passwd) { ResetPasswordsValidityInfo(); m_password_set = activate; memcpy(m_password, passwd, MAXPWLEN); } BOOL vncServer::GetPassword(char *passwd) { memcpy(passwd, m_password, MAXPWLEN); return m_password_set; } void vncServer::SetPasswordViewOnly(BOOL activate, const char *passwd) { ResetPasswordsValidityInfo(); m_password_viewonly_set = activate; memcpy(m_password_viewonly, passwd, MAXPWLEN); } BOOL vncServer::GetPasswordViewOnly(char *passwd) { memcpy(passwd, m_password_viewonly, MAXPWLEN); return m_password_viewonly_set; } BOOL vncServer::ValidPasswordsSet() { if (!m_valid_passwords_set_cached) { m_valid_passwords_set = ValidPasswordsSet_nocache(); m_valid_passwords_set_cached = TRUE; } return m_valid_passwords_set; } BOOL vncServer::ValidPasswordsSet_nocache() { char passwd1[MAXPWLEN]; char passwd2[MAXPWLEN]; BOOL set1 = GetPassword(passwd1); BOOL set2 = GetPasswordViewOnly(passwd2); if (!set1 && !set2) return FALSE; // no passwords set, connections impossible if (!AuthRequired()) return TRUE; // passwords may be empty, but we allow that vncPasswd::ToText plain1(passwd1); vncPasswd::ToText plain2(passwd2); BOOL empty1 = !set1 || (strlen(plain1) == 0); BOOL empty2 = !set2 || (strlen(plain2) == 0); if (empty1 && empty2) return FALSE; // both passwords empty or unset, not allowed return TRUE; // at least one non-empty password } BOOL vncServer::ValidPasswordsEmpty() { if (!m_valid_passwords_empty_cached) { m_valid_passwords_empty = ValidPasswordsEmpty_nocache(); m_valid_passwords_empty_cached = TRUE; } return m_valid_passwords_empty; } BOOL vncServer::ValidPasswordsEmpty_nocache() { if (AuthRequired()) return FALSE; // empty passwords disallowed, always fail char passwd1[MAXPWLEN]; char passwd2[MAXPWLEN]; BOOL set1 = GetPassword(passwd1); BOOL set2 = GetPasswordViewOnly(passwd2); if (!set1 && !set2) return FALSE; // no passwords set, connections impossible vncPasswd::ToText plain1(passwd1); vncPasswd::ToText plain2(passwd2); BOOL empty1 = !set1 || (strlen(plain1) == 0); BOOL empty2 = !set2 || (strlen(plain2) == 0); if (empty1 && empty2) return TRUE; // there are no passwords that are non-empty return FALSE; // at least one non-empty password } // Remote input handling void vncServer::EnableRemoteInputs(BOOL enable) { m_enable_remote_inputs = enable; } BOOL vncServer::RemoteInputsEnabled() { return m_enable_remote_inputs; } // Local input handling void vncServer::DisableLocalInputs(BOOL disable) { if ( m_disable_local_inputs != disable ) { m_disable_local_inputs = disable; if ( AuthClientCount() != 0 ) m_desktop->SetLocalInputDisableHook(disable); } } BOOL vncServer::LocalInputsDisabled() { return m_disable_local_inputs; } void vncServer::LocalInputPriority(BOOL disable) { if( m_local_input_priority != disable ) { m_local_input_priority = disable; m_remote_mouse = 0; m_remote_keyboard = 0; if ( AuthClientCount() != 0 ) m_desktop->SetLocalInputPriorityHook(disable); } } // Socket connection handling BOOL vncServer::SockConnect(BOOL On) { // Are we being asked to switch socket connects on or off? if (On) { // Is there a listening socket? if (m_socketConn == NULL) { m_socketConn = new vncSockConnect(); if (m_socketConn == NULL) return FALSE; // Are we to use automatic port selection? if (m_autoportselect) { BOOL ok = FALSE; // Yes, so cycle through the ports, looking for a free one! for (int i = 0; i < 99; i++) { m_port = DISPLAY_TO_PORT(i); m_port_http = DISPLAY_TO_HPORT(i); // Attempt to connect to the port VSocket tempsock; if (tempsock.Create()) { if (!tempsock.Connect("localhost", m_port)) { // Couldn't connect, so this port is probably usable! if (m_socketConn->Init(this, m_port)) { ok = TRUE; break; } } } } if (!ok) { delete m_socketConn; m_socketConn = NULL; return FALSE; } } else { // No autoportselect if (!m_socketConn->Init(this, m_port)) { delete m_socketConn; m_socketConn = NULL; return FALSE; } } // Now let's start the HTTP connection stuff /*if (m_httpConn == NULL && m_httpd_enabled && m_port_http != m_port) { m_httpConn = new vncHTTPConnect; if (m_httpConn != NULL) { // Start up the HTTP server if (!m_httpConn->Init(this, m_port_http, m_httpd_params_enabled)) { delete m_httpConn; m_httpConn = NULL; return FALSE; } } }*/ } } else { // *** JNW - Trying to fix up a lock-up when the listening socket closes #ifndef HORIZONLIVE KillAuthClients(); KillUnauthClients(); WaitUntilAuthEmpty(); WaitUntilUnauthEmpty(); #endif // Is there a listening socket? if (m_socketConn != NULL) { // Close the socket delete m_socketConn; m_socketConn = NULL; } // Is there an HTTP socket active? /*if (m_httpConn != NULL) { // Close the socket delete m_httpConn; m_httpConn = NULL; }*/ } return TRUE; } BOOL vncServer::SockConnected() { return m_socketConn != NULL; } BOOL vncServer::SetHttpdEnabled(BOOL enable_httpd, BOOL enable_params) { if (enable_httpd != m_httpd_enabled) { m_httpd_enabled = enable_httpd; m_httpd_params_enabled = enable_params; BOOL socketConn = SockConnected(); SockConnect(FALSE); SockConnect(socketConn); } else { if (enable_params != m_httpd_params_enabled) { m_httpd_params_enabled = enable_params; if (SockConnected()) { SockConnect(FALSE); SockConnect(TRUE); } } } return TRUE; } BOOL vncServer::SetLoopbackOnly(BOOL loopbackOnly) { if (loopbackOnly != m_loopbackOnly) { m_loopbackOnly = loopbackOnly; BOOL socketConn = SockConnected(); SockConnect(FALSE); SockConnect(socketConn); } return TRUE; } BOOL vncServer::LoopbackOnly() { return m_loopbackOnly; } BOOL vncServer::SetDisableTrayIcon(BOOL disableTrayIcon) { if (disableTrayIcon != m_disableTrayIcon) { m_disableTrayIcon = disableTrayIcon; } return TRUE; } BOOL vncServer::GetDisableTrayIcon() { return m_disableTrayIcon; } // CORBA connection handling BOOL vncServer::CORBAConnect(BOOL On) { // Are we being asked to switch CORBA connects on or off? if (On) { // Is there a CORBA object? if (m_corbaConn == NULL) { m_corbaConn = new vncCorbaConnect(); } if (m_corbaConn == NULL) return FALSE; if (!m_corbaConn->Init(this)) { delete m_corbaConn; m_corbaConn = NULL; return FALSE; } } else { // Is there a listening socket? if (m_corbaConn != NULL) { // Close the socket delete m_corbaConn; m_corbaConn = NULL; } } return TRUE; } BOOL vncServer::CORBAConnected() { return m_corbaConn != NULL; } void vncServer::GetScreenInfo(int &width, int &height, int &depth) { rfbServerInitMsg scrinfo; omni_mutex_lock l(m_desktopLock); // Is a desktop object currently active? if (m_desktop == NULL) { vncDesktop desktop; // No, so create a dummy desktop and interrogate it if (!desktop.Init(this)) { scrinfo.framebufferWidth = 0; scrinfo.framebufferHeight = 0; scrinfo.format.bitsPerPixel = 0; } else { desktop.FillDisplayInfo(&scrinfo); } } else { m_desktop->FillDisplayInfo(&scrinfo); } // Get the info from the scrinfo structure width = m_shared_rect.right - m_shared_rect.left; height = m_shared_rect.bottom - m_shared_rect.top; depth = scrinfo.format.bitsPerPixel; } void vncServer::SetAuthHosts(const char*hostlist) { omni_mutex_lock l(m_clientsLock); if (m_auth_hosts != 0) free(m_auth_hosts); if (hostlist == 0) { m_auth_hosts = 0; return; } m_auth_hosts = strdup(hostlist); } char* vncServer::AuthHosts() { omni_mutex_lock l(m_clientsLock); if (m_auth_hosts == 0) return strdup(""); else return strdup(m_auth_hosts); } inline BOOL MatchStringToTemplate(const char *addr, size_t addrlen, const char *filtstr, size_t filtlen) { if (filtlen == 0) return 1; if (addrlen < filtlen) return 0; for (size_t x = 0; x < filtlen; x++) { if (addr[x] != filtstr[x]) return 0; } if ((addrlen > filtlen) && (addr[filtlen] != '.')) return 0; return 1; } vncServer::AcceptQueryReject vncServer::VerifyHost(const char *hostname) { if (ClientsDisabled()) return vncServer::aqrReject; omni_mutex_lock l(m_clientsLock); // -=- Is the specified host blacklisted? vncServer::BlacklistEntry *current = m_blacklist; vncServer::BlacklistEntry *previous = 0; SYSTEMTIME systime; FILETIME ftime; LARGE_INTEGER now; // Get the current time as a 64-bit value GetSystemTime(&systime); SystemTimeToFileTime(&systime, &ftime); now.LowPart=ftime.dwLowDateTime;now.HighPart=ftime.dwHighDateTime; now.QuadPart /= 10000000; // Convert it into seconds while (current) { // Has the blacklist entry timed out? if ((now.QuadPart - current->_lastRefTime.QuadPart) > 0) { // Yes. Is it a "blocked" entry? if (current->_blocked) { // Yes, so unblock it & re-set the reference time current->_blocked = FALSE; current->_lastRefTime.QuadPart = now.QuadPart + 10; } else { // No, so remove it if (previous) previous->_next = current->_next; else m_blacklist = current->_next; vncServer::BlacklistEntry *next = current->_next; free(current->_machineName); delete current; current = next; continue; } } // Is this the entry we're interested in? if ((strcmp(current->_machineName, hostname) == 0) && (current->_blocked)) { // Machine is blocked, so just reject it return vncServer::aqrReject; } previous = current; current = current->_next; } // Has a hostname been specified? if (hostname == 0) { return vncServer::aqrReject; } // Set the state machine into the correct mode & process the filter enum vh_Mode {vh_ExpectDelimiter, vh_ExpectIncludeExclude, vh_ExpectPattern}; vh_Mode machineMode = vh_ExpectIncludeExclude; vncServer::AcceptQueryReject verifiedHost = vncServer::aqrAccept; vncServer::AcceptQueryReject patternType = vncServer::aqrReject; UINT authHostsPos = 0; UINT patternStart = 0; size_t hostNameLen = strlen(hostname); // Run through the auth hosts string until we hit the end if (m_auth_hosts) { while (1) { // Which mode are we in? switch (machineMode) { // ExpectIncludeExclude - we should see a + or -. case vh_ExpectIncludeExclude: if (m_auth_hosts[authHostsPos] == '+') { patternType = vncServer::aqrAccept; patternStart = authHostsPos+1; machineMode = vh_ExpectPattern; } else if (m_auth_hosts[authHostsPos] == '-') { patternType = vncServer::aqrReject; patternStart = authHostsPos+1; machineMode = vh_ExpectPattern; } else if (m_auth_hosts[authHostsPos] == '?') { patternType = vncServer::aqrQuery; patternStart = authHostsPos+1; machineMode = vh_ExpectPattern; } else if (m_auth_hosts[authHostsPos] != '\0') { machineMode = vh_ExpectDelimiter; } break; // ExpectPattern - we expect to see a valid pattern case vh_ExpectPattern: // ExpectDelimiter - we're scanning for the next ':', skipping a pattern case vh_ExpectDelimiter: if ((m_auth_hosts[authHostsPos] == ':') || (m_auth_hosts[authHostsPos] == '\0')) { if (machineMode == vh_ExpectPattern) { if (patternStart == 0) { } else { // Process the match if (MatchStringToTemplate(hostname, hostNameLen, &(m_auth_hosts[patternStart]), authHostsPos-patternStart)) { // The hostname matched - apply the include/exclude rule verifiedHost = patternType; } } } // We now expect another + or - machineMode = vh_ExpectIncludeExclude; } break; } // Have we hit the end of the pattern string? if (m_auth_hosts[authHostsPos] == '\0') break; authHostsPos++; } } return AdjustVerification(verifiedHost); } vncServer::AcceptQueryReject vncServer::AdjustVerification(vncServer::AcceptQueryReject host) { vncServer::AcceptQueryReject verifiedHost = host; // Based on the server's QuerySetting, adjust the verification result switch (host) { case vncServer::aqrAccept: if (QuerySetting() >= 3) verifiedHost = vncServer::aqrQuery; break; case vncServer::aqrQuery: if (QuerySetting() <= 1) verifiedHost = vncServer::aqrAccept; else if (QuerySetting() == 4) verifiedHost = vncServer::aqrReject; break; case vncServer::aqrReject: if (QuerySetting() == 0) verifiedHost = vncServer::aqrQuery; break; }; return verifiedHost; } void vncServer::AddAuthHostsBlacklist(const char *machine) { omni_mutex_lock l(m_clientsLock); // -=- Is the specified host blacklisted? vncServer::BlacklistEntry *current = m_blacklist; // Get the current time as a 64-bit value SYSTEMTIME systime; FILETIME ftime; LARGE_INTEGER now; GetSystemTime(&systime); SystemTimeToFileTime(&systime, &ftime); now.LowPart=ftime.dwLowDateTime;now.HighPart=ftime.dwHighDateTime; now.QuadPart /= 10000000; // Convert it into seconds while (current) { // Is this the entry we're interested in? if (strcmp(current->_machineName, machine) == 0) { // If the host is already blocked then ignore if (current->_blocked) return; // Set the RefTime & failureCount current->_lastRefTime.QuadPart = now.QuadPart + 10; current->_failureCount++; if (current->_failureCount > 5) current->_blocked = TRUE; return; } current = current->_next; } // Didn't find the entry current = new vncServer::BlacklistEntry; current->_blocked = FALSE; current->_failureCount = 0; current->_lastRefTime.QuadPart = now.QuadPart + 10; current->_machineName = strdup(machine); current->_next = m_blacklist; m_blacklist = current; } void vncServer::RemAuthHostsBlacklist(const char *machine) { omni_mutex_lock l(m_clientsLock); // -=- Is the specified host blacklisted? vncServer::BlacklistEntry *current = m_blacklist; vncServer::BlacklistEntry *previous = 0; while (current) { // Is this the entry we're interested in? if (strcmp(current->_machineName, machine) == 0) { if (previous) previous->_next = current->_next; else m_blacklist = current->_next; vncServer::BlacklistEntry *next = current->_next; free (current->_machineName); delete current; current = next; continue; } previous = current; current = current->_next; } } void vncServer::SetWindowShared(HWND hWnd) { m_hwndShared=hWnd; } void vncServer::SetMatchSizeFields(int left,int top,int right,int bottom) { RECT trect = GetScreenRect(); /* if ( right - left < 32 ) right = left + 32; if ( bottom - top < 32) bottom = top + 32 ;*/ if( right > trect.right ) right = trect.right; if( bottom > trect.bottom ) bottom = trect.bottom; if( left < trect.left) left = trect.left; if( top < trect.top) top = trect.top; m_screenarea_rect.left=left; m_screenarea_rect.top=top; m_screenarea_rect.bottom=bottom; m_screenarea_rect.right=right; } void vncServer::SetKeyboardCounter(int count) { omni_mutex_lock l(m_clientsLock); if (LocalInputPriority() && vncService::IsWin95()) { m_remote_keyboard += count; if (count == 0) m_remote_keyboard = 0; } } void vncServer::SetMouseCounter(int count, POINT &cursor_pos, BOOL mousemove) { if( (mousemove) && ( abs (m_cursor_pos.x - cursor_pos.x)==0 && abs (m_cursor_pos.y - cursor_pos.y)==0 ) ) return; omni_mutex_lock l(m_clientsLock); if (LocalInputPriority() && vncService::IsWin95()) { m_remote_mouse += count; if (count == 0) m_remote_mouse = 0; m_cursor_pos.x = cursor_pos.x; m_cursor_pos.y = cursor_pos.y; } } void vncServer::SetNewFBSize(BOOL sendnewfb) { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Post new framebuffer size update to all the connected clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { // Post the update GetClient(*i)->SetNewFBSize( sendnewfb); } } BOOL vncServer::FullRgnRequested() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Iterate over the authorised clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { if (GetClient(*i)->FullRgnRequested()) return TRUE; } return FALSE; } BOOL vncServer::IncrRgnRequested() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Iterate over the authorised clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { if (GetClient(*i)->IncrRgnRequested()) return TRUE; } return FALSE; } void vncServer::UpdateLocalFormat() { vncClientList::iterator i; omni_mutex_lock l(m_clientsLock); // Iterate over the authorised clients for (i = m_authClients.begin(); i != m_authClients.end(); i++) { GetClient(*i)->UpdateLocalFormat(); } return; } void vncServer::SetPollingCycle(UINT msec) { if (m_polling_cycle != msec && msec > 10) { m_polling_cycle = msec; PollingCycleChanged(true); } } BOOL vncServer::checkPointer(vncClient *pClient) { vncClientList::iterator i; for (i = m_authClients.begin(); i != m_authClients.end(); i++) { if (GetClient(*i) == pClient) return TRUE; } return FALSE; } BOOL vncServer::DriverActive() { return (m_desktop != NULL) ? m_desktop->DriverActive() : FALSE; } typedef HMONITOR (WINAPI* pMonitorFromPoint)(POINT,DWORD); typedef BOOL (WINAPI* pGetMonitorInfo)(HMONITOR,LPMONITORINFO); BOOL vncServer::SetShareMonitorFromPoint(POINT pt) { HINSTANCE hInstUser32 = LoadLibrary("User32.DLL"); if (!hInstUser32) return FALSE; pMonitorFromPoint pMFP = (pMonitorFromPoint)GetProcAddress(hInstUser32, "MonitorFromPoint"); pGetMonitorInfo pGMI = (pGetMonitorInfo)GetProcAddress(hInstUser32, "GetMonitorInfoA"); if (!pMFP || !pGMI) { FreeLibrary(hInstUser32); return FALSE; } HMONITOR hm = pMFP(pt, MONITOR_DEFAULTTONEAREST); if (!hm) { FreeLibrary(hInstUser32); return FALSE; } MONITORINFO moninfo; moninfo.cbSize = sizeof(moninfo); if (!pGMI(hm, &moninfo)) { FreeLibrary(hInstUser32); return FALSE; } FullScreen(FALSE); WindowShared(FALSE); ScreenAreaShared(TRUE); PrimaryDisplayOnlyShared(FALSE); SetMatchSizeFields( moninfo.rcMonitor.left, moninfo.rcMonitor.top, moninfo.rcMonitor.right, moninfo.rcMonitor.bottom); FreeLibrary(hInstUser32); return TRUE; }