host/securitylib/csgetfingerprint.h (326 lines of code) (raw):
///
/// \file csgetfingerprint.h
///
/// \brief
///
#ifndef CSGETFINGERPRINT_H
#define CSGETFINGERPRINT_H
#include <sstream>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "csclient.h"
#include "defaultdirs.h"
#include "securityutils.h"
#include "createpaths.h"
#include "setpermissions.h"
#include "genpassphrase.h"
namespace securitylib {
inline bool writeFingerprint(std::string& reply,
std::string const& ipAddress,
std::string const& port,
std::string const& fingerprint,
bool overwrite)
{
std::string fingerprintFileName(securitylib::getFingerprintDir());
fingerprintFileName += "/";
fingerprintFileName += ipAddress;
fingerprintFileName += "_";
fingerprintFileName += port;
fingerprintFileName += ".fingerprint";
if (!overwrite) {
securitylib::backup(fingerprintFileName);
}
CreatePaths::createPathsAsNeeded(fingerprintFileName);
std::ofstream outFile(fingerprintFileName.c_str());
if (!outFile.good()) {
reply += "error opening file ";
reply += fingerprintFileName;
reply += ": ";
reply += boost::lexical_cast<std::string>(errno);
return false;
}
outFile << fingerprint;
outFile.close();
// FIXME: enable once apache is figured out
//securitylib::setPermissions(fingerprintFileName, securitylib::SET_PERMISSION_BOTH);
std::string verifyFingerprint;
std::ifstream inFile(fingerprintFileName.c_str());
if (!inFile.good()) {
reply += "error opening file ";
reply += fingerprintFileName;
reply += " to verify fingerprint: ";
reply += boost::lexical_cast<std::string>(errno);
return false;
}
inFile >> verifyFingerprint;
if (verifyFingerprint == fingerprint) {
reply += "successfully wrote fingerprint for CS server @ ";
reply += ipAddress;
reply += ":";
reply += port;
reply += " to ";
reply += fingerprintFileName;
reply += "\n";
return true;
}
reply += "error writting fingerprint ";
reply += fingerprint;
reply += " (";
reply += verifyFingerprint;
reply += ") for CS server @ ";
reply += ipAddress;
reply += ':';
reply += port;
reply += " to ";
reply += fingerprintFileName;
reply += "\n";
return false;
}
inline bool writeCertificate(std::string& reply,
std::string const& ipAddress,
std::string const& port,
std::string const& certificate,
bool overwrite)
{
std::string certificateFileName(securitylib::getCertDir());
certificateFileName += "/";
certificateFileName += ipAddress;
certificateFileName += "_";
certificateFileName += port;
certificateFileName += ".crt";
if (!overwrite) {
securitylib::backup(certificateFileName);
}
CreatePaths::createPathsAsNeeded(certificateFileName);
std::ofstream outFile(certificateFileName.c_str());
if (!outFile.good()) {
reply += "error opening file ";
reply += certificateFileName;
reply += ": ";
reply += boost::lexical_cast<std::string>(errno);
return false;
}
outFile << certificate;
outFile.close();
// FIXME: enable once apache is figured out
//securitylib::setPermissions(certificateFileName, securitylib::SET_PERMISSION_BOTH);
std::ifstream inFile(certificateFileName.c_str());
if (!inFile.good()) {
reply += "error opening file ";
reply += certificateFileName;
reply += " to verify certificate: ";
reply += boost::lexical_cast<std::string>(errno);
return false;
}
inFile.seekg(0, inFile.end);
std::streampos length = inFile.tellg();
inFile.seekg(0, inFile.beg);
std::vector<char> verifyCertificate((size_t)length + 1);
inFile.read(&verifyCertificate[0], length);
verifyCertificate[length] = '\0';
if (certificate == &verifyCertificate[0]) {
reply += "successfully wrote certificate for CS server @ ";
reply += ipAddress;
reply += ":";
reply += port;
reply += " to ";
reply += certificateFileName;
return true;
}
reply += "error writting certificate for CS server @ ";
reply += ipAddress;
reply += ':';
reply += port;
reply += " to ";
reply += certificateFileName;
return false;
}
inline bool csGetIpAddress(std::string & csFQDN, std::string &ipAddress)
{
bool rv = false;
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(csFQDN, "");
for (boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query);
i != boost::asio::ip::tcp::resolver::iterator();
++i) {
boost::asio::ip::tcp::endpoint end = *i;
if (end.data()->sa_family == AF_INET) {
rv = true;
ipAddress = end.address().to_string();
}
}
return rv;
}
inline bool csGetFingerprint(std::string& reply,
std::string hostId,
std::string passphrase,
std::string csFQDN,
std::string port,
bool verifyPassphraeOnly,
bool useSsl,
bool overwrite,
std::string url = std::string("/ScoutAPI/CXAPI.php"))
{
if (!securitylib::isRootAdmin()) {
reply += "Must be ";
reply += securitylib::ROOT_ADMIN_NAME;
reply += " to run this program";
return false;
}
std::string ipAddress;
if (!csGetIpAddress(csFQDN, ipAddress))
{
reply += "Unable to resolve";
reply += csFQDN;
reply += "to ip address";
return false;
}
CsClient csClient(useSsl,
ipAddress,
port,
hostId,
passphrase,
std::string()); // empty cert as we are verifying cert not using it
CsError csError;
std::string fingerprint;
std::string certificate;
if (csClient.csGetFingerprint(url, csError, fingerprint, certificate)) {
if (verifyPassphraeOnly) {
reply += "passphrase is valid";
return true;
}
if (!fingerprint.empty()) {
bool ok = writeFingerprint(reply, csFQDN, port, fingerprint, overwrite);
ok &= writeCertificate(reply, csFQDN, port, certificate, overwrite);
return ok;
}
reply += "fingerprint is empty for CS server @ ";
reply += ipAddress;
reply += ":";
reply += port;
}
else {
if (verifyPassphraeOnly) {
reply += "passphrase failed validation";
}
else {
reply += "failed to get fingerprint for CS server @ ";
reply += ipAddress;
reply += ":";
reply += port;
}
reply += " -- reason: ";
reply += csError.reason;
reply += " -- ";
reply += "data: ";
reply += csError.data;
reply += " -- Verify the correct ip address, port and passphrase were entered";
}
return false;
}
bool inline csVerifyPassphrase(std::string& reply,
std::string hostId,
std::string passphrase,
std::string csFQDN,
std::string port,
bool useSsl,
std::string url = std::string("/ScoutAPI/CXAPI.php"))
{
if (!securitylib::isRootAdmin()) {
reply += "Must be ";
reply += securitylib::ROOT_ADMIN_NAME;
reply += " to run this program";
return false;
}
std::string ipAddress;
if (!csGetIpAddress(csFQDN, ipAddress))
{
reply += "Unable to resolve";
reply += csFQDN;
reply += "to ip address";
return false;
}
CsClient csClient(useSsl,
ipAddress,
port,
hostId,
passphrase,
std::string()); // empty cert as we are verifying it not using it
CsError csError;
std::string fingerprint;
std::string certificate;
if (csClient.csGetFingerprint(url, csError, fingerprint, certificate)) {
reply += "passphrase is valid";
return true;
}
reply += "passphrase failed validation.\n";
reply += "reason: ";
reply += csError.reason;
reply += " -- ";
reply += "data : ";
reply += csError.data;
reply += " -- Verify the correct ip address, port and passphrase were entered";
return false;
}
inline bool copyCsFingerprintForAzureComponents(std::string &reply,
const std::string& csIpAddress,
const std::string& csIpAddrForAzureComponents,
const std::string& csport)
{
std::string fingerprintFileName(securitylib::getFingerprintDir());
fingerprintFileName += "/";
fingerprintFileName += csIpAddress;
fingerprintFileName += "_";
fingerprintFileName += csport;
fingerprintFileName += ".fingerprint";
std::string fingerprint;
std::ifstream inFile(fingerprintFileName.c_str());
if (!inFile.good()) {
reply += "error opening file ";
reply += fingerprintFileName;
reply += " to copy fingerprint: ";
reply += boost::lexical_cast<std::string>(errno);
return false;
}
inFile >> fingerprint;
std::string newfingerprintFileName(securitylib::getFingerprintDir());
newfingerprintFileName += "/";
newfingerprintFileName += csIpAddrForAzureComponents;
newfingerprintFileName += "_";
newfingerprintFileName += csport;
newfingerprintFileName += ".fingerprint";
securitylib::backup(newfingerprintFileName);
CreatePaths::createPathsAsNeeded(newfingerprintFileName);
std::ofstream outFile(newfingerprintFileName.c_str());
if (!outFile.good()) {
reply += "error opening file ";
reply += newfingerprintFileName;
reply += ": ";
reply += boost::lexical_cast<std::string>(errno);
return false;
}
outFile << fingerprint;
outFile.close();
std::string verifyFingerprint;
std::ifstream vinFile(newfingerprintFileName.c_str());
if (!vinFile.good()) {
reply += "error opening file ";
reply += newfingerprintFileName;
reply += " to verify fingerprint: ";
reply += boost::lexical_cast<std::string>(errno);
return false;
}
vinFile >> verifyFingerprint;
if (verifyFingerprint == fingerprint) {
reply += "successfully wrote fingerprint for CS server @ ";
reply += csIpAddrForAzureComponents;
reply += ":";
reply += csport;
reply += " to ";
reply += newfingerprintFileName;
reply += "\n";
return true;
}
reply += "error copying fingerprint for CS server @";
reply += csIpAddrForAzureComponents;
reply += ':';
reply += csport;
reply += " from ";
reply += fingerprintFileName;
reply += "\n";
return false;
}
} // namespace securitylib {
#endif // CSGETFINGERPRINT_H