Skip to content

Commit

Permalink
WebAPI: Add digits only formatting for byte payload.
Browse files Browse the repository at this point in the history
Useful for vote websites that only allow userIds with all digits.
  • Loading branch information
dufernst committed Jan 23, 2023
1 parent 778fc28 commit abd170d
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 14 deletions.
33 changes: 19 additions & 14 deletions src/tools/web_api/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ struct StateAccountReference
};

template <typename T>
std::string StateToHexBytesString(const T& data, const unsigned char* k)
std::string StateToHexBytesString(const T& data, const unsigned char* k, const bool onlyDigits = false)
{
unsigned char nonce[crypto_secretbox_NONCEBYTES];
randombytes(nonce, crypto_secretbox_NONCEBYTES);
Expand All @@ -323,29 +323,31 @@ std::string StateToHexBytesString(const T& data, const unsigned char* k)
for (int i = 0; i < crypto_secretbox_NONCEBYTES; i++)
encryptedV[i] = nonce[i];

char buffer[3];
char buffer[onlyDigits ? 4 : 3];
std::string result;
for (const unsigned char byte : encryptedV)
if (snprintf(buffer, 3, "%.2X", byte) == 2)
if (snprintf(buffer, onlyDigits ? 4 : 3, onlyDigits ? "%.3u" : "%.2X", byte) == onlyDigits ? 3 : 2)
result += std::string(buffer);

return result;
}

template <typename T>
bool HexBytesStringToState(T& data, const unsigned char* k, const std::string& bytesAsHexString)
bool HexBytesStringToState(T& data, const unsigned char* k, const std::string& bytesAsHexString, const bool onlyDigits = false)
{
if (bytesAsHexString.length() % 2 || bytesAsHexString.length() <= crypto_secretbox_NONCEBYTES * 2)
uint64_t charsPerByte = onlyDigits ? 3 : 2;
if (bytesAsHexString.length() % charsPerByte || bytesAsHexString.length() <= crypto_secretbox_NONCEBYTES * charsPerByte)
return false;

unsigned char nonce[crypto_secretbox_NONCEBYTES];
for (int i = 0; i < crypto_secretbox_NONCEBYTES * 2; i += 2)
sscanf(bytesAsHexString.c_str() + i, "%2hhx", &nonce[i / 2]);
for (int i = 0; i < crypto_secretbox_NONCEBYTES * charsPerByte; i += charsPerByte)
sscanf(bytesAsHexString.c_str() + i, onlyDigits ? "%3hhu" : "%2hhx", &nonce[i / charsPerByte]);


std::vector<unsigned char> encryptedV(crypto_secretbox_BOXZEROBYTES + (bytesAsHexString.length() / 2) - crypto_secretbox_NONCEBYTES, '\0');
for (int i = crypto_secretbox_NONCEBYTES * 2; i < bytesAsHexString.length(); i += 2)
sscanf(bytesAsHexString.c_str() + i, "%2hhx", &encryptedV[crypto_secretbox_BOXZEROBYTES + (i - crypto_secretbox_NONCEBYTES * 2) / 2]);
std::vector<unsigned char> encryptedV(crypto_secretbox_BOXZEROBYTES + (bytesAsHexString.length() / charsPerByte) - crypto_secretbox_NONCEBYTES, '\0');
for (int i = crypto_secretbox_NONCEBYTES * charsPerByte; i < bytesAsHexString.length(); i += charsPerByte)
sscanf(bytesAsHexString.c_str() + i, onlyDigits ? "%3hhu" : "%2hhx",
&encryptedV[crypto_secretbox_BOXZEROBYTES + (i - crypto_secretbox_NONCEBYTES * charsPerByte) / charsPerByte]);

std::vector<unsigned char> m(encryptedV.size(), '\0');
if (crypto_secretbox_open(m.data(), encryptedV.data(), encryptedV.size(), nonce, k))
Expand Down Expand Up @@ -421,6 +423,7 @@ struct VoteWebsiteData
std::string callbackHostname;
std::vector<std::string> callbackIps;
std::string callbackUrl;
bool callbackIdOnlyDigits;
std::string voteUrl;
std::string checkKeyName;
std::string checkKeyValue;
Expand Down Expand Up @@ -604,15 +607,17 @@ std::vector<VoteWebsiteData> loadVoteWebsites()
}

