1375 lines
41 KiB
C++

//----------------------------------------------------------------------------
//
// Copyright (C) Intel Corporation, 2006 - 2007.
//
// File: TunnelSupplier.cpp
//
// Contents: Handles incoming data on APF tunnel.
//
// Notes:
//----------------------------------------------------------------------------
#include <ace/SOCK_Dgram.h>
#include <ace/Configuration.h>
#include "TunnelSupplier.h"
#include "TunnelHandler.h"
#include "TunnelConsumer.h"
#include "TunnelManager.h"
#include "TcpConsumer.h"
#include "ChannelConsumer.h"
#include "APF.h"
#include "connector.h"
#include "global.h"
#include "DevicePresence.h"
#define TEXT_UUID_SIZE 37
#define DELIMITER_HOST_PORT ":"
#define PORT_STR_LENGTH 5
// Utility function declaration
void StringFromUUID(const unsigned char binUUID[16],
unsigned char textUUID[TEXT_UUID_SIZE] );
STATUS AMT_Tunnel_Supplier::processReturnVal(STATUS rep)
{
switch (rep)
{
case STATUS_SUCCESS: // Success
case STATUS_RECOVER_ERROR: // some error we wish to keep this tunnel alive
case STATUS_NETWORK_ERROR: // We can't send disconnect in this case
case STATUS_CONNECTION_CLOSED: // We received disconnect message no need to reply
return rep;
case STATUS_AUTH_FAILURE:
tunnel_handler_->_disconnect_data.setParams(APF_DISCONNECT_ILLEGAL_USER_NAME, true, PRIO_LOW);
return STATUS_CONNECTION_CLOSED;
}
// All other status return from any process flow, is invalid and we are closing the channel
tunnel_handler_->_disconnect_data.setParams(true, PRIO_HIGH);
return STATUS_CONNECTION_CLOSED;
}
AMT_Tunnel_Supplier::AMT_Tunnel_Supplier(AMT_Tunnel_Handler *tunnel_handler):
tunnel_handler_(tunnel_handler), major_version_(), minor_version_(), trigger_reason_()
{
}
AMT_Tunnel_Supplier::~AMT_Tunnel_Supplier(void)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("--->AMT_Tunnel_Supplier dtor\n")));
}
// Get reference to this tunnel socket stream
ACE_SOCK_Stream& AMT_Tunnel_Supplier::getPeer(void) const
{
return (ACE_SOCK_Stream &)tunnel_handler_->peer();
}
// Get reference to this tunnel consumer
AMT_Tunnel_Consumer* AMT_Tunnel_Supplier::consumer() const
{
return tunnel_handler_->consumer();
}
// Get reference to this tunnel channel manager
Channel_Manager& AMT_Tunnel_Supplier::channel_manager() const
{
return tunnel_handler_->channel_mgr();
}
void AMT_Tunnel_Supplier::setDisconnectReason(ACE_UINT32 disconnect_reason)
{
tunnel_handler_->_disconnect_data._disconnect_reason = disconnect_reason;
}
ACE_UINT32 AMT_Tunnel_Supplier::getDisconnectReason()
{
return tunnel_handler_->_disconnect_data._disconnect_reason;
}
// Set/Get this tunnel state
void AMT_Tunnel_Supplier::tunnelState (int state)
{
tunnel_handler_->tunnelState(state);
}
int AMT_Tunnel_Supplier::tunnelState (void) const
{
return tunnel_handler_->tunnelState();
}
// Receive and process incoming APF message.
STATUS AMT_Tunnel_Supplier::handle_input()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::handle_input"));
int res;
ACE_UINT8 messageType = 0;
STATUS status;
// Get message Type
if ((res = getPeer().recv_n(&messageType,1, &ACE_Time_Value(*getMaxTunnelTimeout()))) <=0)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier failed reading APF message type from network\n\tres= %d \terrno= %d\n"),
res, errno));
return STATUS_NETWORK_ERROR;
}
switch (messageType)
{
case APF_DISCONNECT:
status = process_disconnect();
break;
case APF_SERVICE_REQUEST:
status = process_service_request();
break;
case APF_USERAUTH_REQUEST:
status = process_userauth_request();
break;
case APF_GLOBAL_REQUEST:
status = process_global_message();
break;
case APF_CHANNEL_OPEN:
status = process_channel_open_direct();
break;
case APF_CHANNEL_OPEN_CONFIRMATION:
case APF_CHANNEL_OPEN_FAILURE:
status = process_channel_open_reply(messageType);
break;
case APF_CHANNEL_WINDOW_ADJUST:
status = process_channel_window_adjust();
break;
case APF_CHANNEL_DATA:
status = process_channel_data();
break;
case APF_CHANNEL_CLOSE:
status = process_channel_close();
break;
case APF_PROTOCOLVERSION:
status = process_init();
break;
case APF_KEEPALIVE_REQUEST:
status = process_KeepAliveReq();
break;
case APF_KEEPALIVE_OPTIONS_REQ:
status = process_KeepAliveOptionReq();
break;
// This tunnel can't receive any of the following message types:
case APF_SERVICE_ACCEPT:
case APF_USERAUTH_FAILURE:
case APF_USERAUTH_SUCCESS:
case APF_REQUEST_SUCCESS:
case APF_REQUEST_FAILURE:
default:
ACE_DEBUG((MY_DEBUG
ACE_TEXT("[%s] AMT_Tunnel_Supplier received illegal message type (%d) disconnecting\n"),identifier(),
messageType));
status = STATUS_ILLEGAL_APF_MESSAGE;
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
break;
}
return processReturnVal(status);
}
// negotiate protocol version
STATUS AMT_Tunnel_Supplier::process_init()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_init"));
STATUS rep = STATUS_SUCCESS;
// Check tunnel state
if (tunnelState() != AMT_Tunnel_Handler::SESSION_INIT)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received protocol version in invalid state (%d)\n"),
tunnelState()));
return STATUS_INVALID_TUNNEL_STATE;
}
APF_ProtocolVersion his_version;
// First read AMT version message
if ((rep = his_version.read(getPeer())) != STATUS_SUCCESS){
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed reading AMT version message\n")));
return rep;
}
// Validate the version message format.
if (his_version.triggerReason < USER_INITIATED_REQUEST ||
his_version.triggerReason > PERIODIC_REQUEST)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received invalid version message\n")));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return STATUS_ILLEGAL_APF_MESSAGE;
}
// Save trigger reason and UUID
trigger_reason_ = his_version.triggerReason;
for (int i=0; i < 16; i++)
UUID_[i] = his_version.systemId[i];
// Send version reply to AMT
APF_ProtocolVersion my_version;
my_version.majorVersion = (ACE_UINT32)APF_PROTOCOL_VERSION_MAJOR;
my_version.minorVersion = (ACE_UINT32)APF_PROTOCOL_VERSION_MINOR;
// for debug
my_version.triggerReason = 0;
for (int i=0; i < 16; i++)
{
my_version.systemId[i] = (ACE_UINT8)i;
my_version.reserved[i] = (ACE_UINT32)i;
}
if ((rep = consumer()->send_APF_message(my_version)) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to send version message\n")));
return rep;
}
// Decide the protocol version as the smallest
major_version_ = my_version.majorVersion;
minor_version_ = my_version.minorVersion;
// This implementation only supports one protocol version
// If AMTs protocol is lower reject this connection
if ((his_version.majorVersion < my_version.majorVersion) ||
((his_version.majorVersion == my_version.majorVersion &&
his_version.minorVersion < my_version.minorVersion)))
{
ACE_DEBUG((MY_WARNING
ACE_TEXT("[%s] Unsupported APF version (%d.%d)\n"),identifier(),
his_version.majorVersion, his_version.minorVersion));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED);
return STATUS_ILLEGAL_APF_MESSAGE;
}
// once agreed upon, we completely ignore the protocol version for now.
tunnelState(AMT_Tunnel_Handler::SESSION_OPENED);
unsigned char textUUID[TEXT_UUID_SIZE];
StringFromUUID(UUID_, textUUID);
tunnel_handler_->set_identifier(ACE_CString((char*)textUUID,TEXT_UUID_SIZE));
ACE_DEBUG ((MY_INFO
ACE_TEXT ("Intel remote client %s is now connected.\n"),
identifier()));
return STATUS_SUCCESS;
}
// handle disconnect message
STATUS AMT_Tunnel_Supplier::process_disconnect()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_disconnect"));
STATUS rep;
APF_Disconnect msg;
if ((rep = msg.read(getPeer())) != STATUS_SUCCESS){
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed reading disconnect message\n")));
return STATUS_NETWORK_ERROR;
}
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("Tunnel disconnected (reason code:%d)\n"),
msg.reason));
//close socket for write:
getPeer().close_writer();
//set disconnect params - so later on, on handle_close, we will inform consumer to close itself.
tunnel_handler_->_disconnect_data.setParams(false, PRIO_HIGH);
// Remove this supplier from the reactor
return STATUS_CONNECTION_CLOSED;
}
// handle service request
STATUS AMT_Tunnel_Supplier::process_service_request()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_service_request"));
STATUS rep = STATUS_SUCCESS;
APF_ServiceRequest request;
if ((rep = request.read(getPeer())) != STATUS_SUCCESS) {
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed reading service request message\n")));
return rep;
}
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("Service request: %s\n"),
request.serviceName.c_str()));
// Handle auth SERVICE request
if (request.serviceName.compare(APF_SERVICE_AUTH) == 0)
{
if (tunnelState() != AMT_Tunnel_Handler::SESSION_OPENED)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received APF auth service request in invalid state (%d)\n"),
tunnelState()));
return STATUS_AUTH_FAILURE;
}
tunnelState(AMT_Tunnel_Handler::AUTH_PENDING);
APF_ServiceAccept accept;
accept.serviceName = request.serviceName;
accept.serviceNameLength = request.serviceNameLength;
rep = consumer()->send_APF_message(accept);
CHECK_STATUS_REP(rep, ACE_TEXT("failed to send reply for APF_SERVICE_AUTH request"));
return STATUS_SUCCESS;
}
// Handle port forwarding service request
if (request.serviceName.compare(APF_SERVICE_PFWD) == 0)
{
// We allow port forwarding without authentication for now
// Here we should check whether an authentication is required
const bool* amtNeedAuthentication = getAmtNeedAuthentication();
if (amtNeedAuthentication == NULL)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("Failed to get if AMT authentication is required.")));
return STATUS_FAILURE;
}
if ((*amtNeedAuthentication) &&
(tunnelState() != AMT_Tunnel_Handler::SESSION_AUTHENTICATED))
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received APF pfwd service request in invalid state (%d)\n"),
tunnelState()));
tunnel_handler_->_disconnect_data.setParams(APF_DISCONNECT_ILLEGAL_USER_NAME, true, PRIO_LOW);
return STATUS_INVALID_TUNNEL_STATE;
}
tunnelState(AMT_Tunnel_Handler::PFWD_OPEN);
APF_ServiceAccept accept;
accept.serviceName = request.serviceName;
accept.serviceNameLength = request.serviceNameLength;
rep = consumer()->send_APF_message(accept);
CHECK_STATUS_REP(rep, ACE_TEXT("failed to send reply for APF_SERVICE_PFWD request"));
return STATUS_SUCCESS;
}
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received APF service request with illegal service name (%s)\n"),
request.serviceName.c_str()));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return STATUS_ILLEGAL_APF_MESSAGE;
}
// handle user authentication message
STATUS AMT_Tunnel_Supplier::process_userauth_request()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_userauth_request"));
STATUS rep = STATUS_SUCCESS;
// Check tunnel state
if (tunnelState() != AMT_Tunnel_Handler::AUTH_PENDING)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("received user authentication request in invalid state (%d)\n"),
tunnelState()));
return STATUS_INVALID_TUNNEL_STATE;
}
APF_UserauthRequest request;
if ((rep = request.read(getPeer())) != STATUS_SUCCESS){
ACE_DEBUG((MY_DEBUG
ACE_TEXT("failed to read user authentication request\n")));
return rep;
}
// Authentication parameters seem to be fine.
// Rest of auth depends on dll and parameters, in case of auth failure, a disconnect is issued anyway.
// ==> Can cancel the timeout on tunnel opening .
ACE_DEBUG((MY_DEBUG ACE_TEXT("Got user authentication request, canceling timeout.\n")));
tunnel_handler_->reactor()->cancel_timer(tunnel_handler_);
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("User authentication request\n\tUsername:\t%s\n"),
request.username.c_str()));
// Check method name
if (request.methodName.compare(APF_USERAUTH_PASSWORD) == 0)
{
//verify the user authorized:
// Not currently supported in Linux
#ifdef ACE_WIN32
char error[MAX_DLL_ERR_LEN];
const bool* amtNeedAuthentication = getAmtNeedAuthentication();
const ACE_TString* amtDllName = getAmtDllName();
const ACE_TString* amtDllParameters = getAmtDllParameters();
if (amtNeedAuthentication == NULL || amtDllName == NULL || amtDllParameters == NULL)
{
ACE_DEBUG((MY_INFO ACE_TEXT("Failed to get AMT authentication details.\n"),
identifier(),
error));
return STATUS_AUTH_FAILURE;
}
Authentication_Param amt_auth_params(*amtNeedAuthentication,
*amtDllName,
*amtDllParameters);
if ((amt_auth_params._authenticate)&&
(_amt_auth_func != NULL) &&
(_amt_auth_func (request.username.c_str(),
request.password.c_str(),
amt_auth_params._dllParams.c_str(),
&(error[0]), MAX_DLL_ERR_LEN ) == 0))
{
ACE_DEBUG((MY_INFO ACE_TEXT("[%s] Failed to authenticate Intel remote client: %s\n"),
identifier(),
error));
#if defined (ACE_WIN32) && !defined (ACE_LACKS_WIN32_SERVICES) && defined (_SERVICE)
ACE_CString errStr(error);
if (errStr.find("Parse connection string error") != ACE_CString::npos)
{
m_pLogger.LogErrorEvent(MPS_ERROR, MPS_AUTH_BAD_USAGE);
}
else if (errStr.find("Error opening file.") != ACE_CString::npos)
{
m_pLogger.LogErrorEvent(MPS_ERROR, MPS_AUTH_BAD_FILE);
}
else if (errStr.find("SOAP failure") != ACE_CString::npos)
{
m_pLogger.LogErrorEvent(MPS_ERROR, MPS_AUTH_SOAP_FAILURE);
}
#endif /* ACE_WIN32 && !(ACE_LACKS_WIN32_SERVICES) && (_SERVICE)*/
//prepare reply message:
APF_UserauthFailure auth_failure;
auth_failure.methodNameListLength = (ACE_UINT32)ACE_OS::strlen(APF_USERAUTH_FAILURE_STR);
auth_failure.methodNameList = APF_USERAUTH_FAILURE_STR;
//send the msg:
rep = consumer()->send_APF_message(auth_failure,PRIO_HIGH);
CHECK_STATUS_REP(rep, ACE_TEXT("failed to send reply for APF_USERAUTH_FAILURE request\n"));
return STATUS_AUTH_FAILURE;
}
#endif /* ACE_WIN32 */
ACE_DEBUG((MY_DEBUG ACE_TEXT("authentication SUCCESS\n")));
}
else if(request.methodName.compare(APF_USERAUTH_NONE) == 0)
{
const bool* amtNeedAuthentication = getAmtNeedAuthentication();
if (amtNeedAuthentication == NULL)
{
ACE_DEBUG((MY_INFO ACE_TEXT("Failed to get if AMT authentication is required.")));
return STATUS_AUTH_FAILURE;
}
if(*amtNeedAuthentication)
{
ACE_DEBUG((MY_INFO ACE_TEXT("[%s] Failed to authenticate Intel remote client, no authentication provided\n"), identifier()));
//prepare reply message:
APF_UserauthFailure auth_failure;
auth_failure.methodNameListLength = (ACE_UINT32)ACE_OS::strlen(APF_USERAUTH_FAILURE_STR);
auth_failure.methodNameList = APF_USERAUTH_FAILURE_STR;
//send the msg:
rep = consumer()->send_APF_message(auth_failure,PRIO_HIGH);
CHECK_STATUS_REP(rep, ACE_TEXT("failed to send reply for APF_USERAUTH_FAILURE request\n"));
return STATUS_AUTH_FAILURE;
}
else
{
// Password is not needed - let him in.
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("\tNo password required\n")));
}
}
else
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: invalid method name (%s) in user authentication request\n"),
request.methodName.c_str()));
return STATUS_ILLEGAL_APF_MESSAGE;
}
tunnelState(AMT_Tunnel_Handler::SESSION_AUTHENTICATED);
// For now we always accept the user
rep = consumer()->send_APF_message((ACE_UINT8)APF_USERAUTH_SUCCESS);
CHECK_STATUS_REP(rep, ACE_TEXT("failed to send reply for APF_USERAUTH_SUCCESS request\n"));
return STATUS_SUCCESS;
}
// read a global message from the socket and process it.
STATUS AMT_Tunnel_Supplier::process_global_message()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_global_message\n"));
STATUS rep = STATUS_SUCCESS;
APF_GlobalRequestHeader header;
if ((rep = header.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read global message\n")));
return rep;
}
// No need for PFWD in UDP
if (header.requestString.compare(APF_UDP_SENDTO) == 0)
{
return process_udp_send_to();
}
if (tunnelState() != AMT_Tunnel_Handler::PFWD_OPEN)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received global message in invalid state\n")));
return STATUS_INVALID_TUNNEL_STATE;
}
if (header.requestString.compare(APF_TCP_FORWARD_REQUEST) == 0)
{
return process_tcp_forward();
}
if (header.requestString.compare(APF_TCP_FORWARD_CANCEL) == 0)
{
return process_tcp_forward_cancel();
}
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: invalid global message string\n\t%s\n"),
header.requestString.c_str()));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return STATUS_ILLEGAL_APF_MESSAGE;
}
// read a tcp forward request from the socket and process it.
STATUS AMT_Tunnel_Supplier::process_tcp_forward()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_tcp_forward\n"));
APF_TcpForwardRequest request;
APF_TcpForwardReply reply;
STATUS rep;
if ((rep = request.read(getPeer())) != STATUS_SUCCESS){
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read tcp forward request\n")));
return rep;
}
//removes '[' ']' if exists (legal in ipv6)
// ACE_CString addr_to_bind = request.addressToBind;
if (request.addressToBind.find("[") != ACE_CString::npos)
{
request.addressToBind = request.addressToBind.substr(request.addressToBind.find('[')+1, request.addressToBind.find(']')-1);
request.addressToBindLength = request.addressToBind.length();
}
{
ACE_WRITE_GUARD_RETURN( ACE_RW_Thread_Mutex,
lock,
Tunnel_Manager::instance().guard(),
STATUS_FAILURE);
// Check if this address and port already exists in the tunnel manager.
AMT_Tunnel_Handler* old_tunnel = NULL;
if ((old_tunnel = Tunnel_Manager::instance().find_tunnel(request.addressToBind, request.port)) != NULL)
{
if (old_tunnel == tunnel_handler_)
{
// Tunnel already exists
rep = consumer()->send_APF_message((ACE_UINT8)APF_REQUEST_FAILURE);
CHECK_STATUS_REP(rep, ACE_TEXT("AMT_Tunnel_Supplier: failed to send tcp forward request failure\n"));
return STATUS_SUCCESS;
}
//if such tunnel exist - close the old one.
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received tcp forward request on existed address and port\n\t%s:%d\n"),
request.addressToBind.c_str(), request.port));
//remove from tunnel mangers map:
tunnel_handler_->removeFromTunnelMgr();
lock.release();
tunnel_handler_->reactor()->remove_handler(old_tunnel, ACE_Event_Handler::READ_MASK);
}
if (request.port == 0)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received tcp forward request with illegal port = 0\n")));
rep = consumer()->send_APF_message((ACE_UINT8)APF_REQUEST_FAILURE);
CHECK_STATUS_REP(rep, ACE_TEXT("AMT_Tunnel_Supplier: failed to send tcp forward request failure\n"));
return STATUS_SUCCESS;
}
(tunnel_handler_)->set_identifier(request.addressToBind);
ACE_DEBUG ((MY_INFO
ACE_TEXT ("Intel remote client %s started port forwarding to address %s:%d\n"),
identifier(), request.addressToBind.c_str(),
request.port));
//save this connection details:
(tunnel_handler_->_tcp_forward_connections).push_back(Port_Address(request.addressToBind, request.port));
int tmp = 0;
if ((tmp = Tunnel_Manager::instance().add_tunnel(tunnel_handler_,
request.addressToBind, request.port)) != 0)
{
reply.status = APF_REQUEST_FAILURE;
}
else
{
// Send the reply back to AMT
reply.status = APF_REQUEST_SUCCESS;
reply.portBound = request.port;
}
}
if (sendAlertToSubscribMCList( mps__ConnectionStateTypeDefinition__CONNECTED,
request.addressToBind,
request.port) == STATUS_FAILURE)
{
ACE_ERROR_RETURN ((MY_WARNING
ACE_TEXT("[%s] Failed to send SOAP notification upon new port forwarding\n"),identifier()),STATUS_FAILURE);
}
if ((rep = consumer()->send_APF_message(reply)) != STATUS_SUCCESS)
{
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("failed to send APF message:TcpForwardReplay\n")));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return rep;
}
return STATUS_SUCCESS;
}
// read a tcp forward cancel request from the socket and process it.
STATUS AMT_Tunnel_Supplier::process_tcp_forward_cancel()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_tcp_forward_cancel"));
STATUS rep = STATUS_SUCCESS;
APF_TcpForwardCancelRequest request;
if ((rep = request.read(getPeer()))!= STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read tcp forward cancel request\n")));
return rep;
}
ACE_DEBUG ((MY_INFO
ACE_TEXT ("Intel remote client %s canceled port forwarding to address %s:%d\n"),
identifier(),
request.addressToBind.c_str(),
request.port));
{
ACE_WRITE_GUARD_RETURN( ACE_RW_Thread_Mutex,
lock,
Tunnel_Manager::instance().guard(),
STATUS_FAILURE);
// Check if this address and port already exists in the tunnel manager.
if (!Tunnel_Manager::instance ().tunnel_exists(request.addressToBind, request.port))
{
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("Tunnel doesn't exists in map\n")));
rep = consumer()->send_APF_message((ACE_UINT8)APF_REQUEST_FAILURE);
CHECK_STATUS_REP(rep, ACE_TEXT("failed to send APF message:TcpForwardCancel\n"));
return STATUS_SUCCESS;
}
Port_Address port_add(request.addressToBind, request.port);
tunnel_handler_->removeTcpForwardConnection(port_add);
}
// Send alert to MC
if (sendAlertToSubscribMCList( mps__ConnectionStateTypeDefinition__DISCONNECTED,
request.addressToBind,
request.port) == -1)
{
ACE_DEBUG ((MY_WARNING
ACE_TEXT("[%s] Failed to send SOAP notification on port forwarding cancellation\n"),identifier()));
}
rep = consumer()->send_APF_message((ACE_UINT8)APF_REQUEST_SUCCESS);
CHECK_STATUS_REP(rep, ACE_TEXT ("failed to send APF message:TcpForwardCancelReplay\n"));
return STATUS_SUCCESS;
}
// read udp send to request from the socket and process it.
STATUS AMT_Tunnel_Supplier::process_udp_send_to()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_udp_send_to"));
STATUS rep;
//read UDP request:
APF_UdpSendTo request;
if ((rep = request.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read UDP send to message\n")));
return rep;
}
// Check if can send a message to that server using the filter hash
// (specified in the configuration)
const bool* authServersListNeeded = getAuthServersListNeeded();
if (authServersListNeeded == NULL)
{
ACE_DEBUG((MY_INFO
ACE_TEXT("Failed to get if servers list is required\n")));
return STATUS_FAILURE;
}
if ((*authServersListNeeded) && !checkInFilter(request.hostStr, request.port))
{
// Not found MC in filter hash - don't continue to send UDP message.
ACE_DEBUG((MY_INFO
ACE_TEXT("[%s] Did not send UDP to %s:%d - not in filter list\n"),
identifier(),
request.hostStr.c_str(),
request.port));
// Filtering is still a success.
return STATUS_SUCCESS;
}
//send UDP data
ACE_SOCK_Dgram cli_dgram;
ACE_INET_Addr mc_addr;
mc_addr.set(request.port, request.hostStr.c_str());
if (cli_dgram.open(ACE_Addr::sap_any, mc_addr.get_type ()) == -1)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("protocol %d, SOCK_Dgram open FAILURE\n"),
mc_addr.get_type()));
// We are not closing the tunnel if the udp send failed
return STATUS_RECOVER_ERROR;
}
else if (cli_dgram.send (request.data->base(), request.dataLength, mc_addr) == -1)
{
ACE_DEBUG((MY_WARNING
ACE_TEXT("[%s] Intel remote client failed to send a UDP message to %s:%d\n"),
identifier(),request.hostStr.c_str(),request.port));
// We are not closing the tunnel if the udp send failed
cli_dgram.close();
return STATUS_RECOVER_ERROR;
}
cli_dgram.close();
ACE_DEBUG((MY_INFO
ACE_TEXT("[%s] Intel remote client send a UDP message to %s:%d\n"),
identifier(),
request.hostStr.c_str(),
request.port));
return STATUS_SUCCESS;
}
bool AMT_Tunnel_Supplier::checkInFilter(const ACE_CString& host, const ACE_UINT32& port)
{
// this check is a sanity check so no error will occur later.
if (port > USHRT_MAX)
return false;
char bufPort[PORT_STR_LENGTH + 1];
ACE_OS::sprintf(bufPort, "%d", port);
ACE_TString addressStr = host + DELIMITER_HOST_PORT + bufPort;
AuthServerHash &filterHash = *getChangableAutherizedServersHash();
if (&filterHash == NULL)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("Failed to get changeable authorized server hash.\n")));
return false;
}
ACE_READ_GUARD_RETURN(ACE_RW_Thread_Mutex,
lock,
filterHash.guard(),
false);
return (filterHash.find(addressStr) != filterHash.end());
}
// Handle channel open reply
STATUS AMT_Tunnel_Supplier::process_channel_open_reply(ACE_UINT8 status)
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_channel_open_reply"));
// Check tunnel state
if (tunnelState() != AMT_Tunnel_Handler::PFWD_OPEN)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT ("AMT_Tunnel_Supplier: channel open direct request with illegal state\n")));
return STATUS_INVALID_TUNNEL_STATE;
}
STATUS rep;
APF_ChannelOpenReply reply;
if ((rep = reply.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read channel open reply message\n")));
return rep;
}
ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, lock, channel_manager().guard(),STATUS_FAILURE);
// Get the channel from map
AMT_Channel *ch = NULL;
ch = channel_manager().find_channel(reply.recipientChannel,
Channel_Manager::MPS_ENDPOINT);
if (ch == NULL || ch->getState() != AMT_Channel::PENDING_OPEN)
{
// Channel doesn't exists - error
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier::channel_open_reply Channel doesn't exists\n")));
return STATUS_INVALID_CHANNEL;
}
// If confirmation
if (status == APF_CHANNEL_OPEN_CONFIRMATION)
{
ACE_DEBUG((MY_INFO
ACE_TEXT("Channel between Intel remote client %s and management console %s opened. Channel ID [%d:%d]\n"),
identifier(),
((SocksConsumer*)(ch->getTcpConsumer()))->identifier(),
reply.recipientChannel,reply.senderChannel));
ch->setAMTid(reply.senderChannel);
if ((channel_manager().add_amt_id(reply.recipientChannel,
reply.senderChannel)) != 0)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier::channel_open_reply invalid senderChannel\n")));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return STATUS_ILLEGAL_APF_MESSAGE;
}
ch->setState(AMT_Channel::OPEN);
// Send reply to consumers
// We don't check the return code of the following, if a failure in the
// tcp consumer/channel consumer occurred we expect the channel to be closed
((SocksConsumer*)(ch->getTcpConsumer()))->openRep(Tcp_Consumer::SUCCESS);
ch->getChannelConsumer()->activateChannel(reply.senderChannel,reply.initialWindowSize);
}
else if (status == APF_CHANNEL_OPEN_FAILURE)
{
ACE_DEBUG((MY_WARNING
ACE_TEXT("[%s] Intel remote client rejected connection request\n"),identifier()));
// Delete channel from map
channel_manager().remove_channel(reply.recipientChannel,
Channel_Manager::MPS_ENDPOINT);
ch->getChannelConsumer()->channelOpenFailure();
((SocksConsumer*)ch->getTcpConsumer())->openRep(Tcp_Consumer::FAILURE);
ch->getTcpConsumer()->connectionClose();
delete ch;
}
else
{
// impossible. sanity check
ACE_ERROR((MY_DEBUG
ACE_TEXT(" channel open reply failure. unknown status = %d\n"),
status));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return STATUS_ILLEGAL_APF_MESSAGE;
}
return STATUS_SUCCESS;
}
//-------------------------------------------------
// Process a channel open request from AMT.
//-------------------------------------------------
STATUS AMT_Tunnel_Supplier::process_channel_open_direct()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_channel_open_direct"));
if (tunnelState() != AMT_Tunnel_Handler::PFWD_OPEN)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT ("AMT_Tunnel_Supplier channel open direct request with illegal state\n")));
return STATUS_INVALID_TUNNEL_STATE;
}
STATUS rep = STATUS_FAILURE;
//read message:
APF_ChannelOpenDirectRequest request;
if ((rep = request.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read channel open direct request\n")));
return rep;
}
// Verify APF message
if (request.channelTypeString.compare(APF_CHANNEL_OPEN_DIRECT_FORWARD) != 0)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received channel open direct request with invalid type (%s)\n"),
request.channelTypeString.c_str()));
return STATUS_ILLEGAL_APF_MESSAGE;
}
ACE_DEBUG((MY_DEBUG
ACE_TEXT ("Received Channel Open Direct Request (%s:%d)\n"),
request.targetHostString.c_str(),
request.targetPort));
const bool* authServersListNeeded = getAuthServersListNeeded();
if (authServersListNeeded == NULL)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("Failed to get if servers list is required.\n")));
return STATUS_FAILURE;
}
if ((*authServersListNeeded) && !checkInFilter(request.targetHostString, request.targetPort))
{
// Not found MC in filter hash - don't continue to send TCP message.
ACE_DEBUG((MY_INFO
ACE_TEXT("[%s] Did not send TCP to %s:%d - not in filter list\n"),
identifier(),
request.targetHostString.c_str(),
request.targetPort));
//send failure reply:
consumer()->channelOpenDirectRep(false,request.senderChannel, NULL, NULL);
// Filtering is still a success.
return STATUS_SUCCESS;
}
ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, lock, channel_manager().guard(),STATUS_FAILURE);
// Create a new pending channel
AMT_Channel *ch = channel_manager().create_channel(request.senderChannel);
if (ch == NULL)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier denied open direct request, invalid sender channel or no more channels available!!!\n")));
consumer()->channelOpenDirectRep(false,request.senderChannel, NULL, NULL);
return STATUS_SUCCESS;
}
// Update the channel details
ch->setWindowSize(*getMaximumWindowSize());
ch->setState(AMT_Channel::PENDING_OPEN);
//create tcp:
Tcp_Svc_Handler* tcp;
ACE_NEW_RETURN (tcp, Tcp_Svc_Handler(request.initialWindowSize, ch->getAMTid(), consumer()), STATUS_MALLOC_FAILURE);
//set tcp handlers addresses:
ACE_INET_Addr remote_addr(request.targetPort, request.targetHostString.c_str(),AF_INET);
tcp->remote_addr(remote_addr);
ACE_INET_Addr local_addr(request.targetPort, request.originatorIpAddress.c_str(),AF_INET);
tcp->local_addr(local_addr);
//connect TCP handler:
Connection_Handler_Connector* connector = &Connection_Handler_Connector::instance();
//NOTE:
// the connection performed in sync way (blocking until connection will complete)
if (connector->initiate_connection(tcp) == -1)
{
//send failure reply:
consumer()->channelOpenDirectRep(false,ch->getAMTid(), NULL, NULL, ch->getMPSid());
channel_manager().remove_channel(ch->getMPSid(), Channel_Manager::MPS_ENDPOINT);
delete ch;
}
return STATUS_SUCCESS;
}
// Process channel windows adjust message
STATUS AMT_Tunnel_Supplier::process_channel_window_adjust()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_channel_window_adjust"));
if (tunnelState() != AMT_Tunnel_Handler::PFWD_OPEN)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT ("AMT_Tunnel_Supplier: received channel window adjust with illegal state\n")));
return STATUS_INVALID_TUNNEL_STATE;
}
STATUS rep;
APF_ChannelWindowAdjust msg;
AMT_Channel *ch = NULL;
if ((rep = msg.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read channel window adjust message\n")));
return rep;
}
ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, lock, channel_manager().guard(),STATUS_FAILURE);
// Get the channel from the map
ch = channel_manager().find_channel(msg.recipientChannel,
Channel_Manager::MPS_ENDPOINT);
if (ch == NULL)
{
// Channel doesn't exist - according do APF protocol
return STATUS_SUCCESS;
}
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("Channel window adjust: AMT(%d) => MC(%d), size = %d\n"),
ch->getAMTid(),
ch->getMPSid(),
msg.bytesToAdd));
if (ch->getChannelConsumer() == NULL)
{
return STATUS_FATAL_ERROR;
}
// Here we give CPU time to the channel consumer (to put messages into our consumer)
if (ch->getChannelConsumer()->setWinSize(msg.bytesToAdd) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("failed to set window size in process_channel_window_adjust")));
}
return STATUS_SUCCESS;
}
// process channel data
STATUS AMT_Tunnel_Supplier::process_channel_data()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_channel_data"));
ACE_DEBUG((MY_TRACE
ACE_TEXT("[%s] AMT_Tunnel_Supplier::process_channel_data\n"), identifier()));
APF_ChannelData msg;
STATUS rep = STATUS_SUCCESS;
if (tunnelState() != AMT_Tunnel_Handler::PFWD_OPEN)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT ("AMT_Tunnel_Supplier: received channel data with illegal state\n")));
return STATUS_INVALID_TUNNEL_STATE;
}
if ((rep = msg.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("[%s] AMT_Tunnel_Supplier: failed to read channel data message\n"), identifier()));
return rep;
}
ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, lock, channel_manager().guard(),STATUS_FAILURE);
// Get the channel from map
AMT_Channel *ch = NULL;
ch = channel_manager().find_channel(msg.recipientChannel,
Channel_Manager::MPS_ENDPOINT);
if (ch == NULL)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("received data from AMT but failed to find the match channel\n")));
// Channel doesn't exists - error
return STATUS_FAILURE;
}
else if ((ch->getState() != AMT_Channel::OPEN) && (ch->getState() != AMT_Channel::MC_CLOSED))
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("received data from AMT but channel not in OPEN state\n")));
return STATUS_FAILURE;
}
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("[%s] Channel data: AMT(%d) => MC(%d), size = %d\n"),
identifier(),
ch->getAMTid(),
ch->getMPSid(),
msg.dataLen));
rep = ch->getTcpConsumer()->sendData(msg.data);
if (rep != STATUS_SUCCESS)
{
ACE_DEBUG ((MY_DEBUG
ACE_TEXT("failed to send data to MC\n")));
}
if (ch->getWindowSize() < msg.dataLen)
{
ACE_DEBUG ((MY_DEBUG ACE_TEXT("received more data to send then window size\n")));
ch->setWindowSize(0);
}
else
{
ch->setWindowSize(ch->getWindowSize() - msg.dataLen);
}
if (ch->getWindowSize() <= *getMinimumWindowSize())
{
APF_ChannelWindowAdjust win_adj;
win_adj.recipientChannel = ch->getAMTid();
win_adj.bytesToAdd = *getMaximumWindowSize() - ch->getWindowSize();
rep = this->consumer()->send_APF_message(win_adj);
CHECK_STATUS_REP(rep, ACE_TEXT("failed to send APF:Window Adjust message\n"));
ch->setWindowSize(*getMaximumWindowSize());
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("Channel window adjust: MC(%d) => AMT(%d), size = %d\n"),
ch->getMPSid(),
ch->getAMTid(),
win_adj.bytesToAdd));
}
return rep;
}
// Process channel close message
STATUS AMT_Tunnel_Supplier::process_channel_close()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_channel_close"));
ACE_DEBUG((MY_DEBUG ACE_TEXT("AMT_Tunnel_Supplier::process_channel_close\n")));
APF_ChannelClose msg;
STATUS rep = STATUS_SUCCESS;
if (tunnelState() != AMT_Tunnel_Handler::PFWD_OPEN)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT ("AMT_Tunnel_Supplier: received channel close with illegal state\n")));
return STATUS_INVALID_TUNNEL_STATE;
}
if ((rep = msg.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read channel close message\n")));
return rep;
}
// Get lock on channel manager
ACE_GUARD_RETURN( ACE_Recursive_Thread_Mutex,
lock,
channel_manager().guard(),
STATUS_FAILURE);
// Get the channel from map
AMT_Channel *ch = NULL;
ch = channel_manager().find_channel(msg.recipientChannel,
Channel_Manager::MPS_ENDPOINT);
if (ch == NULL)
{
// Channel doesn't exists - error
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received channel close on invalid channel\n")));
return STATUS_FAILURE;
}
Tcp_Consumer* tcp_consumer = ch->getTcpConsumer();
ch->setTcpConsumer(NULL);
// The MC send close request first, we can delete this channel
if (ch->getState() == AMT_Channel::MC_CLOSED)
{
ACE_DEBUG((MY_INFO
ACE_TEXT("Channel between Intel remote client %s and management console %s closed. Channel ID [%d:%d]\n"),
identifier(), tcp_consumer->identifier(),ch->getAMTid(),ch->getMPSid()));
if (ch->getChannelConsumer() != NULL)
{
ch->getChannelConsumer()->connectionUnbind();
}
// Remove this channel from both maps
channel_manager().remove_channel(msg.recipientChannel, Channel_Manager::MPS_ENDPOINT);
delete ch;
}
// Check if AMT requested to close this channel
else if (ch->getState() == AMT_Channel::OPEN) {
ch->setState(AMT_Channel::TUNNEL_CLOSED);
// Notify this channel consumer that we are closed
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: Channel close MC(%d)\n"),
msg.recipientChannel));
ch->getChannelConsumer()->channelClose();
}
else {
// received close channel on illegal state
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: received close channel on illegal state\n")));
return STATUS_FAILURE;
}
lock.release();
// Notify consumer to close
if (tcp_consumer!= NULL)
{
tcp_consumer->connectionClose();
}
return STATUS_SUCCESS;
}
// Close this supplier, called from the reactor after read mask close
STATUS AMT_Tunnel_Supplier::handle_close()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::close"));
return STATUS_CONNECTION_CLOSED;
}
STATUS AMT_Tunnel_Supplier::process_KeepAliveReq()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_KeepAliveReq"));
APF_KeepAliveReq msg;
STATUS rep = STATUS_SUCCESS;
//if (tunnelState() != AMT_Tunnel_Handler::PFWD_OPEN)
//{
// ACE_DEBUG((MY_ERROR
// ACE_TEXT ("AMT_Tunnel_Supplier: received channel close with illegal state\n")));
// return STATUS_INVALID_TUNNEL_STATE;
//}
if ((rep = msg.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read keepAlive message\n")));
return rep;
}
APF_KeepAliveReply reply;
reply._cookie = msg._cookie;
if ((rep = consumer()->send_APF_message(reply)) != STATUS_SUCCESS)
{
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("failed to send APF message:KeepAliveReply\n")));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return rep;
}
return STATUS_SUCCESS;
}
STATUS AMT_Tunnel_Supplier::process_KeepAliveOptionReq()
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::process_KeepAliveOptionReq"));
APF_KeepAliveOptionReq msg;
STATUS rep = STATUS_SUCCESS;
if ((rep = msg.read(getPeer())) != STATUS_SUCCESS)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("AMT_Tunnel_Supplier: failed to read keepAlive message\n")));
return rep;
}
APF_KeepAliveOptionReply reply;
reply._keepalive_interval = 0;
reply._read_timeout = 0;
if ((rep = consumer()->send_APF_message(reply)) != STATUS_SUCCESS)
{
ACE_DEBUG ((MY_DEBUG
ACE_TEXT ("failed to send APF message:KeepAliveReply\n")));
setDisconnectReason(APF_DISCONNECT_PROTOCOL_ERROR);
return rep;
}
return STATUS_SUCCESS;
}
//-----------------------------------------
// Parses 16 bytes of UUID sent from AMT
// device in hello message to UUID string format.
//
// Arguments:
// @binUUID - UUID to convert
// @textUUID - [out] UUID string in correct format
//
//-----------------------------------------
void StringFromUUID(const unsigned char binUUID[16],
unsigned char textUUID[TEXT_UUID_SIZE])
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::StringFromUUID"));
unsigned char *hexString = (unsigned char *)binUUID;
int res = sprintf_s((char *)textUUID, TEXT_UUID_SIZE, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
*(unsigned long *) (hexString),
*(unsigned short *)(hexString+4),
*(unsigned short *)(hexString+4+2),
*(unsigned char *) (hexString+4+2+2),
*(unsigned char *) (hexString+4+2+2+1),
*(unsigned char *) (hexString+4+2+2+2),
*(unsigned char *) (hexString+4+2+2+3),
*(unsigned char *) (hexString+4+2+2+4),
*(unsigned char *) (hexString+4+2+2+5),
*(unsigned char *) (hexString+4+2+2+6),
*(unsigned char *) (hexString+4+2+2+7)
);
if (res == -1) {
ACE_ERROR((MY_ERROR
ACE_TEXT(" Failed to parse UUID sent from AMT to string\n")));
}
}
STATUS AMT_Tunnel_Supplier::sendAlertToSubscribMCList( mps__ConnectionStateTypeDefinition state,
ACE_CString &fqdn,
unsigned short port)
{
ACE_TRACE(ACE_TEXT("AMT_Tunnel_Supplier::sendAlertToSubscribMCList"));
ACE_CString str_state;
if (state == mps__ConnectionStateTypeDefinition__CONNECTED)
str_state = "CONNECT";
else
str_state = "DISCONNECT";
unsigned char textUUID[TEXT_UUID_SIZE];
StringFromUUID(UUID_, textUUID);
ACE_CString fqdn_upper_case=toUpper(fqdn);
ACE_DEBUG((MY_DEBUG
ACE_TEXT("Sending notification to management console\n\tDevice = %s:%d - %s\n"),
fqdn_upper_case.c_str(), port, str_state.c_str()));
string temp_fqdn(fqdn_upper_case.c_str());
string temp_uuid((char*)textUUID);
string temp_hostname((*getMCSocksListenIP()).c_str());
const unsigned short* mcHttpListenPort = getMCHttpListenPort();
const unsigned short* mcSocksListenPort = getMCSocksListenPort();
if (mcHttpListenPort == NULL || mcSocksListenPort == NULL)
{
ACE_DEBUG((MY_DEBUG
ACE_TEXT("Failed to get MC authentication details.\n")));
return STATUS_FAILURE;
}
DevicePresence::instance().sendEvent(
temp_fqdn,
port,
temp_uuid,
temp_hostname,
*mcHttpListenPort,
*mcSocksListenPort,
state);
return STATUS_SUCCESS;
}
const char* AMT_Tunnel_Supplier::identifier()
{
return tunnel_handler_->identifier();
}