339 lines
8.1 KiB
C++
339 lines
8.1 KiB
C++
|
|
// 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
|
||
|
|
}
|
||
|
|
}
|