voteWebsites[i - 1].callbackUrl = sConfigMgr->GetStringDefault(std::string("CallbackUrl") + std::to_string(i), "");
voteWebsites[i - 1].callbackIdOnlyDigits = sConfigMgr->GetBoolDefault(std::string("CallbackIdOnlyDigits") + std::to_string(i), false);
voteWebsites[i - 1].voteUrl = sConfigMgr->GetStringDefault(std::string("VoteUrl") + std::to_string(i), "");
voteWebsites[i - 1].checkKeyName = sConfigMgr->GetStringDefault(std::string("CheckKeyName") + std::to_string(i), "");
voteWebsites[i - 1].checkKeyValue = sConfigMgr->GetStringDefault(std::string("CheckKeyValue") + std::to_string(i), "");
voteWebsites[i - 1].voteTokenType = sConfigMgr->GetIntDefault(std::string("VoteToken") + std::to_string(i), 0);
voteWebsites[i - 1].voteTokensGiven = sConfigMgr->GetIntDefault(std::string("VoteTokensGiven") + std::to_string(i), 0);

printf("Loaded vote site: %s, with CallbackKeyName: %s, CallbackHostname: %s, CallbackUrl: %s, VoteUrl: %s, CheckKeyName: %s, CheckKeyValue: %s, VoteToken: %d, VoteTokensGiven: %d\n",
printf("Loaded vote site: %s, with CallbackKeyName: %s, CallbackHostname: %s, CallbackUrl: %s, CallbackIdOnlyDigits: %u, VoteUrl: %s, CheckKeyName: %s, CheckKeyValue: %s, VoteToken: %d, VoteTokensGiven: %d\n",
voteWebsites[i - 1].name.c_str(), voteWebsites[i - 1].callbackKeyName.c_str(), voteWebsites[i - 1].callbackHostname.c_str(),
voteWebsites[i - 1].callbackUrl.c_str(), voteWebsites[i - 1].voteUrl.c_str(), voteWebsites[i - 1].checkKeyName.c_str(), voteWebsites[i - 1].checkKeyValue.c_str(),
voteWebsites[i - 1].callbackUrl.c_str(), voteWebsites[i - 1].callbackIdOnlyDigits,
voteWebsites[i - 1].voteUrl.c_str(), voteWebsites[i - 1].checkKeyName.c_str(), voteWebsites[i - 1].checkKeyValue.c_str(),
voteWebsites[i - 1].voteTokenType, voteWebsites[i - 1].voteTokensGiven);
for (auto& ip : voteWebsites[i - 1].callbackIps)
printf("Added callbackIp: %s\n", ip.c_str());
Expand Down Expand Up @@ -688,7 +693,7 @@ void handleVoteCallback(const VoteWebsiteData& voteWebsite, const std::string& i
req.get_param_value(voteWebsite.callbackKeyName) : req.get_header_value(voteWebsite.callbackKeyName);

StateAccountReference sar;
if (!HexBytesStringToState(sar, k, userRef))
if (!HexBytesStringToState(sar, k, userRef, voteWebsite.callbackIdOnlyDigits))
{
printf("Unable to parse StateAccountReference from provided userRef.\n");
printReqData(req);
Expand Down Expand Up @@ -2015,7 +2020,7 @@ int main(int argc, char* argv[])

StateAccountReference sar;
sar.aId = sli.accountId;
std::string redirectUrl = voteWebsite.voteUrl + StateToHexBytesString(sar, k);
std::string redirectUrl = voteWebsite.voteUrl + StateToHexBytesString(sar, k, voteWebsite.callbackIdOnlyDigits);
res.set_redirect(redirectUrl);
});
}
Expand Down
1 change: 1 addition & 0 deletions src/tools/web_api/webapi.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ WebisteName4 = GamingTop100
CallbackKeyName4 = userid
CallbackHostname4 = gamingtop100.net
CallbackUrl4 = /callback/gamingtop100-vote/api
CallbackIdOnlyDigits4 = 1
VoteUrl4 = http://gamingtop100.net/in-SITEID-
VoteToken4 = 1
VoteTokensGiven4 = 1

0 comments on commit abd170d

Please sign in to comment.