From 6d2e37e7fc60f63b501fe5cb6aef334b3523b18a Mon Sep 17 00:00:00 2001 From: Mudit Vats Date: Fri, 30 Oct 2020 09:51:18 -0700 Subject: [PATCH] Update amtinfo, usage and admin check. General code cleanup and bug fixes. --- CMakeLists.txt | 7 +- MicroLMS/heci/PTHICommand.c | 4 +- MicroLMS/microstack/ILibParsers.c | 4 +- README.md | 2 - activation.cpp | 10 +- args.cpp | 53 ++++++++- args.h | 1 + commands.cpp | 112 +++++++++++++++++-- commands.h | 24 ++++- info.cpp | 171 ++++++++++++++++++++++++------ info.h | 4 +- main.cpp | 103 +++++++++--------- usage.cpp | 87 +++++++++------ 13 files changed, 434 insertions(+), 148 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e14006..a50f3cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,11 +58,14 @@ find_package(Boost COMPONENTS system REQUIRED) # Find OpenSSL find_package(OpenSSL) +# Find ZLIB +find_package(ZLIB) + # Download and build CppRestSDK, If GIT_TAG is changed then need to delete cpprestsdk-prefix because UPDATE_COMMAND is set to "" include(ExternalProject) ExternalProject_Add(cpprestsdk GIT_REPOSITORY https://github.com/Microsoft/cpprestsdk.git - GIT_TAG v2.10.14 + GIT_TAG v2.10.16 CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=0 -DBUILD_SAMPLES=OFF -DBUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=/../../install TEST_COMMAND "" UPDATE_COMMAND "" @@ -72,7 +75,7 @@ set(CPPRESTSDK_LIBARIES ${SOURCE_DIR}/../../install/lib/) set(CPPRESTSDK_INCLUDE_DIR ${SOURCE_DIR}/../../install/include/) add_library(cpprest INTERFACE) -target_link_libraries(cpprest INTERFACE ${CPPRESTSDK_LIBARIES}/libcpprest.a OpenSSL::SSL OpenSSL::Crypto ${Boost_LIBRARIES} Threads::Threads) +target_link_libraries(cpprest INTERFACE ${CPPRESTSDK_LIBARIES}/libcpprest.a OpenSSL::SSL OpenSSL::Crypto ${Boost_LIBRARIES} Threads::Threads ZLIB::ZLIB) target_include_directories(cpprest INTERFACE ${CPPRESTSDK_INCLUDE_DIR}) else (UNIX) diff --git a/MicroLMS/heci/PTHICommand.c b/MicroLMS/heci/PTHICommand.c index c43504d..154bd61 100644 --- a/MicroLMS/heci/PTHICommand.c +++ b/MicroLMS/heci/PTHICommand.c @@ -898,7 +898,7 @@ AMT_STATUS pthi_GetRemoteAccessConnectionStatus(REMOTE_ACCESS_STATUS *remoteAcce AMT_STATUS _verifyRemoteAccessConnectionStatus(const CFG_GET_REMOTE_ACCESS_CONNECTION_STATUS_RESPONSE *response) { ULONG ByteCount = response->Header.Header.Length; - if (ByteCount != (sizeof(CFG_GET_REMOTE_ACCESS_CONNECTION_STATUS_RESPONSE) - sizeof(PTHI_MESSAGE_HEADER) - sizeof(CHAR *) + response->MpsHostname.Length)) return PTSDK_STATUS_INTERNAL_ERROR; + if (ByteCount < (sizeof(CFG_GET_REMOTE_ACCESS_CONNECTION_STATUS_RESPONSE) - sizeof(PTHI_MESSAGE_HEADER) - sizeof(CHAR*))) return PTSDK_STATUS_INTERNAL_ERROR; return AMT_STATUS_SUCCESS; } @@ -1347,7 +1347,7 @@ AMT_STATUS pthi_SetHostFQDN(char* str) AMT_STATUS status; UINT8 *readBuffer = NULL; CFG_SET_HOST_FQDN_REQUEST command; - int len = (int)strnlen_s(str, _MAX_PATH); + int len = (int)strnlen_s(str, 256); memset(&command, 0, sizeof(CFG_SET_HOST_FQDN_REQUEST)); // Fix the valgrind warning command.Header = SET_HOST_FQDN_HEADER; diff --git a/MicroLMS/microstack/ILibParsers.c b/MicroLMS/microstack/ILibParsers.c index 409a20e..de69d3e 100644 --- a/MicroLMS/microstack/ILibParsers.c +++ b/MicroLMS/microstack/ILibParsers.c @@ -2441,8 +2441,8 @@ ILibExportMethod void ILibStartChain(void *Chain) // // Free the pipe resources // - fclose(((ILibBaseChain*)Chain)->TerminateReadPipe); - fclose(((ILibBaseChain*)Chain)->TerminateWritePipe); + if (((ILibBaseChain*)Chain)->TerminateReadPipe != NULL) {fclose(((ILibBaseChain*)Chain)->TerminateReadPipe);} + if (((ILibBaseChain*)Chain)->TerminateWritePipe != NULL) {fclose(((ILibBaseChain*)Chain)->TerminateWritePipe);} ((ILibBaseChain*)Chain)->TerminateReadPipe=0; ((ILibBaseChain*)Chain)->TerminateWritePipe=0; #endif diff --git a/README.md b/README.md index 8400006..788706f 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ The Default ("master") branch is our release branch that is for production use. RPC is an application which enables remote capabilities for AMT, such as as device activation. To accomplish this, RPC communicates with the RPS (Remote Provisioning Server). -As a prerequisite, a Local Management Service (LMS) must be installed and running on the operating system. - ## Linux Steps below are for Ubuntu 18.04. diff --git a/activation.cpp b/activation.cpp index 81959db..d758ac8 100644 --- a/activation.cpp +++ b/activation.cpp @@ -17,15 +17,15 @@ bool get_certificate_hashes(web::json::value& hashes) { std::vector hashValues; - std::vector certHashes; + std::vector certHashes; if (!cmd_get_certificate_hashes(certHashes)) { return false; } - for (std::string hashString : certHashes) + for (cert_hash_entry hashString : certHashes) { - hashValues.push_back(web::json::value::string(utility::conversions::convertstring(hashString))); + hashValues.push_back(web::json::value::string(utility::conversions::convertstring(hashString.hash))); } hashes = web::json::value::array(hashValues); @@ -269,10 +269,6 @@ bool act_create_request(std::string commands, std::string dns_suffix, std::strin utility::string_t payload = utility::conversions::to_string_t(encodedPayload); msg[U("payload")] = web::json::value::string(payload); -#ifdef DEBUG - std::cout << "Activation info payload:" << serializedPayload << std::endl; -#endif - // serialize the entire message request = utility::conversions::to_utf8string(msg.serialize()); diff --git a/args.cpp b/args.cpp index 17028c9..63ac07c 100644 --- a/args.cpp +++ b/args.cpp @@ -21,6 +21,19 @@ bool get_arg_exists(int argc, char* argv[], const char* long_opt, const char* sh return false; } +bool get_arg_exists(int argc, char* argv[], const char* opt) +{ + for (int i = 1; i < argc; i++) + { + if ((strcasecmp(argv[i], opt) == 0)) + { + return true; + } + } + + return false; +} + bool get_arg_string(int argc, char* argv[], const char* long_opt, const char* short_opt, std::string& value) { value = ""; @@ -48,14 +61,41 @@ bool get_arg_string(int argc, char* argv[], const char* long_opt, const char* sh return false; } +bool get_arg_string(int argc, char* argv[], const char* opt, std::string& value) +{ + value = ""; + + for (int i = 1; i < argc; i++) + { + if ((strcasecmp(argv[i], opt) == 0)) + { + if (i + 1 < argc) + { + std::string tmp = argv[++i]; + + if (!util_is_printable(tmp)) + { + return false; + } + + value = tmp; + + return true; + } + } + } + + return false; +} + bool args_get_help(int argc, char* argv[]) { - return get_arg_exists(argc, argv, "--help", "-h"); + return get_arg_exists(argc, argv, "--help"); } bool args_get_version(int argc, char* argv[]) { - return get_arg_exists(argc, argv, "--version", "-v"); + return get_arg_exists(argc, argv, "--version"); } bool args_get_url(int argc, char* argv[], std::string& url) @@ -65,7 +105,7 @@ bool args_get_url(int argc, char* argv[], std::string& url) bool args_get_proxy(int argc, char* argv[], std::string& proxy) { - return get_arg_string(argc, argv, "--proxy", "-x", proxy); + return get_arg_string(argc, argv, "--proxy", "-p", proxy); } bool args_get_cmd(int argc, char* argv[], std::string& cmd) @@ -80,5 +120,10 @@ bool args_get_dns(int argc, char* argv[], std::string& dns) bool args_get_info(int argc, char* argv[], std::string& info) { - return get_arg_string(argc, argv, "--info", "-i", info); + return get_arg_string(argc, argv, "--amtinfo", info); } + +bool args_get_verbose(int argc, char* argv[]) +{ + return get_arg_exists(argc, argv, "--verbose", "-v"); +} \ No newline at end of file diff --git a/args.h b/args.h index 7e9918c..1e7f4f0 100644 --- a/args.h +++ b/args.h @@ -15,5 +15,6 @@ bool args_get_proxy(int argc, char* argv[], std::string& proxy); bool args_get_cmd(int argc, char* argv[], std::string& cmd); bool args_get_dns(int argc, char* argv[], std::string& dns); bool args_get_info(int argc, char* argv[], std::string& info); +bool args_get_verbose(int argc, char* argv[]); #endif diff --git a/commands.cpp b/commands.cpp index 7b0b027..453b9f1 100644 --- a/commands.cpp +++ b/commands.cpp @@ -6,6 +6,7 @@ #include "commands.h" #include #include "port.h" +#include "utils.h" #ifndef _WIN32 #include @@ -22,6 +23,13 @@ extern "C" { } #include "version.h" +bool cmd_is_admin() +{ + if (heci_Init(NULL, PTHI_CLIENT) == 0) return false; + + return true; +} + bool cmd_get_version(std::string& version) { version.clear(); @@ -184,8 +192,12 @@ bool cmd_get_dns_suffix(std::string& suffix) if (amt_status == 0) { - std::string tmp(amt_dns_suffix.Buffer, amt_dns_suffix.Length); - suffix = tmp; + if (amt_dns_suffix.Buffer != NULL) + { + std::string tmp(amt_dns_suffix.Buffer, amt_dns_suffix.Length); + suffix = tmp; + free(amt_dns_suffix.Buffer); + } return true; } @@ -222,9 +234,9 @@ bool cmd_get_wired_mac_address(std::vector& address) return false; } -bool cmd_get_certificate_hashes(std::vector& hashes) +bool cmd_get_certificate_hashes(std::vector& hash_entries) { - hashes.clear(); + hash_entries.clear(); // initialize HECI interface if (heci_Init(NULL, PTHI_CLIENT) == 0) return false; @@ -242,28 +254,38 @@ bool cmd_get_certificate_hashes(std::vector& hashes) AMT_STATUS status = pthi_GetCertificateHashEntry(amt_hash_handles.Handles[i], &certhash_entry); int hashSize; + cert_hash_entry tmp; switch (certhash_entry.HashAlgorithm) { case 0: // MD5 hashSize = 16; + tmp.algorithm = "MD5"; break; case 1: // SHA1 hashSize = 20; + tmp.algorithm = "SHA1"; break; case 2: // SHA256 hashSize = 32; + tmp.algorithm = "SHA256"; break; case 3: // SHA512 hashSize = 64; + tmp.algorithm = "SHA512"; break; default: - hashSize = 64; + hashSize = 0; + tmp.algorithm = "UNKNOWN"; break; } if (certhash_entry.IsActive == 1) { + std::string cert_name(certhash_entry.Name.Buffer, certhash_entry.Name.Length); + tmp.name = cert_name; + tmp.is_default = certhash_entry.IsDefault; + tmp.is_active = certhash_entry.IsActive; + std::string hashString; - hashString.clear(); for (int i = 0; i < hashSize; i++) { char hex[10]; @@ -271,7 +293,9 @@ bool cmd_get_certificate_hashes(std::vector& hashes) hashString += hex; } - hashes.push_back(hashString); + tmp.hash = hashString; + + hash_entries.push_back(tmp); } } @@ -280,3 +304,77 @@ bool cmd_get_certificate_hashes(std::vector& hashes) return false; } + +bool cmd_get_remote_access_connection_status(int& network_status, int& remote_status, int& remote_trigger, std::string& mps_hostname) +{ + network_status = 0; + remote_status = 0; + remote_trigger = 0; + mps_hostname = ""; + const int MPS_SERVER_MAXLENGTH = 256; + + // initialize HECI interface + if (heci_Init(NULL, PTHI_CLIENT) == 0) return false; + + // get DNS according to AMT + REMOTE_ACCESS_STATUS remote_access_connection_status; + AMT_STATUS amt_status = pthi_GetRemoteAccessConnectionStatus(&remote_access_connection_status); + + if (amt_status == 0) + { + network_status = remote_access_connection_status.AmtNetworkConnectionStatus; + remote_status = remote_access_connection_status.RemoteAccessConnectionStatus; + remote_trigger = remote_access_connection_status.RemoteAccessConnectionTrigger; + + if (remote_access_connection_status.MpsHostname.Buffer != NULL) + { + if (remote_access_connection_status.MpsHostname.Length < MPS_SERVER_MAXLENGTH) + { + std::string tmp(remote_access_connection_status.MpsHostname.Buffer, remote_access_connection_status.MpsHostname.Length); + if (util_is_printable(tmp)) + { + mps_hostname = tmp; + } + } + + free(remote_access_connection_status.MpsHostname.Buffer); + } + + return true; + } + + return false; +} + +bool cmd_get_lan_interface_settings(lan_interface_settings& lan_interface_settings) +{ + // initialize HECI interface + if (heci_Init(NULL, PTHI_CLIENT) == 0) return false; + + // get wired interface + LAN_SETTINGS lan_settings; + UINT32 interface_settings = 0; // wired=0, wireless=1 + AMT_STATUS amt_status = pthi_GetLanInterfaceSettings(interface_settings, &lan_settings); + if (amt_status == 0) + { + lan_interface_settings.is_enabled = lan_settings.Enabled; + lan_interface_settings.dhcp_mode = lan_settings.DhcpIpMode; + lan_interface_settings.dhcp_enabled = lan_settings.DhcpEnabled; + + lan_interface_settings.ip_address.push_back((lan_settings.Ipv4Address >> 24) & 0xff); + lan_interface_settings.ip_address.push_back((lan_settings.Ipv4Address >> 16) & 0xff); + lan_interface_settings.ip_address.push_back((lan_settings.Ipv4Address >> 8) & 0xff); + lan_interface_settings.ip_address.push_back((lan_settings.Ipv4Address) & 0xff); + + lan_interface_settings.mac_address.push_back(lan_settings.MacAddress[0]); + lan_interface_settings.mac_address.push_back(lan_settings.MacAddress[1]); + lan_interface_settings.mac_address.push_back(lan_settings.MacAddress[2]); + lan_interface_settings.mac_address.push_back(lan_settings.MacAddress[3]); + lan_interface_settings.mac_address.push_back(lan_settings.MacAddress[4]); + lan_interface_settings.mac_address.push_back(lan_settings.MacAddress[5]); + + return true; + } + + return false; +} diff --git a/commands.h b/commands.h index 6f13833..82c2e5a 100644 --- a/commands.h +++ b/commands.h @@ -9,6 +9,26 @@ #include #include +struct cert_hash_entry +{ + std::string hash; + std::string name; + std::string algorithm; + bool is_active; + bool is_default; +}; + +struct lan_interface_settings +{ + bool is_enabled; + bool link_status; + bool dhcp_enabled; + int dhcp_mode; + std::vector ip_address; + std::vector mac_address; +}; + +bool cmd_is_admin(); bool cmd_get_version(std::string& version); bool cmd_get_build_number(std::string& version); bool cmd_get_sku(std::string& version); @@ -17,6 +37,8 @@ bool cmd_get_local_system_account(std::string& username, std::string& password); bool cmd_get_control_mode(int& mode); bool cmd_get_dns_suffix(std::string& suffix); bool cmd_get_wired_mac_address(std::vector& address); -bool cmd_get_certificate_hashes(std::vector& hashes); +bool cmd_get_certificate_hashes(std::vector& hash_entries); +bool cmd_get_remote_access_connection_status(int& network_status, int& remote_status, int& remote_trigger, std::string& mps_hostname); +bool cmd_get_lan_interface_settings(lan_interface_settings& lan_interface_settings); #endif \ No newline at end of file diff --git a/info.cpp b/info.cpp index 16a07d3..ddd3471 100644 --- a/info.cpp +++ b/info.cpp @@ -10,13 +10,16 @@ #include "commands.h" #include "utils.h" -void out_text(const std::string name, const std::vector value, const unsigned char delimeter=' ') +const int PADDING = 25; + +void out_text(const std::string name, const std::vector value, const unsigned char delimeter = ' ', const bool hex = true) { - std::cout << name << ": "; + std::cout << name << std::setfill(' ') << std::setw(PADDING - name.size()) << ": "; int char_count = 1; for (unsigned char tmp : value) { - std::cout << std::setfill('0') << std::setw(2) << std::hex << (unsigned int) tmp; + (hex) ? std::cout << std::setfill('0') << std::setw(2) << std::hex << (unsigned int)tmp + : std::cout << (unsigned int)tmp; if (char_count++ < value.size()) { @@ -29,26 +32,23 @@ void out_text(const std::string name, const std::vector value, co void out_text(const std::string name, const std::string value) { - std::cout << name << ": "; + std::cout << name << std::setfill(' ') << std::setw(PADDING - name.size()) << ": "; std::cout << value; std::cout << std::endl; } void out_text(const std::string name, const int value) { - std::cout << name << ": "; + std::cout << name << std::setfill(' ') << std::setw(PADDING - name.size()) << ": "; std::cout << value; std::cout << std::endl; } void out_text(const std::string name, const std::vector value) { - int count = 1; - - std::cout << name << std::endl; + std::cout << name << std::setfill(' ') << std::setw(PADDING - name.size()) << ": " << std::endl; for (std::string tmp : value) { - std::cout << std::setfill('0') << std::setw(2) << count++ << ":"; std::cout << tmp << std::endl; } } @@ -70,7 +70,7 @@ bool info_get_build_number() if (!cmd_get_build_number(tmp)) return false; - out_text("Build number", tmp); + out_text("Build Number", tmp); return true; } @@ -111,7 +111,7 @@ bool info_get_control_mode() else if (tmp == 1) control_mode = "activated in client control mode"; else if (tmp == 2) control_mode = "activated in admin control mode"; - out_text("Control mode", control_mode); + out_text("Control Mode", control_mode); return true; } @@ -122,29 +122,31 @@ bool info_get_dns_suffix() if (!cmd_get_dns_suffix(tmp)) return false; - out_text("DNS suffix", tmp); - - return true; -} - -bool info_get_wired_mac_address() -{ - std::vector tmp; - - if (!cmd_get_wired_mac_address(tmp)) return false; - - out_text("Wired MAC address", tmp, '-'); + out_text("DNS Suffix", tmp); return true; } bool info_get_certificate_hashes() { + std::vector hash_entries; std::vector tmp; - if (!cmd_get_certificate_hashes(tmp)) return false; + if (!cmd_get_certificate_hashes(hash_entries)) return false; - out_text("Certificate hashes", tmp); + for (cert_hash_entry entry : hash_entries) + { + std::string name = entry.name; + (entry.is_default) ? name += ", (Default, " : ", (Not Default, "; + (entry.is_active) ? name += "Active)" : "Not Active)"; + tmp.push_back(name); + + std::string algorithm = " " + entry.algorithm; + algorithm += ": " + entry.hash; + tmp.push_back(algorithm); + } + + out_text("Certificate Hashes", tmp); return true; } @@ -153,13 +155,99 @@ bool info_get_all() { std::vector tmp; - if (info_get_version() && info_get_build_number() && info_get_sku() && - info_get_uuid() && info_get_control_mode() && info_get_dns_suffix() && - info_get_wired_mac_address() && info_get_certificate_hashes()) + bool status_ver = info_get_version(); + bool status_bld = info_get_build_number(); + bool status_sku = info_get_sku(); + bool status_uuid = info_get_uuid(); + bool status_mode = info_get_control_mode(); + bool status_dns = info_get_dns_suffix(); + bool status_ras = info_get_remote_access_connection_status(); + bool status_lan = info_get_lan_interface_settings(); + bool status_cert = info_get_certificate_hashes(); + + if (status_ver && status_bld && status_sku && status_uuid && status_mode && + status_dns && status_ras && status_lan && status_cert) { return true; } + return false; +} + +bool info_get_remote_access_connection_status() +{ + int network_status; + int remote_status; + int remote_trigger; + std::string mps_hostname; + + if (!cmd_get_remote_access_connection_status(network_status, remote_status, remote_trigger, mps_hostname)) return false; + + std::string tmp; + + switch (network_status) + { + case 0: tmp = "direct"; + break; + case 1: tmp = "vpn"; + break; + case 2: tmp = "outside enterprise"; + break; + case 3: + default: tmp = "unknown"; + break; + } + + out_text("RAS Network", tmp); + + switch (remote_status) + { + case 0: tmp = "not connected"; + break; + case 1: tmp = "connecting"; + break; + case 2: tmp = "connected"; + break; + default: tmp = "unknown"; + break; + } + + out_text("RAS Remote Status", tmp); + + switch (remote_trigger) + { + case 0: tmp = "user initiated"; + break; + case 1: tmp = "alert"; + break; + case 2: tmp = "periodic"; + break; + case 3: tmp = "provisioning"; + break; + default: tmp = "unknown"; + break; + + } + + out_text("RAS Trigger", tmp); + + out_text("RAS MPS Hostname", mps_hostname); + + return true; +} + +bool info_get_lan_interface_settings() +{ + lan_interface_settings tmp; + + if (!cmd_get_lan_interface_settings(tmp)) return false; + + out_text("DHCP Enabled", (tmp.dhcp_enabled) ? "true" : "false"); + out_text("DHCP Mode", (tmp.dhcp_mode == 1) ? "active" : "passive"); + out_text("Link Status", (tmp.link_status) ? "up" : "down"); + out_text("IP Address", tmp.ip_address, '.', false); + out_text("MAC Address", tmp.mac_address, ':'); + return true; } @@ -169,7 +257,7 @@ bool info_get(const std::string info) { return info_get_version(); } - else if (info.compare("build") == 0) + else if (info.compare("bld") == 0) { return info_get_build_number(); } @@ -189,14 +277,18 @@ bool info_get(const std::string info) { return info_get_dns_suffix(); } - else if (info.compare("mac") == 0) - { - return info_get_wired_mac_address(); - } else if (info.compare("cert") == 0) { return info_get_certificate_hashes(); } + else if (info.compare("ras") == 0) + { + return info_get_remote_access_connection_status(); + } + else if (info.compare("lan") == 0) + { + return info_get_lan_interface_settings(); + } else if (info.compare("all") == 0) { return info_get_all(); @@ -204,3 +296,16 @@ bool info_get(const std::string info) return false; } + +bool info_get_verify(const std::string info) +{ + if ((info.compare("ver") == 0) || (info.compare("bld") == 0) || (info.compare("sku") == 0) || + (info.compare("uuid") == 0) || (info.compare("mode") == 0) || (info.compare("dns") == 0) || + (info.compare("cert") == 0) || (info.compare("ras") == 0) || (info.compare("lan") == 0) || + (info.compare("all") == 0)) + { + return true; + } + + return false; +} \ No newline at end of file diff --git a/info.h b/info.h index 43f456e..8a8e470 100644 --- a/info.h +++ b/info.h @@ -9,13 +9,15 @@ #include bool info_get(const std::string info); +bool info_get_verify(const std::string info); bool info_get_version(); bool info_get_build_number(); bool info_get_sku(); bool info_get_uuid(); bool info_get_control_mode(); bool info_get_dns_suffix(); -bool info_get_wired_mac_address(); bool info_get_all(); +bool info_get_remote_access_connection_status(); +bool info_get_lan_interface_settings(); #endif diff --git a/main.cpp b/main.cpp index f409de4..2ad0ba9 100644 --- a/main.cpp +++ b/main.cpp @@ -59,10 +59,11 @@ int main(int argc, char* argv[]) std::string arg_cmd; std::string arg_dns; std::string arg_info; + bool arg_verbose = false; if (argc == 1) { - std::cout << "Use -h, --help for help." << std::endl; + std::cout << "Use --help for help." << std::endl; return 0; } @@ -80,14 +81,24 @@ int main(int argc, char* argv[]) return 0; } + // Check if running in elevated privileges + if (!cmd_is_admin()) + { + std::cout << "Unable to launch application. Please ensure that Intel ME is present, the MEI driver is installed and that this application is run with administrator or root privileges." << std::endl; + return 0; + } + // check for info if (args_get_info(argc, argv, arg_info)) { - if (!info_get(arg_info)) + if (!info_get_verify(arg_info)) { std::cout << "Incorrect or missing arguments." << std::endl; - std::cout << "Use -h, --help for help." << std::endl; + std::cout << "Use --help for help." << std::endl; + return 0; } + + info_get(arg_info); return 0; } @@ -95,10 +106,16 @@ int main(int argc, char* argv[]) if (!args_get_url(argc, argv, arg_url) || !args_get_cmd(argc, argv, arg_cmd)) { std::cout << "Incorrect or missing arguments." << std::endl; - std::cout << "Use -h, --help for help." << std::endl; + std::cout << "Use --help for help." << std::endl; return 0; } + // verbose output + if (args_get_verbose(argc, argv)) + { + arg_verbose = true; + } + // Print version info usage_show_version(); @@ -122,8 +139,8 @@ int main(int argc, char* argv[]) try { // check if LMS is available - SOCKET s = lms_connect(); - closesocket(s); + SOCKET lms_socket = lms_connect(); + closesocket(lms_socket); } catch (...) { @@ -137,10 +154,6 @@ int main(int argc, char* argv[]) } } -#ifdef DEBUG - std::cout << "Activation info: " << std::endl << activation_info << std::endl; -#endif - // webSocket Interface web::websockets::client::websocket_client_config client_config; if (args_get_proxy(argc, argv, arg_proxy)) @@ -149,16 +162,17 @@ int main(int argc, char* argv[]) } #ifdef DEBUG // skip certificate verification if debug build - std::cout << "!!! SKIPPING CERTIFICATE VERIFICATION !!!" << std::endl; + std::cout << "Skipping certificate verification." << std::endl; client_config.set_validate_certificates(false); #endif web::websockets::client::websocket_callback_client client(client_config); std::condition_variable cv; std::mutex mx; - SOCKET s; + SOCKET lms_socket; + memset(&lms_socket, 0, sizeof(SOCKET)); // set receive handler - client.set_message_handler([&client, &mx, &cv, &s](web::websockets::client::websocket_incoming_message ret_msg) + client.set_message_handler([&client, &mx, &cv, &lms_socket, arg_verbose](web::websockets::client::websocket_incoming_message ret_msg) { // kick the timer std::chrono::time_point now = std::chrono::system_clock::now(); @@ -169,10 +183,6 @@ int main(int argc, char* argv[]) { // handle message from server std::string rcv_websocket_msg = ret_msg.extract_string().get(); -#ifdef DEBUG - std::cout << std::endl << "<<<<< Received Message " << std::endl; - std::cout << rcv_websocket_msg << std::endl; -#endif std::cout << "." << std::flush; // dot status output // parse incoming JSON message @@ -224,12 +234,6 @@ int main(int argc, char* argv[]) return; } - -#ifdef DEBUG - std::cout << msgMethod << ", " << msgStatus << ", " << msgMessage << std::endl; - std::cout << rcv_websocket_msg << std::endl; -#endif - // process any messages we can // - if success, done // - if error, get out @@ -280,7 +284,7 @@ int main(int argc, char* argv[]) try { // conntect to lms - s = lms_connect(); + lms_socket = lms_connect(); } catch (...) { @@ -288,22 +292,23 @@ int main(int argc, char* argv[]) return; } -#ifdef DEBUG - std::cout << std::endl << "vvvvv Sending Message " << std::endl; - std::cout << payloadDecoded << std::endl; -#endif + if (arg_verbose) + { + std::cout << std::endl << "vvv -- message to AMT -- vvv" << std::endl; + std::cout << payloadDecoded << std::endl; + } // send message to LMS - if (send(s, payloadDecoded.c_str(), (int)payloadDecoded.length(), 0) < 0) + if (send(lms_socket, payloadDecoded.c_str(), (int)payloadDecoded.length(), 0) < 0) { throw std::runtime_error("error: socket send"); } // handle response message from LMS - int fd = ((int) s) + 1; + int fd = ((int)lms_socket) + 1; fd_set rset; FD_ZERO(&rset); - FD_SET(s, &rset); + FD_SET(lms_socket, &rset); timeval timeout; memset(&timeout, 0, sizeof(timeval)); @@ -328,13 +333,9 @@ int main(int argc, char* argv[]) // read from LMS char recv_buffer[4096]; memset(recv_buffer, 0, 4096); - res = recv(s, recv_buffer, 4096, 0); + res = recv(lms_socket, recv_buffer, 4096, 0); if (res > 0) { -#ifdef DEBUG - std::cout << std::endl << "^^^^^ Received Message" << std::endl; - std::cout << recv_buffer << std::endl; -#endif superBuffer += recv_buffer; } else if (res < 0) @@ -353,31 +354,32 @@ int main(int argc, char* argv[]) // if there is some data send it if (superBuffer.length() > 0) { + if (arg_verbose) + { + std::cout << std::endl << "^^^ -- message from AMT -- ^^^" << std::endl; + std::cout << superBuffer << std::endl; + } + std::string response; if (!act_create_response(superBuffer.c_str(), response)) return; web::websockets::client::websocket_outgoing_message send_websocket_msg; std::string send_websocket_buffer(response); send_websocket_msg.set_utf8_message(send_websocket_buffer); -#ifdef DEBUG - std::cout << std::endl << ">>>>> Sending Message" << std::endl; - std::cout << superBuffer << std::endl; - std::cout << send_websocket_buffer << std::endl; -#endif client.send(send_websocket_msg).wait(); // done - closesocket(s); + closesocket(lms_socket); return; } } - closesocket(s); + closesocket(lms_socket); } catch (...) { std::cerr << std::endl << "Communication error in receive handler." << std::endl; - closesocket(s); + closesocket(lms_socket); } }); @@ -403,12 +405,7 @@ int main(int argc, char* argv[]) { // send activationParams to websocket web::websockets::client::websocket_outgoing_message out_msg; - out_msg.set_utf8_message(activation_info); - -#ifdef DEBUG - std::cout << std::endl << ">>>>> Sending Activiation Info" << std::endl; - std::cout << activation_info << std::endl; -#endif + out_msg.set_utf8_message(activation_info); client.send(out_msg).wait(); } catch (...) @@ -433,10 +430,8 @@ int main(int argc, char* argv[]) client.close().wait(); // clean-up socket - if (s) { - shutdown(s, SD_BOTH); - closesocket(s); - } + shutdown(lms_socket, SD_BOTH); + closesocket(lms_socket); exit(0); } diff --git a/usage.cpp b/usage.cpp index 5947e46..30abebf 100644 --- a/usage.cpp +++ b/usage.cpp @@ -10,41 +10,62 @@ void usage_show_help() { - std::cout << "Usage: " << PROJECT_NAME << " --help | --version | --info | --url --cmd [--proxy ] [--dns ]" << std::endl; - std::cout << "Required:" << std::endl; - std::cout << " -u, --url websocket server" << std::endl; - std::cout << " -c, --cmd server command" << std::endl; - std::cout << "Optional:" << std::endl; - std::cout << " -x, --proxy proxy address and port" << std::endl; - std::cout << " -d, --dns dns suffix" << std::endl; - std::cout << "Informational:" << std::endl; - std::cout << " -h, --help this help text" << std::endl; - std::cout << " -v, --version version" << std::endl; - std::cout << " -i, --info info on an " << std::endl; - std::cout << std::endl; - std::cout << "Info :" << std::endl; - std::cout << " all all items" << std::endl; - std::cout << " ver bios version" << std::endl; - std::cout << " build build number" << std::endl; - std::cout << " sku product sku" << std::endl; - std::cout << " uuid unique identifier" << std::endl; - std::cout << " mode current control mode {0=none, 1=client, 2=admin}" << std::endl; - std::cout << " dns domain name suffix" << std::endl; - std::cout << " mac wired MAC address" << std::endl; - std::cout << " cert certificate hashes" << std::endl; - std::cout << std::endl; - std::cout << "Examples:" << std::endl; - std::cout << " " << PROJECT_NAME << " --url wss://localhost:8080 --cmd \"-t activate --profile profile1\"" << std::endl; - std::cout << " " << PROJECT_NAME << " -u wss://localhost:8080 -c \"-t deactivate --password P@ssw0rd\" -x http://proxy.com:1000" << std::endl; - std::cout << " " << PROJECT_NAME << " -u wss://localhost:8080 -c \"-e [encrypted-command-text] -h [signature-hash]\"" << std::endl; - std::cout << std::endl; - std::cout << "Note:" << std::endl; - std::cout << " Since can contain multiple options and arguments, the entire must be in quotes as shown" << std::endl; - std::cout << " in the examples." << std::endl; + // 80 chars "01234567890123456789012345678901234567890123456789012345678901234567890123456789" + std::cout << "Usage: " << std::endl; + std::cout << " " << PROJECT_NAME << " [optional]" << std::endl; + std::cout << " " << PROJECT_NAME << " " << std::endl; + std::cout << std::endl; + std::cout << "Required:" << std::endl; + std::cout << " -u, --url websocket server" << std::endl; + std::cout << " -c, --cmd server command" << std::endl; + std::cout << std::endl; + std::cout << " Since can contain multiple options and arguments, the entire" << std::endl; + std::cout << " must be in quotes. Please see examples below." << std::endl; + std::cout << std::endl; + std::cout << "Optional:" << std::endl; + std::cout << " -p, --proxy proxy address and port" << std::endl; + std::cout << " -d, --dns dns suffix override" << std::endl; + std::cout << " -v, --verbose verbose output" << std::endl; + std::cout << std::endl; + std::cout << "Informational:" << std::endl; + std::cout << " --help this help text" << std::endl; + std::cout << " --version version" << std::endl; + std::cout << " --amtinfo AMT info on an " << std::endl; + std::cout << std::endl; + std::cout << "Item:" << std::endl; + std::cout << " all all items" << std::endl; + std::cout << " ver BIOS version" << std::endl; + std::cout << " bld build number" << std::endl; + std::cout << " sku product SKU" << std::endl; + std::cout << " uuid unique identifier" << std::endl; + std::cout << " mode current control mode" << std::endl; + std::cout << " dns domain name suffix" << std::endl; + std::cout << " cert certificate hashes" << std::endl; + std::cout << " ras remote access status" << std::endl; + std::cout << " lan LAN settings" << std::endl; + std::cout << std::endl; + std::cout << "Examples:" << std::endl; + std::cout << " # Activate platform using profile1" << std::endl; + std::cout << " " << PROJECT_NAME << \ + " --url wss://localhost:8080 --cmd \"-t activate --profile profile1\"" << std::endl; + std::cout << std::endl; + std::cout << " # Activate platform using profile1 and override DNS detection" << std::endl; + std::cout << " " << PROJECT_NAME << \ + " --url wss://localhost:8080 --cmd \"-t activate --profile profile1\" --dns corp.com" << std::endl; + std::cout << std::endl; + std::cout << " # Deactivate platform and connect through a proxy" << std::endl; + std::cout << " " << PROJECT_NAME << \ + " -u wss://localhost:8080 -c \"-t deactivate --password P@ssw0rd\" -p http://proxy.com:1000" << std::endl; + std::cout << std::endl; + std::cout << " # Show all informational items" << std::endl; + std::cout << " " << PROJECT_NAME << " --amtinfo all" << std::endl; } void usage_show_version() { - std::cout << PROJECT_NAME << " " << PROJECT_VER << std::endl; - std::cout << "protocol " << PROTOCOL_VERSION << std::endl; + std::string project_name = PROJECT_NAME; + for (auto& c : project_name) c = toupper(c); // get upper case string + + std::cout << project_name << " " << PROJECT_VER << "." << std::endl; + std::cout << "Protocol " << PROTOCOL_VERSION << "." << std::endl; } \ No newline at end of file