21 #include <boost/foreach.hpp> 23 #include <event2/event.h> 24 #include <event2/http.h> 25 #include <event2/buffer.h> 26 #include <event2/keyvalq_struct.h> 28 #include <openssl/bio.h> 29 #include <openssl/evp.h> 30 #include <openssl/buffer.h> 44 b64 = BIO_new(BIO_f_base64());
45 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
46 mem = BIO_new_mem_buf((
void *) &sInput[0], sInput.size());
50 if(sInput.size() % 4 != 0) {
51 throw std::runtime_error(
"Input length should be a multiple of 4");
53 size_t nMaxLen = sInput.size() / 4 * 3;
54 output.resize(nMaxLen);
58 nLen = BIO_read(b64, (
void *) &output[0], sInput.size());
71 b64 = BIO_new(BIO_f_base64());
72 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
73 mem = BIO_new(BIO_s_mem());
77 BIO_write(b64, &sInput[0], sInput.size());
78 (void) BIO_flush(b64);
82 BIO_get_mem_ptr(b64, &bptr);
94 :sKeyBase64(
" "), sKey(
" "), sUrl(
" ")
134 std::string sCipherValue;
138 throw std::runtime_error(
"Unable to encrypt Verifier");
146 return requestObj.write();
152 strIV = std::string(&sIVSecure[0], sIVSecure.size());
155 addStrParameter(
"Nonce", std::string(&sNonceBase64Secure[0], sNonceBase64Secure.size()));
156 addStrParameter(
"Verifier", sNonceBase64Secure);
157 addStrParameter(
"RequestType", strType);
163 if(!responseValue.
read(strResponse))
165 throw std::runtime_error(
"Unable to parse KeePassHttp response");
168 responseObj = responseValue;
171 bSuccess = responseObj[
"Success"].
get_bool();
172 strType = getStr(
"RequestType");
178 return responseObj[strName].get_str();
183 std::string strValueBase64Encrypted(responseObj[strName].get_str());
187 sValue = decrypt(strValueBase64Encrypted);
189 catch (std::exception &e)
191 std::string strError =
"Exception occured while decrypting ";
192 strError += strName +
": " + e.what();
193 throw std::runtime_error(strError);
200 std::string strValueEncrypted =
DecodeBase64(strValueBase64Encrypted);
204 throw std::runtime_error(
"Unable to decrypt value.");
212 std::vector<CKeePassEntry> vEntries;
215 for(
size_t i = 0; i < aEntries.
size(); i++)
217 SecureString sEntryUuid(decrypt(aEntries[i][
"Uuid"].get_str().c_str()));
218 SecureString sEntryName(decrypt(aEntries[i][
"Name"].get_str().c_str()));
219 SecureString sEntryLogin(decrypt(aEntries[i][
"Login"].get_str().c_str()));
220 SecureString sEntryPassword(decrypt(aEntries[i][
"Password"].get_str().c_str()));
221 CKeePassEntry entry(sEntryUuid, sEntryName, sEntryLogin, sEntryPassword);
222 vEntries.push_back(entry);
244 std::ostringstream streamOut;
245 streamOut <<
"POST / HTTP/1.1\r\n" 247 <<
"Host: localhost\r\n" 248 <<
"Content-Type: application/json\r\n" 249 <<
"Content-Length: " << strMsg.size() <<
"\r\n" 250 <<
"Connection: close\r\n" 251 <<
"Accept: application/json\r\n";
252 BOOST_FOREACH(
const PAIRTYPE(std::string, std::string)& item, mapRequestHeaders)
253 streamOut << item.first <<
": " << item.second <<
"\r\n";
254 streamOut <<
"\r\n" << strMsg;
256 return streamOut.str();
278 reply->
nStatus = evhttp_request_get_response_code(req);
280 struct evbuffer *buf = evhttp_request_get_input_buffer(req);
283 size_t size = evbuffer_get_length(buf);
284 const char *
data = (
const char*)evbuffer_pullup(buf, size);
287 evbuffer_drain(buf, size);
317 struct event_base *
base = event_base_new();
319 throw std::runtime_error(
"cannot create event_base");
324 throw std::runtime_error(
"create connection failed");
332 struct evhttp_request *req = evhttp_request_new(
http_request_done, (
void*)&response);
334 throw std::runtime_error(
"create http request failed");
336 struct evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
337 assert(output_headers);
339 evhttp_add_header(output_headers,
"User-Agent", (
"dash-json-rpc/" +
FormatFullVersion()).c_str());
341 evhttp_add_header(output_headers,
"Accept",
"application/json");
342 evhttp_add_header(output_headers,
"Content-Type",
"application/json");
344 evhttp_add_header(output_headers,
"Connection",
"close");
348 LogPrint(
"keepass",
"CKeePassIntegrator::doHTTPPost -- send POST data\n");
374 struct evbuffer * output_buffer = evhttp_request_get_output_buffer(req);
375 assert(output_buffer);
376 evbuffer_add(output_buffer, sRequest.data(), sRequest.size());
378 int r = evhttp_make_request(evcon, req, EVHTTP_REQ_POST,
"/");
380 evhttp_connection_free(evcon);
381 event_base_free(
base);
382 throw std::runtime_error(
"send http request failed");
385 event_base_dispatch(
base);
386 evhttp_connection_free(evcon);
387 event_base_free(
base);
408 nStatus = response.nStatus;
409 if (response.nStatus == 0)
410 throw std::runtime_error(
"couldn't connect to server");
412 throw std::runtime_error(
strprintf(
"server returned HTTP error %d", response.nStatus));
413 else if (response.strBody.empty())
414 throw std::runtime_error(
"no response from server");
418 if (!valReply.
read(response.strBody))
419 throw std::runtime_error(
"couldn't parse reply from server");
422 throw std::runtime_error(
"expected reply to have result, error and id properties");
424 strResponse = valReply.
get_str();
430 request.
addStrParameter(
"TriggerUnlock", std::string(bTriggerUnlock ?
"true" :
"false"));
433 std::string strResponse;
437 LogPrint(
"keepass",
"CKeePassIntegrator::rpcTestAssociation -- send result: status: %d response: %s\n", nStatus, strResponse);
453 std::string strResponse;
459 LogPrint(
"keepass",
"CKeePassIntegrator::rpcGetLogins -- send result: status: %d\n", nStatus);
463 std::string strError =
"Error returned by KeePassHttp: HTTP code ";
464 strError +=
itostr(nStatus);
465 strError +=
" - Response: ";
466 strError +=
" response: [";
467 strError += strResponse;
469 throw std::runtime_error(strError);
477 std::string strError =
"KeePassHttp returned failure status";
478 throw std::runtime_error(strError);
494 LogPrint(
"keepass",
"CKeePassIntegrator::rpcSetLogin -- send Url: %s\n",
sUrl);
499 if(sEntryId.size() != 0)
505 std::string strResponse;
510 LogPrint(
"keepass",
"CKeePassIntegrator::rpcSetLogin -- send result: status: %d response: %s\n", nStatus, strResponse);
514 std::string strError =
"Error returned: HTTP code ";
515 strError +=
itostr(nStatus);
516 strError +=
" - Response: ";
517 strError +=
" response: [";
518 strError += strResponse;
520 throw std::runtime_error(strError);
528 throw std::runtime_error(
"KeePassHttp returned failure status");
549 std::string strResponse;
553 LogPrint(
"keepass",
"CKeePassIntegrator::rpcAssociate -- send result: status: %d response: %s\n", nStatus, strResponse);
557 std::string strError =
"Error returned: HTTP code ";
558 strError +=
itostr(nStatus);
559 strError +=
" - Response: ";
560 strError +=
" response: [";
561 strError += strResponse;
563 throw std::runtime_error(strError);
571 throw std::runtime_error(
"KeePassHttp returned failure status");
575 strId = response.
getStr(
"Id");
585 throw std::runtime_error(
"keepasskey parameter is not defined. Please specify the configuration parameter.");
589 throw std::runtime_error(
"keepassid parameter is not defined. Please specify the configuration parameter.");
593 throw std::runtime_error(
"keepassname parameter is not defined. Please specify the configuration parameter.");
597 std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries =
rpcGetLogins();
600 if(vecEntries.size() == 0)
602 throw std::runtime_error(
"KeePassHttp returned 0 matches, please verify the keepassurl setting.");
604 if(vecEntries.size() > 1)
606 throw std::runtime_error(
"KeePassHttp returned multiple matches, bailing out.");
609 return vecEntries[0].getPassword();
618 throw std::runtime_error(
"keepasskey parameter is not defined. Please specify the configuration parameter.");
622 throw std::runtime_error(
"keepassid parameter is not defined. Please specify the configuration parameter.");
626 throw std::runtime_error(
"keepassname parameter is not defined. Please specify the configuration parameter.");
631 std::string strError;
634 std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries =
rpcGetLogins();
636 if(vecEntries.size() > 1)
638 throw std::runtime_error(
"KeePassHttp returned multiple matches, bailing out.");
641 if(vecEntries.size() == 1)
643 sEntryId = vecEntries[0].getUuid();
SecureString decrypt(std::string strValue)
std::vector< CKeePassEntry > rpcGetLogins()
bool EncryptAES256(const SecureString &sKey, const SecureString &sPlaintext, const std::string &sIV, std::string &sCiphertext)
static const unsigned int DEFAULT_KEEPASS_HTTP_PORT
SecureString EncodeBase64Secure(const SecureString &sInput)
void RandAddSeedPerfmon()
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
static const char * KEEPASS_HTTP_HOST
static std::string constructHTTPPost(const std::string &strMsg, const std::map< std::string, std::string > &mapRequestHeaders)
void rpcTestAssociation(bool bTriggerUnlock)
bool DecryptAES256(const SecureString &sKey, const std::string &sCiphertext, const std::string &sIV, SecureString &sPlaintext)
bool push_back(const UniValue &val)
string EncodeBase64(const unsigned char *pch, size_t len)
void addStrParameter(std::string strName, std::string strValue)
SecureString DecodeBase64Secure(const SecureString &sInput)
std::string getStr(std::string strName)
static SecureString generateRandomKey(size_t nSize)
void memory_cleanse(void *ptr, size_t len)
const UniValue & get_obj() const
bool GetBoolArg(const std::string &strArg, bool fDefault)
static const int KEEPASS_CRYPTO_BLOCK_SIZE
static int LogPrint(const char *category, const char *format)
vector< unsigned char > DecodeBase64(const char *p, bool *pfInvalid)
static secp256k1_context * ctx
static void http_request_done(struct evhttp_request *req, void *ctx)
void parseResponse(std::string strResponse)
static std::pair< std::string, UniValue > Pair(const char *cKey, const char *cVal)
static const int KEEPASS_HTTP_CONNECT_TIMEOUT
std::string FormatFullVersion()
void updatePassphrase(const SecureString &sWalletPassphrase)
CKeePassIntegrator keePassInt
void rpcSetLogin(const SecureString &sWalletPass, const SecureString &sEntryId)
static SecureString generateKeePassKey()
void rpcAssociate(std::string &strId, SecureString &sKeyBase64)
void GetRandBytes(unsigned char *buf, int num)
SecureString retrievePassphrase()
std::string GetArg(const std::string &strArg, const std::string &strDefault)
void doHTTPPost(const std::string &strRequest, int &nStatus, std::string &strResponse)
static const int KEEPASS_CRYPTO_KEY_SIZE
std::vector< CKeePassEntry > getEntries()
bool read(const char *raw)
std::string strKeePassEntryName
const UniValue & get_array() const
std::string get_str() const
std::string itostr(int n)
SecureString getSecureStr(std::string strName)