Sleds/cppcore/cppcoreobjects/cloudguardurn.cpp

339 lines
8.1 KiB
C++
Raw Normal View History

2025-03-13 21:28:38 +00:00
// Copyright (c) 2013, IOnU Security, Inc.
// Copyright (c) 2016, Sequence Logic, Inc. All rights reserved.
/**
* CloudGuardURN implementation.
*/
#include "cloudguardurn.h"
#include "../internal.h"
#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WINXP
#include <Rpc.h>
#else
#include <uuid/uuid.h>
#include <string.h>
#include <locale>
#endif
#include <vector>
#include <sstream>
#ifdef WIN32
#include <regex>
#endif
#include <algorithm>
#include <functional>
using namespace sequencelogic;
namespace
{
/**
* Validate URN parts...
*/
bool validateURNPart(const std::string &urnPart, int nLength);
/**
* Generate a UUID.
*/
std::string getUUID();
/**
* This is kind of a hack. This function needs to be linked into any code that directly links 'cppcoreobjects.lib'.
* However, it was meant to be internal to the DLL.
*/
int SplitString2(const std::string &strToSplit, const char ch, std::vector<std::string> &splitStrings)
{
int nRetVal = 0;
splitStrings.clear();
std::string::size_type nStart = 0;
while (strToSplit.find(ch, nStart) != std::string::npos)
{
splitStrings.push_back(strToSplit.substr(nStart, strToSplit.find(ch, nStart) - nStart));
++nRetVal;
nStart = strToSplit.find(ch, nStart)+1;
}
// Check for a last arg...
if (nStart <= strToSplit.length())
{
splitStrings.push_back(strToSplit.substr(nStart));
++nRetVal;
}
return nRetVal;
}
};
const char CloudGuardURN::NAMESPACE[] = "urn:sl:";
/**
* Exact length of NSS specific part of URN.
*/
const int CloudGuardURN::NSS_LENGTH = SL_URN_VAN_LEN + 1 + SL_URN_PMO_LEN + 1
+ SL_URN_DEV_LEN + 1 + SL_URN_DOC_LEN;
bool CloudGuardURN::isDoNotGenerateUUID(const char *pIdStr)
{
// There are certain reserved document ID values
bool bRetVal = false;
bRetVal = ( (pIdStr != NULL) && (pIdStr[0] != '\0') &&
((strcmp(pIdStr, PMO_ALL_ID) == 0) ||
(strcmp(pIdStr, TEST_VAN_ID) == 0) ||
(strcmp(pIdStr, BROWSER_DEVICE_ID) == 0) ||
(strcmp(pIdStr, HEADLESS_DEVICE_ID) == 0) ||
(strcmp(pIdStr, TEST_DEVICE_ID) == 0) ||
(strcmp(pIdStr, GROUP_DOC_DEVICE_ID) == 0) ||
(strncmp(pIdStr, "000000", 6) == 0)) );
return bRetVal;
}
CloudGuardURN& CloudGuardURN::operator=(const CloudGuardURN &rhs)
{
if (this != &rhs)
setUrn(rhs.getUrn());
return *this;
}
/**
* Get the NSS part of the URN string...
*/
std::string CloudGuardURN::toNSS() const
{
std::string retVal (_urn, ::strlen(NAMESPACE));
return retVal;
}
/**
* Set the URN strings.
*/
bool CloudGuardURN::setUrn(const std::string &urnStr)
{
bool bRetVal = true;
std::vector<std::string> urnParts;
int nNumParts = SplitString2(urnStr, ':', urnParts);
if ((nNumParts < 3) || (nNumParts > 6))
bRetVal = false;
else
{
// check parts
// 0 urn
// 1 sl
// 2 van
// 3 pmo
// 4 device
// 5 doc
if ((nNumParts > 5) && (urnParts[5] != ""))
{
if (validateURNPart(urnParts[2], SL_URN_VAN_LEN) &&
validateURNPart(urnParts[3], SL_URN_PMO_LEN) &&
validateURNPart(urnParts[4], SL_URN_DEV_LEN) &&
validateURNPart(urnParts[5], SL_URN_DOC_LEN))
{
_type = PMO_DEVICE_DOCUMENT;
_vanID = urnParts[2];
_pmoID = urnParts[3];
_deviceID = urnParts[4];
_docID = urnParts[5];
}
else
bRetVal = false;
}
else if ((nNumParts > 4) && (urnParts[4] != ""))
{
if (validateURNPart(urnParts[2], SL_URN_VAN_LEN) &&
validateURNPart(urnParts[3], SL_URN_PMO_LEN) &&
validateURNPart(urnParts[4], SL_URN_DEV_LEN) )
{
_type = PMO_DEVICE;
_vanID = urnParts[2];
_pmoID = urnParts[3];
_deviceID = urnParts[4];
_docID = "";
}
else
bRetVal = false;
}
else if ((nNumParts > 3) && (urnParts[3] != ""))
{
if (validateURNPart(urnParts[2], SL_URN_VAN_LEN) &&
validateURNPart(urnParts[3], SL_URN_PMO_LEN) )
{
_type = PMO;
_vanID = urnParts[2];
_pmoID = urnParts[3];
_deviceID = "";
_docID = "";
}
else
bRetVal = false;
}
else if ((nNumParts > 2) && (urnParts[2] != ""))
{
if (validateURNPart(urnParts[2], SL_URN_VAN_LEN) )
{
_type = VAN;
_vanID = urnParts[2];
_pmoID = "";
_deviceID = "";
_docID = "";
}
else
bRetVal = false;
}
if (bRetVal)
_urn = urnStr;
}
return bRetVal;
}
bool CloudGuardURN::setUrn(const std::string &van, const std::string &pmo, const std::string &dev/* = ""*/, const std::string &doc/* = ""*/)
{
std::stringstream urnStrStream;
urnStrStream << NAMESPACE << van << ":" << pmo << ":" << dev << ":" << doc;
return setUrn(urnStrStream.str());
}
/**
* Get an URN as type X.
*/
CloudGuardURN CloudGuardURN::as(URN_TYPE nType) const
{
CloudGuardURN retVal;
if (_type == nType)
retVal = *this;
else
{
switch (nType)
{
case VAN:
retVal.setUrn(getVANID(), "");
break;
case PMO:
retVal.setUrn(getVANID(), getPMOID());
break;
case PMO_DEVICE:
retVal.setUrn(getVANID(), getPMOID(), getDeviceID());
break;
case PMO_DEVICE_DOCUMENT:
retVal.setUrn(getVANID(), getPMOID(), getDeviceID(), getDocumentID());
break;
case INVALID:
default:
break;
}
}
return retVal;
}
/**
* Generate a unique (probabilistically anyway) UUID of length given.
* Does not generate reserved values.
* @param len
* @return
*/
std::string CloudGuardURN::generateUUID(int len)
{
std::string uuidStr = PMO_ALL_ID;
do
{
uuidStr = getUUID();
std::remove_if(uuidStr.begin(), uuidStr.end(), [] (std::string::value_type nChar) { return (nChar == '-'); });
if (static_cast<int>(uuidStr.length()) > len)
uuidStr = uuidStr.substr(0, len);
std::transform(uuidStr.begin(), uuidStr.end(), uuidStr.begin(),
std::bind2nd(std::ptr_fun(std::toupper<std::string::value_type>), std::locale()));
}
while (isDoNotGenerateUUID(uuidStr));
return uuidStr;
}
/**
* Reset an URN (clear it out).
*/
void CloudGuardURN::reset()
{
_urn = "";
_vanID = "";
_pmoID = "";
_deviceID = "";
_docID = "";
_type = INVALID;
}
namespace sequencelogic
{
std::ostream &operator<<(std::ostream &out, const CloudGuardURN *pUrn)
{
if (pUrn != NULL)
out << pUrn->getUrn();
return out;
}
}
namespace
{
/**
* Validate URN parts...
*/
bool validateURNPart(const std::string &urnPart, int nLength)
{
bool bRetVal = true;
if (urnPart.length() != static_cast<unsigned int>(nLength))
bRetVal = false;
else
{
const std::locale &loc = std::locale();
for (unsigned int i = 0; bRetVal && (i < urnPart.length()); ++i)
{
char tmpChar = urnPart[i];
bRetVal = (std::isdigit(tmpChar, loc) ||
(('a' <= tmpChar) && (tmpChar <= 'f')) ||
(('A' <= tmpChar) && (tmpChar <= 'F')));
}
}
return bRetVal;
}
/**
* Generate a UUID.
*/
std::string getUUID()
{
#ifdef WIN32
UUID uuid;
RPC_CSTR pTmpBuf;
::UuidCreate(&uuid);
::UuidToString(&uuid, &pTmpBuf);
std::string retVal = reinterpret_cast <const char *>(pTmpBuf);
::RpcStringFree(&pTmpBuf);
return retVal;
#else
uuid_t uuid;
uuid_generate_random (uuid);
char retVal[37];
uuid_unparse (uuid, retVal);
return retVal;
#endif
}
}