Protocol.cpp revision 617e2443dfc17fe44fd44c0675d6aad2ffc9df42
/*******************************************************************************
* Copyright (C) 2004-2008 Intel Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
*
* - Neither the name of Intel Corp. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <cerrno>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <syslog.h>
#define _stprintf_s snprintf
#define strnicmp strncasecmp
#else
#include <winsock2.h>
#include <iphlpapi.h>
#include <Ws2tcpip.h>
#include <tchar.h>
#endif // __sun || _LINUX
#include <fstream>
#include <algorithm>
#include "Protocol.h"
#include "LMS_if.h"
#include "LMS_if_compat.h"
#include "Lock.h"
#include "ATNetworkTool.h"
#if DEBUGLOG
_lme(true),
#else
_lme(false),
#endif
#ifdef _REMOTE_SUPPORT
, _cfg(true)
#endif
{
_sockets_active = false;
#ifdef _REMOTE_SUPPORT
_remoteAccessEnabled = false;
#endif
oldProtocolMode = false;
_deinitReq = false;
}
{
if (!oldProtocolMode) {
}
DeinitFull();
}
{
DeinitFull();
{
_deinitReq = false;
}
return false;
}
{
Lock l(_versionLock);
if (_handshakingStatus == NOT_INITIATED) {
if (oldProtocolMode) {
} else {
}
}
}
if (!oldProtocolMode) {
#ifdef _REMOTE_SUPPORT
#else
if (!_cfg.IsAMTEnabled(false)) {
#endif
return false;
}
}
if (bufSize > 0) {
_rxSocketBuffer = new char[bufSize];
} else {
DeinitFull();
return false;
}
#ifdef _REMOTE_SUPPORT
if (!oldProtocolMode) {
_checkRemoteSupport(true);
}
#endif
return true;
}
{
if (oldProtocolMode) {
}
}
} else {
}
}
return NULL;
}
bool Protocol::IsDeInitialized()
{
return _deinitReq;
}
bool Protocol::IsInitialized()
{
if (IsDeInitialized()) {
return false;
}
return _lme.IsInitialized();
}
{
_deinitReq = true;
{
Lock l(_channelsLock);
}
}
{
Lock l(_portsLock);
delete *it2;
}
}
}
_openPorts.clear();
}
#ifdef _REMOTE_SUPPORT
if (!oldProtocolMode) {
}
#endif
{
}
}
void Protocol::DeinitFull()
{
Deinit();
if (_rxSocketBuffer != NULL) {
delete []_rxSocketBuffer;
_rxSocketBufferSize = 0;
}
_sockets_active = false;
#ifdef _REMOTE_SUPPORT
_remoteAccessEnabled = false;
#endif
}
{
bool exists = false;
exists = true;
break;
}
}
}
} else {
}
return exists;
}
{
return ATNetworkTool::CreateServerSocket(
port,
false, true, PF_INET);
}
{
int error;
int socket = INVALID_SOCKET;
if (serverSocket == INVALID_SOCKET) {
if (exists) {
//already listening
}
return false;
}
serverSocket, _isLocalCallback, true);
return true;
}
bool Protocol::CreateSockets()
{
int error;
_sockets_active = false;
if (_serverSignalSocket == INVALID_SOCKET) {
return false;
}
if (_clientSignalSocket == INVALID_SOCKET) {
return false;
}
struct sockaddr_storage addr;
if (s_new == INVALID_SOCKET) {
return false;
}
if (oldProtocolMode) {
if (!_localListen(16992)) {
return false;
}
if (!_localListen(16993)) {
return false;
}
}
_sockets_active = true;
return true;
}
void Protocol::DestroySockets()
{
_sockets_active = false;
if (_serverSignalSocket != INVALID_SOCKET) {
}
}
{
int error = 0;
char buf[NI_MAXHOST];
if (!IsInitialized()) {
return false;
}
if (s_new == INVALID_SOCKET) {
#if DEBUGLOG
#endif
return false;
}
PRINT("Error: ntop failed for new connection\n");
return false;
}
//_portsLock is already aquired by the calling function: Select().
break;
}
}
}
if (portForwardRequest == NULL) {
return false;
}
if (oldProtocolMode) {
unsigned int connId;
if (!oret) {
PRINT("[Compat]Error: failed to open new LME MEI connection\n");
return false;
}
c->AddBytesTxWindow(1024);
Lock l(_channelsLock);
_openChannels[connId] = c;
} else {
Lock l(_channelsLock);
_openChannels[s_new] = c;
port,
}
return true;
}
{
int res;
int fdCount = 0;
int fdMin = -1;
if ((int)_serverSignalSocket > fdCount) {
fdCount = (int)_serverSignalSocket;
}
{
Lock l(_portsLock);
if ((int)serverSocket > fdCount) {
fdCount = (int)serverSocket;
}
}
}
}
{
Lock l(_channelsLock);
}
}
}
}
}
fdCount++;
if (res == -1) {
#if DEBUGLOG
#else
int err = GetLastError();
#endif // __sun || _LINUX
#endif
return -1;
}
if (res == 0) {
return 0;
}
if (!IsInitialized()) {
return 0;
}
char c = 0;
res--;
}
{
Lock l(_portsLock);
// connection request
res--;
}
}
}
}
int i;
_rxFromSocket(i);
res--;
}
}
return 1;
}
{
if (!IsInitialized()) {
return 0;
}
{
Lock l(_channelsLock);
// Data received from a socket that is not in the map.
// Since we only select on our sockets, this means it was
// in the map, but was removed, probably because we received
// an End Connection message from the HECI.
return 0;
}
}
int res = 0;
if (res > 0) {
// send data to LME
if (oldProtocolMode) {
} else {
}
goto out;
} else if (res == 0) {
// connection closed
PRINT("Received 0 bytes from socket %d.\n", (int)s);
goto out;
} else {
#if DEBUGLOG
#else
int err = GetLastError();
#endif // __sun || _LINUX
#endif
#ifdef __sun
ATNetworkTool::CloseSocket(s);
#endif
goto out;
}
out:
{
Lock l(_channelsLock);
// Data received from a socket that is not in the map.
// Since we only select on our sockets, this means it was
// in the map, but was removed, probably because we received
// an End Connection message from the HECI.
delete c;
return 0;
}
if (res > 0) {
if (!oldProtocolMode) {
}
}
else {
if (oldProtocolMode) {
if (res == 0) {
break;
}
}
}
}
((res == 0) ? LMS_CLOSE_STATUS_CLIENT :
} else {
}
}
}
delete c;
return 0;
}
void Protocol::_signalSelect()
{
int senderr = 0;
}
{
return;
}
bool found = false;
if ((*it2) == p) {
found = true;
break;
}
}
delete (*it2);
if (res != 0) {
int err;
#else
err = WSAGetLastError()
#endif
}
}
}
}
{
switch (message->MessageType) {
case APF_SERVICE_REQUEST:
case APF_USERAUTH_REQUEST:
{
Lock l(_versionLock);
if (_handshakingStatus != AGREED) {
Deinit();
return false;
}
return true;
}
break;
case APF_GLOBAL_REQUEST:
case APF_CHANNEL_OPEN:
case APF_CHANNEL_OPEN_FAILURE:
case APF_CHANNEL_CLOSE:
case APF_CHANNEL_DATA:
{
Lock l(_versionLock);
Deinit();
return false;
}
return true;
}
break;
case APF_DISCONNECT:
case APF_PROTOCOLVERSION:
return true;
break;
default:
{
Deinit();
return false;
}
break;
}
return false;
}
{
switch (message->MessageType) {
case APF_SERVICE_REQUEST:
return sizeof(LMEServiceRequestMessage);
break;
case APF_USERAUTH_REQUEST:
return sizeof(LMEUserAuthRequestMessage);
break;
case APF_GLOBAL_REQUEST:
return sizeof(LMEGlobalRequestMessage);
break;
case APF_CHANNEL_OPEN:
return sizeof(LMEChannelOpenRequestMessage);
break;
return sizeof(LMEChannelOpenReplaySuccessMessage);
break;
case APF_CHANNEL_OPEN_FAILURE:
return sizeof(LMEChannelOpenReplayFailureMessage);
break;
case APF_CHANNEL_CLOSE:
return sizeof(LMEChannelCloseMessage);
break;
case APF_CHANNEL_DATA:
return sizeof(LMEChannelDataMessage);
break;
return sizeof(LMEChannelWindowAdjustMessage);
break;
case APF_DISCONNECT:
return sizeof(LMEDisconnectMessage);
break;
case APF_PROTOCOLVERSION:
return sizeof(LMEProtocolVersionMessage);
break;
default:
return 0;
}
return 0;
}
{
if (len < sizeof(LMEMessage)) {
Deinit();
return false;
}
if (!_checkProtocolFlow(message)) {
return false;
}
Deinit();
return false;
}
return true;
}
{
if (prot->oldProtocolMode) {
} else {
}
}
{
*status = 0;
return;
}
switch (message->MessageType) {
case APF_DISCONNECT:
{
PRINT("LME requested to disconnect with reason code 0x%08x\n",
Deinit();
return;
}
break;
case APF_SERVICE_REQUEST:
{
PRINT("Accepting service: %s\n",
Lock l(_versionLock);
}
} else {
PRINT("Requesting to disconnect from LME with reason code 0x%08x\n",
Deinit();
return;
}
}
break;
case APF_USERAUTH_REQUEST:
{
PRINT("Sending Userauth success message\n");
}
break;
case APF_PROTOCOLVERSION:
break;
case APF_GLOBAL_REQUEST:
break;
case APF_CHANNEL_OPEN:
break;
{
Lock l(_channelsLock);
}
}
break;
case APF_CHANNEL_OPEN_FAILURE:
{
Lock l(_portsLock);
}
}
break;
case APF_CHANNEL_CLOSE:
{
Lock l(_portsLock);
}
}
break;
case APF_CHANNEL_DATA:
{
Lock l(_portsLock);
}
}
break;
{
Lock l(_channelsLock);
}
}
break;
default:
Deinit();
break;
}
}
{
switch (globalMessage->RequestType) {
return sizeof(LMETcpForwardRequestMessage);
break;
return sizeof(LMETcpForwardCancelRequestMessage);
break;
return sizeof(LMEUdpSendToMessage);
break;
default:
return 0;
}
return 0;
}
{
Deinit();
return;
}
switch (globalMessage->RequestType) {
break;
break;
break;
default:
Deinit();
break;
}
}
{
bool failure = false;
#ifdef _REMOTE_SUPPORT
}
else
#endif
{
}
{
Lock l(_portsLock);
*status = 1;
// Log in Event Log
TEXT("LMS Service already accepted a request at %s:%d\n"),
tcpFwdReqMsg->Port);
// Send Failure replay to LME
return;
}
if (serverSocket == INVALID_SOCKET) {
int error;
if (serverSocket == INVALID_SOCKET) {
*status = 1;
// Log in Event Log
TEXT("LMS Service cannot listen at port %d.\n"),
tcpFwdReqMsg->Port);
}
// Send Failure replay to LME
failure = true;
}
}
if (failure != true) {
PRINT("Listening at port %d at %s interface.\n",
// Send Success replay to LME
(cb == _isLocalCallback) ?
}
}
}
if (failure == true) {
Deinit();
return;
}
if (cb == _isLocalCallback) {
if (_listenFailReported.empty()) {
}
}
#ifdef _REMOTE_SUPPORT
else {
_checkRemoteSupport(true);
}
#endif
}
{
bool found = false;
Lock l(_portsLock);
PRINT("Previous request on address %s and port %d doesn't exist.\n",
return;
}
//((*it2)->GetPort() == tcpFwdCnclMsg->Port)) {
found = true;
break;
}
}
if (found) {
if ((*it2)->GetChannelCount() == 0) {
}
} else {
PRINT("Previous request on address %s and port %d doesn't exist.\n",
}
}
{
int error = 0;
if (s == INVALID_SOCKET) {
*status = 1;
PRINT("Unable to send UDP data.\n");
return;
}
ATNetworkTool::CloseSocket(s);
}
{
Lock l(_versionLock);
switch (_handshakingStatus) {
case AGREED:
case NOT_INITIATED:
case INITIATED:
if (*verMsg < MIN_PROT_VERSION) {
PRINT("Version %d.%d is not supported.\n",
Deinit();
return;
}
if (*verMsg > MAX_PROT_VERSION) {
} else {
_AmtProtVersion = (*verMsg);
}
break;
default:
Deinit();
break;
}
}
{
int error = 0;
PRINT("Got channel request from AMT. "
" Recipient channel %d for address %s, port %d.\n",
if (s == INVALID_SOCKET) {
*status = 1;
PRINT("Unable to open direct channel to address %s.\n",
return;
}
{
Lock l(_channelsLock);
_openChannels[c->GetSenderChannel()] = c;
}
}
{
PortForwardRequest *p = c->GetPortForwardRequest();
if ((p != NULL) && (p->DecreaseChannelCount() == 0)) {
clPFwdReq = p;
}
delete c;
return clPFwdReq;
}
{
Lock l(_channelsLock);
PRINT("Channel open request was refused. Reason code: 0x%02x reason.\n",
}
return clPFwdReq;
}
{
Lock l(_channelsLock);
switch(c->GetStatus()) {
break;
case Channel::WAITING_CLOSE:
break;
case Channel::NOT_OPENED:
break;
}
clPFwdReq = _closeMChannel(c);
}
return clPFwdReq;
}
{
do {
Lock l(_channelsLock);
break;
}
break;
}
break;
}
int senderr = 0;
PRINT("Sent %d bytes of %d from AMT to channel %d with socket %d.\n",
*status = 1;
PRINT("Channel send data request was refused. Broken pipe.\n");
break;
}
//it->second->AddBytesRxWindow(-count);
//if (it->second->GetRxWindow() < Channel::LMS_WINDOW_SIZE / 2) {
//Channel::LMS_WINDOW_SIZE - it->second->GetRxWindow());
//}
} while (0);
return clPFwdReq;
}
#ifdef _REMOTE_SUPPORT
{
return false;
}
return false;
}
AMTDNSSuffix.size()) == 0) {
return true;
}
return false;
}
{
if (requestDnsFromAmt) {
if (status != AMT_STATUS_SUCCESS) {
return false;
}
}
int error = 0;
return true;
}
{
bool access = false;
access = true;
break;
}
}
bool sendEntAccessMessage = true;
if (access) {
Lock l(_portsLock);
sendEntAccessMessage = false;
break; // Assuming that there is a such request one per port
}
}
}
}
if (sendEntAccessMessage == false) {
return;
}
switch (status) {
case AMT_STATUS_SUCCESS:
PRINT("Remote access is allowed.\n");
break;
PRINT("Remote access is denied because AMT is directly connected "
"to enterprise network.\n");
break;
PRINT("Remote access is disabled.\n");
break;
default:
PRINT("Remote access is disabled.\n");
break;
}
//if (_remoteAccessEnabled) {
// Lock l(_portsLock);
// for (PortMap::iterator it = _openPorts.begin(); it != _openPorts.end(); it++) {
// for (PortForwardRequestList::iterator it2 = it->second.begin();
// it2 != it->second.end(); it2++) {
// if ((*it2)->GetStatus() == PortForwardRequest::PENDING_REQUEST) {
// (*it2)->SetStatus(PortForwardRequest::LISTENING);
// break; // Assuming that there is a such request one per port
// }
// }
// }
// _signalSelect();
//}
}
#endif
{
int error = 0;
}
#ifdef _REMOTE_SUPPORT
{
}
{
int result = 0;
int error = 0;
int ret;
if (ret != 1) {
return ret;
}
if (_remoteAccessEnabled) {
result = 1;
break;
}
}
}
return result;
}
#endif
{
// If AMT FQDN is equal to local FQDN than we don't do anything
if (_handleFQDNChange(fqdn) < 0) {
ERROR("Error: failed to update FQDN info\n");
return -1;
}
} else {
if (_handleFQDNChange("") < 0) {
ERROR("Error: failed to update FQDN info\n");
return -1;
}
}
}
return 0;
}
{
static char buffer[1024];
#else
NULL,
err,
0,
sizeof(buffer) - 1,
0);
#endif // __sun || _LINUX
return buffer;
}
{
const char *hostFile = "hosts";
const char *tmpFile = "hosts-lms.tmp";
bool hasFqdn = false;
#define LMS_MAX_FILENAME_LEN 1024
#define LMS_MAX_LINE_LEN 1023
#define LMS_LINE_SIG_FIRST_WORDS "# LMS GENERATED "
#define LMS_LINE_SIG_LAST_WORD "LINE"
#define LMS_LINE_SIG_LAST_WORD_LEN 4
#define lmsname(s) #s
#define LMS_LINE_SCAN_FORMAT "127.0.0.1 %" lmsstr(FQDN_MAX_SIZE) "s %" lmsstr(FQDN_MAX_SIZE) "s " LMS_LINE_SIG_FIRST_WORDS "%" lmsstr(LMS_LINE_SIG_LAST_WORD_LEN) "c"
const char *dir = "/etc/";
#else
char *sysDrive;
const char *dir = "\\system32\\drivers\\etc\\";
return -1;
}
// sanity check before string copying
return -1;
}
// sanity check before string copying
return -1;
}
#endif // __sun || _LINUX
return -1;
}
return -1;
}
// First create a copy of the hosts file, without lines that were
// previously added by the LMS.
// Go over each line and copy it to the tmp file.
// don't copy the line if it was generated by the LMS
if (0 == (
: (-2))
) {
// copy the old LMS line too, since it's up to date
hasFqdn = true;
}
continue;
}
}
}
if (hasFqdn) {
return 0;
}
// If the original hosts file does not end with a new line character,
// add a new line at the end of the new file before adding our line.
if ('\n' != lastChar) {
}
lmsdot[0] = '\0';
}
// Add the specified FQDN to the end of the tmp file
}
return -1;
}
return -1;
}
return -1;
}
return -1;
}
return -1;
}
return -1;
}
}
}
return 0;
}
{
#if defined(_LINUX)
}
}
#else
#endif // _LINUX
return result;
}