Merge #957: Refactor CKeePassIntegrator
d4f5d7c Refactor CKeePassIntegrator
This commit is contained in:
parent
a1d2c938de
commit
83f4e57087
229
src/keepass.cpp
229
src/keepass.cpp
@ -30,11 +30,12 @@
|
||||
#include <openssl/buffer.h>
|
||||
#include "support/cleanse.h" // for OPENSSL_cleanse()
|
||||
|
||||
const char* CKeePassIntegrator::KEEPASS_HTTP_HOST = "localhost";
|
||||
|
||||
CKeePassIntegrator keePassInt;
|
||||
|
||||
// Base64 decoding with secure memory allocation
|
||||
SecureString DecodeBase64Secure(const SecureString& input)
|
||||
SecureString DecodeBase64Secure(const SecureString& sInput)
|
||||
{
|
||||
SecureString output;
|
||||
|
||||
@ -42,19 +43,19 @@ SecureString DecodeBase64Secure(const SecureString& input)
|
||||
BIO *b64, *mem;
|
||||
b64 = BIO_new(BIO_f_base64());
|
||||
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
|
||||
mem = BIO_new_mem_buf((void *) &input[0], input.size());
|
||||
mem = BIO_new_mem_buf((void *) &sInput[0], sInput.size());
|
||||
BIO_push(b64, mem);
|
||||
|
||||
// Prepare buffer to receive decoded data
|
||||
if(input.size() % 4 != 0) {
|
||||
if(sInput.size() % 4 != 0) {
|
||||
throw std::runtime_error("Input length should be a multiple of 4");
|
||||
}
|
||||
size_t nMaxLen = input.size() / 4 * 3; // upper bound, guaranteed divisible by 4
|
||||
size_t nMaxLen = sInput.size() / 4 * 3; // upper bound, guaranteed divisible by 4
|
||||
output.resize(nMaxLen);
|
||||
|
||||
// Decode the string
|
||||
size_t nLen;
|
||||
nLen = BIO_read(b64, (void *) &output[0], input.size());
|
||||
nLen = BIO_read(b64, (void *) &output[0], sInput.size());
|
||||
output.resize(nLen);
|
||||
|
||||
// Free memory
|
||||
@ -63,7 +64,7 @@ SecureString DecodeBase64Secure(const SecureString& input)
|
||||
}
|
||||
|
||||
// Base64 encoding with secure memory allocation
|
||||
SecureString EncodeBase64Secure(const SecureString& input)
|
||||
SecureString EncodeBase64Secure(const SecureString& sInput)
|
||||
{
|
||||
// Init openssl BIO with base64 filter and memory output
|
||||
BIO *b64, *mem;
|
||||
@ -73,7 +74,7 @@ SecureString EncodeBase64Secure(const SecureString& input)
|
||||
BIO_push(b64, mem);
|
||||
|
||||
// Decode the string
|
||||
BIO_write(b64, &input[0], input.size());
|
||||
BIO_write(b64, &sInput[0], sInput.size());
|
||||
(void) BIO_flush(b64);
|
||||
|
||||
// Create output variable from buffer mem ptr
|
||||
@ -105,39 +106,39 @@ void CKeePassIntegrator::init()
|
||||
bIsActive = GetBoolArg("-keepass", false);
|
||||
nPort = GetArg("-keepassport", DEFAULT_KEEPASS_HTTP_PORT);
|
||||
sKeyBase64 = SecureString(GetArg("-keepasskey", "").c_str());
|
||||
sKeePassId = GetArg("-keepassid", "");
|
||||
sKeePassEntryName = GetArg("-keepassname", "");
|
||||
strKeePassId = GetArg("-keepassid", "");
|
||||
strKeePassEntryName = GetArg("-keepassname", "");
|
||||
// Convert key if available
|
||||
if(sKeyBase64.size() > 0)
|
||||
{
|
||||
sKey = DecodeBase64Secure(sKeyBase64);
|
||||
}
|
||||
// Construct url if available
|
||||
if(sKeePassEntryName.size() > 0)
|
||||
if(strKeePassEntryName.size() > 0)
|
||||
{
|
||||
sUrl = SecureString("http://");
|
||||
sUrl += SecureString(sKeePassEntryName.c_str());
|
||||
sUrl += SecureString(strKeePassEntryName.c_str());
|
||||
sUrl += SecureString("/");
|
||||
//sSubmitUrl = "http://";
|
||||
//sSubmitUrl += SecureString(sKeePassEntryName.c_str());
|
||||
//sSubmitUrl += SecureString(strKeePassEntryName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::CKeePassRequest::addStrParameter(std::string sName, std::string sValue)
|
||||
void CKeePassIntegrator::CKeePassRequest::addStrParameter(std::string strName, std::string strValue)
|
||||
{
|
||||
requestObj.push_back(Pair(sName, sValue));
|
||||
requestObj.push_back(Pair(strName, strValue));
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::CKeePassRequest::addStrParameter(std::string sName, SecureString sValue)
|
||||
void CKeePassIntegrator::CKeePassRequest::addStrParameter(std::string strName, SecureString sValue)
|
||||
{
|
||||
std::string sCipherValue;
|
||||
|
||||
if(!EncryptAES256(sKey, sValue, sIV, sCipherValue))
|
||||
if(!EncryptAES256(sKey, sValue, strIV, sCipherValue))
|
||||
{
|
||||
throw std::runtime_error("Unable to encrypt Verifier");
|
||||
}
|
||||
|
||||
addStrParameter(sName, EncodeBase64(sCipherValue));
|
||||
addStrParameter(strName, EncodeBase64(sCipherValue));
|
||||
}
|
||||
|
||||
std::string CKeePassIntegrator::CKeePassRequest::getJson()
|
||||
@ -148,18 +149,18 @@ std::string CKeePassIntegrator::CKeePassRequest::getJson()
|
||||
void CKeePassIntegrator::CKeePassRequest::init()
|
||||
{
|
||||
SecureString sIVSecure = generateRandomKey(KEEPASS_CRYPTO_BLOCK_SIZE);
|
||||
sIV = std::string(&sIVSecure[0], sIVSecure.size());
|
||||
strIV = std::string(&sIVSecure[0], sIVSecure.size());
|
||||
// Generate Nonce, Verifier and RequestType
|
||||
SecureString sNonceBase64Secure = EncodeBase64Secure(sIVSecure);
|
||||
addStrParameter("Nonce", std::string(&sNonceBase64Secure[0], sNonceBase64Secure.size())); // Plain
|
||||
addStrParameter("Verifier", sNonceBase64Secure); // Encoded
|
||||
addStrParameter("RequestType", sType);
|
||||
addStrParameter("RequestType", strType);
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::CKeePassResponse::parseResponse(std::string sResponse)
|
||||
void CKeePassIntegrator::CKeePassResponse::parseResponse(std::string strResponse)
|
||||
{
|
||||
UniValue responseValue;
|
||||
if(!responseValue.read(sResponse))
|
||||
if(!responseValue.read(strResponse))
|
||||
{
|
||||
throw std::runtime_error("Unable to parse KeePassHttp response");
|
||||
}
|
||||
@ -168,37 +169,37 @@ void CKeePassIntegrator::CKeePassResponse::parseResponse(std::string sResponse)
|
||||
|
||||
// retrieve main values
|
||||
bSuccess = responseObj["Success"].get_bool();
|
||||
sType = getStr("RequestType");
|
||||
sIV = DecodeBase64(getStr("Nonce"));
|
||||
strType = getStr("RequestType");
|
||||
strIV = DecodeBase64(getStr("Nonce"));
|
||||
}
|
||||
|
||||
std::string CKeePassIntegrator::CKeePassResponse::getStr(std::string sName)
|
||||
std::string CKeePassIntegrator::CKeePassResponse::getStr(std::string strName)
|
||||
{
|
||||
return responseObj[sName].get_str();
|
||||
return responseObj[strName].get_str();
|
||||
}
|
||||
|
||||
SecureString CKeePassIntegrator::CKeePassResponse::getSecureStr(std::string sName)
|
||||
SecureString CKeePassIntegrator::CKeePassResponse::getSecureStr(std::string strName)
|
||||
{
|
||||
std::string sValueBase64Encrypted(responseObj[sName].get_str());
|
||||
std::string strValueBase64Encrypted(responseObj[strName].get_str());
|
||||
SecureString sValue;
|
||||
try
|
||||
{
|
||||
sValue = decrypt(sValueBase64Encrypted);
|
||||
sValue = decrypt(strValueBase64Encrypted);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::string sErrorMessage = "Exception occured while decrypting ";
|
||||
sErrorMessage += sName + ": " + e.what();
|
||||
throw std::runtime_error(sErrorMessage);
|
||||
std::string strError = "Exception occured while decrypting ";
|
||||
strError += strName + ": " + e.what();
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
return sValue;
|
||||
}
|
||||
|
||||
SecureString CKeePassIntegrator::CKeePassResponse::decrypt(std::string sValueBase64Encrypted)
|
||||
SecureString CKeePassIntegrator::CKeePassResponse::decrypt(std::string strValueBase64Encrypted)
|
||||
{
|
||||
std::string sValueEncrypted = DecodeBase64(sValueBase64Encrypted);
|
||||
std::string strValueEncrypted = DecodeBase64(strValueBase64Encrypted);
|
||||
SecureString sValue;
|
||||
if(!DecryptAES256(sKey, sValueEncrypted, sIV, sValue))
|
||||
if(!DecryptAES256(sKey, strValueEncrypted, strIV, sValue))
|
||||
{
|
||||
throw std::runtime_error("Unable to decrypt value.");
|
||||
}
|
||||
@ -228,20 +229,20 @@ std::vector<CKeePassIntegrator::CKeePassEntry> CKeePassIntegrator::CKeePassRespo
|
||||
SecureString CKeePassIntegrator::generateRandomKey(size_t nSize)
|
||||
{
|
||||
// Generates random key
|
||||
SecureString key;
|
||||
key.resize(nSize);
|
||||
SecureString sKey;
|
||||
sKey.resize(nSize);
|
||||
|
||||
RandAddSeedPerfmon();
|
||||
GetRandBytes((unsigned char *) &key[0], nSize);
|
||||
GetRandBytes((unsigned char *) &sKey[0], nSize);
|
||||
|
||||
return key;
|
||||
return sKey;
|
||||
}
|
||||
|
||||
// Construct POST body for RPC JSON call
|
||||
std::string CKeePassIntegrator::constructHTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "POST / HTTP/1.1\r\n"
|
||||
std::ostringstream streamOut;
|
||||
streamOut << "POST / HTTP/1.1\r\n"
|
||||
<< "User-Agent: dash-json-rpc/" << FormatFullVersion() << "\r\n"
|
||||
<< "Host: localhost\r\n"
|
||||
<< "Content-Type: application/json\r\n"
|
||||
@ -249,17 +250,17 @@ std::string CKeePassIntegrator::constructHTTPPost(const std::string& strMsg, con
|
||||
<< "Connection: close\r\n"
|
||||
<< "Accept: application/json\r\n";
|
||||
BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, mapRequestHeaders)
|
||||
s << item.first << ": " << item.second << "\r\n";
|
||||
s << "\r\n" << strMsg;
|
||||
streamOut << item.first << ": " << item.second << "\r\n";
|
||||
streamOut << "\r\n" << strMsg;
|
||||
|
||||
return s.str();
|
||||
return streamOut.str();
|
||||
}
|
||||
|
||||
/** Reply structure for request_done to fill in */
|
||||
struct HTTPReply
|
||||
{
|
||||
int status;
|
||||
std::string body;
|
||||
int nStatus;
|
||||
std::string strBody;
|
||||
};
|
||||
|
||||
static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
@ -270,11 +271,11 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
/* If req is NULL, it means an error occurred while connecting, but
|
||||
* I'm not sure how to find out which one. We also don't really care.
|
||||
*/
|
||||
reply->status = 0;
|
||||
reply->nStatus = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
reply->status = evhttp_request_get_response_code(req);
|
||||
reply->nStatus = evhttp_request_get_response_code(req);
|
||||
|
||||
struct evbuffer *buf = evhttp_request_get_input_buffer(req);
|
||||
if (buf)
|
||||
@ -282,13 +283,13 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
size_t size = evbuffer_get_length(buf);
|
||||
const char *data = (const char*)evbuffer_pullup(buf, size);
|
||||
if (data)
|
||||
reply->body = std::string(data, size);
|
||||
reply->strBody = std::string(data, size);
|
||||
evbuffer_drain(buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Send RPC message to KeePassHttp
|
||||
void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatus, std::string& sResponse)
|
||||
void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatus, std::string& strResponse)
|
||||
{
|
||||
// // Prepare communication
|
||||
// boost::asio::io_service io_service;
|
||||
@ -401,26 +402,26 @@ void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatus, s
|
||||
//
|
||||
// // Receive HTTP reply message headers and body
|
||||
// std::map<std::string, std::string> mapHeaders;
|
||||
// ReadHTTPMessage(response_stream, mapHeaders, sResponse, nProto, std::numeric_limits<size_t>::max());
|
||||
// ReadHTTPMessage(response_stream, mapHeaders, strResponse, nProto, std::numeric_limits<size_t>::max());
|
||||
// LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- Processed body\n");
|
||||
|
||||
nStatus = response.status;
|
||||
if (response.status == 0)
|
||||
nStatus = response.nStatus;
|
||||
if (response.nStatus == 0)
|
||||
throw std::runtime_error("couldn't connect to server");
|
||||
else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
|
||||
throw std::runtime_error(strprintf("server returned HTTP error %d", response.status));
|
||||
else if (response.body.empty())
|
||||
else if (response.nStatus >= 400 && response.nStatus != HTTP_BAD_REQUEST && response.nStatus != HTTP_NOT_FOUND && response.nStatus != HTTP_INTERNAL_SERVER_ERROR)
|
||||
throw std::runtime_error(strprintf("server returned HTTP error %d", response.nStatus));
|
||||
else if (response.strBody.empty())
|
||||
throw std::runtime_error("no response from server");
|
||||
|
||||
// Parse reply
|
||||
UniValue valReply(UniValue::VSTR);
|
||||
if (!valReply.read(response.body))
|
||||
if (!valReply.read(response.strBody))
|
||||
throw std::runtime_error("couldn't parse reply from server");
|
||||
const UniValue& reply = valReply.get_obj();
|
||||
if (reply.empty())
|
||||
throw std::runtime_error("expected reply to have result, error and id properties");
|
||||
|
||||
sResponse = valReply.get_str();
|
||||
strResponse = valReply.get_str();
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::rpcTestAssociation(bool bTriggerUnlock)
|
||||
@ -429,11 +430,11 @@ void CKeePassIntegrator::rpcTestAssociation(bool bTriggerUnlock)
|
||||
request.addStrParameter("TriggerUnlock", std::string(bTriggerUnlock ? "true" : "false"));
|
||||
|
||||
int nStatus;
|
||||
std::string sResponse;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, sResponse);
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcTestAssociation -- send result: status: %d response: %s\n", nStatus, sResponse);
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcTestAssociation -- send result: status: %d response: %s\n", nStatus, strResponse);
|
||||
}
|
||||
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> CKeePassIntegrator::rpcGetLogins()
|
||||
@ -445,82 +446,82 @@ std::vector<CKeePassIntegrator::CKeePassEntry> CKeePassIntegrator::rpcGetLogins(
|
||||
CKeePassRequest request(sKey, "get-logins");
|
||||
request.addStrParameter("addStrParameter", std::string("true"));
|
||||
request.addStrParameter("TriggerUnlock", std::string("true"));
|
||||
request.addStrParameter("Id", sKeePassId);
|
||||
request.addStrParameter("Id", strKeePassId);
|
||||
request.addStrParameter("Url", sUrl);
|
||||
|
||||
int nStatus;
|
||||
std::string sResponse;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, sResponse);
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
// Logging of actual response data disabled as to not write passphrase in debug.log. Only enable temporarily when needed
|
||||
//LogPrint("keepass", "CKeePassIntegrator::rpcGetLogins -- send result: status: %d response: %s\n", nStatus, sResponse);
|
||||
//LogPrint("keepass", "CKeePassIntegrator::rpcGetLogins -- send result: status: %d response: %s\n", nStatus, strResponse);
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcGetLogins -- send result: status: %d\n", nStatus);
|
||||
|
||||
if(nStatus != 200)
|
||||
{
|
||||
std::string sErrorMessage = "Error returned by KeePassHttp: HTTP code ";
|
||||
sErrorMessage += itostr(nStatus);
|
||||
sErrorMessage += " - Response: ";
|
||||
sErrorMessage += " response: [";
|
||||
sErrorMessage += sResponse;
|
||||
sErrorMessage += "]";
|
||||
throw std::runtime_error(sErrorMessage);
|
||||
std::string strError = "Error returned by KeePassHttp: HTTP code ";
|
||||
strError += itostr(nStatus);
|
||||
strError += " - Response: ";
|
||||
strError += " response: [";
|
||||
strError += strResponse;
|
||||
strError += "]";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
CKeePassResponse response(sKey, sResponse);
|
||||
CKeePassResponse response(sKey, strResponse);
|
||||
|
||||
if(!response.getSuccess())
|
||||
{
|
||||
std::string sErrorMessage = "KeePassHttp returned failure status";
|
||||
throw std::runtime_error(sErrorMessage);
|
||||
std::string strError = "KeePassHttp returned failure status";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
return response.getEntries();
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::rpcSetLogin(const SecureString& strWalletPass, const SecureString& sEntryId)
|
||||
void CKeePassIntegrator::rpcSetLogin(const SecureString& sWalletPass, const SecureString& sEntryId)
|
||||
{
|
||||
|
||||
// Convert key format
|
||||
SecureString sKey = DecodeBase64Secure(sKeyBase64);
|
||||
|
||||
CKeePassRequest request(sKey, "set-login");
|
||||
request.addStrParameter("Id", sKeePassId);
|
||||
request.addStrParameter("Id", strKeePassId);
|
||||
request.addStrParameter("Url", sUrl);
|
||||
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcSetLogin -- send Url: %s\n", sUrl);
|
||||
|
||||
//request.addStrParameter("SubmitUrl", sSubmitUrl); // Is used to construct the entry title
|
||||
request.addStrParameter("Login", SecureString("dash"));
|
||||
request.addStrParameter("Password", strWalletPass);
|
||||
request.addStrParameter("Password", sWalletPass);
|
||||
if(sEntryId.size() != 0)
|
||||
{
|
||||
request.addStrParameter("Uuid", sEntryId); // Update existing
|
||||
}
|
||||
|
||||
int nStatus;
|
||||
std::string sResponse;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, sResponse);
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcSetLogin -- send result: status: %d response: %s\n", nStatus, sResponse);
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcSetLogin -- send result: status: %d response: %s\n", nStatus, strResponse);
|
||||
|
||||
if(nStatus != 200)
|
||||
{
|
||||
std::string sErrorMessage = "Error returned: HTTP code ";
|
||||
sErrorMessage += itostr(nStatus);
|
||||
sErrorMessage += " - Response: ";
|
||||
sErrorMessage += " response: [";
|
||||
sErrorMessage += sResponse;
|
||||
sErrorMessage += "]";
|
||||
throw std::runtime_error(sErrorMessage);
|
||||
std::string strError = "Error returned: HTTP code ";
|
||||
strError += itostr(nStatus);
|
||||
strError += " - Response: ";
|
||||
strError += " response: [";
|
||||
strError += strResponse;
|
||||
strError += "]";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
CKeePassResponse response(sKey, sResponse);
|
||||
CKeePassResponse response(sKey, strResponse);
|
||||
|
||||
if(!response.getSuccess())
|
||||
{
|
||||
@ -536,7 +537,7 @@ SecureString CKeePassIntegrator::generateKeePassKey()
|
||||
return sKeyBase64;
|
||||
}
|
||||
|
||||
void CKeePassIntegrator::rpcAssociate(std::string& sId, SecureString& sKeyBase64)
|
||||
void CKeePassIntegrator::rpcAssociate(std::string& strId, SecureString& sKeyBase64)
|
||||
{
|
||||
sKey = generateRandomKey(KEEPASS_CRYPTO_KEY_SIZE);
|
||||
CKeePassRequest request(sKey, "associate");
|
||||
@ -545,25 +546,25 @@ void CKeePassIntegrator::rpcAssociate(std::string& sId, SecureString& sKeyBase64
|
||||
request.addStrParameter("Key", std::string(&sKeyBase64[0], sKeyBase64.size()));
|
||||
|
||||
int nStatus;
|
||||
std::string sResponse;
|
||||
std::string strResponse;
|
||||
|
||||
doHTTPPost(request.getJson(), nStatus, sResponse);
|
||||
doHTTPPost(request.getJson(), nStatus, strResponse);
|
||||
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcAssociate -- send result: status: %d response: %s\n", nStatus, sResponse);
|
||||
LogPrint("keepass", "CKeePassIntegrator::rpcAssociate -- send result: status: %d response: %s\n", nStatus, strResponse);
|
||||
|
||||
if(nStatus != 200)
|
||||
{
|
||||
std::string sErrorMessage = "Error returned: HTTP code ";
|
||||
sErrorMessage += itostr(nStatus);
|
||||
sErrorMessage += " - Response: ";
|
||||
sErrorMessage += " response: [";
|
||||
sErrorMessage += sResponse;
|
||||
sErrorMessage += "]";
|
||||
throw std::runtime_error(sErrorMessage);
|
||||
std::string strError = "Error returned: HTTP code ";
|
||||
strError += itostr(nStatus);
|
||||
strError += " - Response: ";
|
||||
strError += " response: [";
|
||||
strError += strResponse;
|
||||
strError += "]";
|
||||
throw std::runtime_error(strError);
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
CKeePassResponse response(sKey, sResponse);
|
||||
CKeePassResponse response(sKey, strResponse);
|
||||
|
||||
if(!response.getSuccess())
|
||||
{
|
||||
@ -571,7 +572,7 @@ void CKeePassIntegrator::rpcAssociate(std::string& sId, SecureString& sKeyBase64
|
||||
}
|
||||
|
||||
// If we got here, we were successful. Return the information
|
||||
sId = response.getStr("Id");
|
||||
strId = response.getStr("Id");
|
||||
}
|
||||
|
||||
// Retrieve wallet passphrase from KeePass
|
||||
@ -583,29 +584,29 @@ SecureString CKeePassIntegrator::retrievePassphrase()
|
||||
{
|
||||
throw std::runtime_error("keepasskey parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(sKeePassId.size() == 0)
|
||||
if(strKeePassId.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("keepassid parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(sKeePassEntryName == "")
|
||||
if(strKeePassEntryName == "")
|
||||
{
|
||||
throw std::runtime_error("keepassname parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
|
||||
// Retrieve matching logins from KeePass
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> entries = rpcGetLogins();
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries = rpcGetLogins();
|
||||
|
||||
// Only accept one unique match
|
||||
if(entries.size() == 0)
|
||||
if(vecEntries.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned 0 matches, please verify the keepassurl setting.");
|
||||
}
|
||||
if(entries.size() > 1)
|
||||
if(vecEntries.size() > 1)
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned multiple matches, bailing out.");
|
||||
}
|
||||
|
||||
return entries[0].getPassword();
|
||||
return vecEntries[0].getPassword();
|
||||
}
|
||||
|
||||
// Update wallet passphrase in keepass
|
||||
@ -616,30 +617,30 @@ void CKeePassIntegrator::updatePassphrase(const SecureString& sWalletPassphrase)
|
||||
{
|
||||
throw std::runtime_error("keepasskey parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(sKeePassId.size() == 0)
|
||||
if(strKeePassId.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("keepassid parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
if(sKeePassEntryName == "")
|
||||
if(strKeePassEntryName == "")
|
||||
{
|
||||
throw std::runtime_error("keepassname parameter is not defined. Please specify the configuration parameter.");
|
||||
}
|
||||
|
||||
SecureString sEntryId("");
|
||||
|
||||
std::string sErrorMessage;
|
||||
std::string strError;
|
||||
|
||||
// Lookup existing entry
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> vEntries = rpcGetLogins();
|
||||
std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries = rpcGetLogins();
|
||||
|
||||
if(vEntries.size() > 1)
|
||||
if(vecEntries.size() > 1)
|
||||
{
|
||||
throw std::runtime_error("KeePassHttp returned multiple matches, bailing out.");
|
||||
}
|
||||
|
||||
if(vEntries.size() == 1)
|
||||
if(vecEntries.size() == 1)
|
||||
{
|
||||
sEntryId = vEntries[0].getUuid();
|
||||
sEntryId = vecEntries[0].getUuid();
|
||||
}
|
||||
|
||||
// Update wallet passphrase in KeePass
|
||||
|
@ -9,13 +9,18 @@
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
static const int KEEPASS_CRYPTO_KEY_SIZE = 32;
|
||||
static const int KEEPASS_CRYPTO_BLOCK_SIZE = 16;
|
||||
static const int KEEPASS_HTTP_CONNECT_TIMEOUT = 30;
|
||||
class CKeePassIntegrator;
|
||||
|
||||
static const unsigned int DEFAULT_KEEPASS_HTTP_PORT = 19455;
|
||||
static const char* KEEPASS_HTTP_HOST = "localhost";
|
||||
|
||||
extern CKeePassIntegrator keePassInt;
|
||||
|
||||
class CKeePassIntegrator {
|
||||
private:
|
||||
static const int KEEPASS_CRYPTO_KEY_SIZE = 32;
|
||||
static const int KEEPASS_CRYPTO_BLOCK_SIZE = 16;
|
||||
static const int KEEPASS_HTTP_CONNECT_TIMEOUT = 30;
|
||||
static const char* KEEPASS_HTTP_HOST;
|
||||
|
||||
bool bIsActive;
|
||||
unsigned int nPort;
|
||||
@ -23,27 +28,27 @@ class CKeePassIntegrator {
|
||||
SecureString sKey;
|
||||
SecureString sUrl;
|
||||
//SecureString sSubmitUrl;
|
||||
std::string sKeePassId;
|
||||
std::string sKeePassEntryName;
|
||||
std::string strKeePassId;
|
||||
std::string strKeePassEntryName;
|
||||
|
||||
class CKeePassRequest {
|
||||
|
||||
UniValue requestObj;
|
||||
std::string sType;
|
||||
std::string sIV;
|
||||
std::string strType;
|
||||
std::string strIV;
|
||||
SecureString sKey;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
void addStrParameter(std::string sName, std::string sValue); // Regular
|
||||
void addStrParameter(std::string sName, SecureString sValue); // Encrypt
|
||||
void addStrParameter(std::string strName, std::string strValue); // Regular
|
||||
void addStrParameter(std::string strName, SecureString sValue); // Encrypt
|
||||
std::string getJson();
|
||||
|
||||
CKeePassRequest(SecureString sKey, std::string sType)
|
||||
CKeePassRequest(SecureString sKey, std::string strType)
|
||||
{
|
||||
this->sKey = sKey;
|
||||
this->sType = sType;
|
||||
this->strType = strType;
|
||||
init();
|
||||
};
|
||||
};
|
||||
@ -51,30 +56,30 @@ class CKeePassIntegrator {
|
||||
|
||||
class CKeePassEntry {
|
||||
|
||||
SecureString uuid;
|
||||
SecureString name;
|
||||
SecureString login;
|
||||
SecureString password;
|
||||
SecureString sUuid;
|
||||
SecureString sName;
|
||||
SecureString sLogin;
|
||||
SecureString sPassword;
|
||||
|
||||
public:
|
||||
CKeePassEntry(SecureString uuid, SecureString name, SecureString login, SecureString password) :
|
||||
uuid(uuid), name(name), login(login), password(password) {
|
||||
CKeePassEntry(SecureString sUuid, SecureString sName, SecureString sLogin, SecureString sPassword) :
|
||||
sUuid(sUuid), sName(sName), sLogin(sLogin), sPassword(sPassword) {
|
||||
}
|
||||
|
||||
SecureString getUuid() {
|
||||
return uuid;
|
||||
return sUuid;
|
||||
}
|
||||
|
||||
SecureString getName() {
|
||||
return name;
|
||||
return sName;
|
||||
}
|
||||
|
||||
SecureString getLogin() {
|
||||
return login;
|
||||
return sLogin;
|
||||
}
|
||||
|
||||
SecureString getPassword() {
|
||||
return password;
|
||||
return sPassword;
|
||||
}
|
||||
|
||||
};
|
||||
@ -83,48 +88,46 @@ class CKeePassIntegrator {
|
||||
class CKeePassResponse {
|
||||
|
||||
bool bSuccess;
|
||||
std::string sType;
|
||||
std::string sIV;
|
||||
std::string strType;
|
||||
std::string strIV;
|
||||
SecureString sKey;
|
||||
|
||||
void parseResponse(std::string sResponse);
|
||||
void parseResponse(std::string strResponse);
|
||||
|
||||
public:
|
||||
UniValue responseObj;
|
||||
CKeePassResponse(SecureString sKey, std::string sResponse) {
|
||||
CKeePassResponse(SecureString sKey, std::string strResponse) {
|
||||
this->sKey = sKey;
|
||||
parseResponse(sResponse);
|
||||
parseResponse(strResponse);
|
||||
}
|
||||
|
||||
bool getSuccess() {
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
SecureString getSecureStr(std::string sName);
|
||||
std::string getStr(std::string sName);
|
||||
SecureString getSecureStr(std::string strName);
|
||||
std::string getStr(std::string strName);
|
||||
std::vector<CKeePassEntry> getEntries();
|
||||
|
||||
SecureString decrypt(std::string sValue); // DecodeBase64 and decrypt arbitrary string value
|
||||
SecureString decrypt(std::string strValue); // DecodeBase64 and decrypt arbitrary string value
|
||||
|
||||
};
|
||||
|
||||
static SecureString generateRandomKey(size_t nSize);
|
||||
static std::string constructHTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders);
|
||||
void doHTTPPost(const std::string& sRequest, int& nStatus, std::string& sResponse);
|
||||
void doHTTPPost(const std::string& strRequest, int& nStatus, std::string& strResponse);
|
||||
void rpcTestAssociation(bool bTriggerUnlock);
|
||||
std::vector<CKeePassEntry> rpcGetLogins();
|
||||
void rpcSetLogin(const SecureString& strWalletPass, const SecureString& sEntryId);
|
||||
void rpcSetLogin(const SecureString& sWalletPass, const SecureString& sEntryId);
|
||||
|
||||
public:
|
||||
CKeePassIntegrator();
|
||||
void init();
|
||||
static SecureString generateKeePassKey();
|
||||
void rpcAssociate(std::string& sId, SecureString& sKeyBase64);
|
||||
void rpcAssociate(std::string& strId, SecureString& sKeyBase64);
|
||||
SecureString retrievePassphrase();
|
||||
void updatePassphrase(const SecureString& sWalletPassphrase);
|
||||
|
||||
};
|
||||
|
||||
extern CKeePassIntegrator keePassInt;
|
||||
|
||||
#endif
|
@ -2411,28 +2411,25 @@ UniValue keepass(const UniValue& params, bool fHelp) {
|
||||
|
||||
if (strCommand == "genkey")
|
||||
{
|
||||
SecureString result;
|
||||
SecureString sResult;
|
||||
// Generate RSA key
|
||||
//std::string keePassKey = CKeePassIntegrator::generateKey();
|
||||
//return keePassKey;
|
||||
SecureString sKey = CKeePassIntegrator::generateKeePassKey();
|
||||
result = "Generated Key: ";
|
||||
result += sKey;
|
||||
return result.c_str();
|
||||
sResult = "Generated Key: ";
|
||||
sResult += sKey;
|
||||
return sResult.c_str();
|
||||
}
|
||||
else if(strCommand == "init")
|
||||
{
|
||||
// Generate base64 encoded 256 bit RSA key and associate with KeePassHttp
|
||||
SecureString result;
|
||||
SecureString sResult;
|
||||
SecureString sKey;
|
||||
std::string sId;
|
||||
std::string sErrorMessage;
|
||||
keePassInt.rpcAssociate(sId, sKey);
|
||||
result = "Association successful. Id: ";
|
||||
result += sId.c_str();
|
||||
result += " - Key: ";
|
||||
result += sKey.c_str();
|
||||
return result.c_str();
|
||||
std::string strId;
|
||||
keePassInt.rpcAssociate(strId, sKey);
|
||||
sResult = "Association successful. Id: ";
|
||||
sResult += strId.c_str();
|
||||
sResult += " - Key: ";
|
||||
sResult += sKey.c_str();
|
||||
return sResult.c_str();
|
||||
}
|
||||
else if(strCommand == "setpassphrase")
|
||||
{
|
||||
|
@ -252,7 +252,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool anonymizeOnly
|
||||
}
|
||||
|
||||
// Verify KeePassIntegration
|
||||
if(strWalletPassphrase == "keepass" && GetBoolArg("-keepass", false)) {
|
||||
if (strWalletPassphrase == "keepass" && GetBoolArg("-keepass", false)) {
|
||||
try {
|
||||
strWalletPassphraseFinal = keePassInt.retrievePassphrase();
|
||||
} catch (std::exception& e) {
|
||||
@ -270,7 +270,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool anonymizeOnly
|
||||
LOCK(cs_wallet);
|
||||
BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
|
||||
{
|
||||
if(!crypter.SetKeyFromPassphrase(strWalletPassphraseFinal, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||
if (!crypter.SetKeyFromPassphrase(strWalletPassphraseFinal, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
|
||||
return false;
|
||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
|
||||
continue; // try another master key
|
||||
@ -302,7 +302,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
|
||||
try {
|
||||
strOldWalletPassphraseFinal = keePassInt.retrievePassphrase();
|
||||
} catch (std::exception& e) {
|
||||
LogPrintf("CWallet::ChangeWalletPassphrase could not retrieve passphrase from KeePass: Error: %s\n", e.what());
|
||||
LogPrintf("CWallet::ChangeWalletPassphrase -- could not retrieve passphrase from KeePass: Error: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -346,11 +346,11 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
|
||||
|
||||
// Update KeePass if necessary
|
||||
if(bUseKeePass) {
|
||||
LogPrintf("CWallet::ChangeWalletPassphrase - Updating KeePass with new passphrase");
|
||||
LogPrintf("CWallet::ChangeWalletPassphrase -- Updating KeePass with new passphrase");
|
||||
try {
|
||||
keePassInt.updatePassphrase(strNewWalletPassphrase);
|
||||
} catch (std::exception& e) {
|
||||
LogPrintf("CWallet::ChangeWalletPassphrase - could not update passphrase in KeePass: Error: %s\n", e.what());
|
||||
LogPrintf("CWallet::ChangeWalletPassphrase -- could not update passphrase in KeePass: Error: %s\n", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -653,11 +653,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||
|
||||
// Update KeePass if necessary
|
||||
if(GetBoolArg("-keepass", false)) {
|
||||
LogPrintf("CWallet::EncryptWallet - Updating KeePass with new passphrase");
|
||||
LogPrintf("CWallet::EncryptWallet -- Updating KeePass with new passphrase");
|
||||
try {
|
||||
keePassInt.updatePassphrase(strWalletPassphrase);
|
||||
} catch (std::exception& e) {
|
||||
LogPrintf("CWallet::EncryptWallet - could not update passphrase in KeePass: Error: %s\n", e.what());
|
||||
LogPrintf("CWallet::EncryptWallet -- could not update passphrase in KeePass: Error: %s\n", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user