/** * Activate an account on the server. * * @param LP1 Password hash for the account */ tABC_CC ABC_LoginServerActivate(const Lobby &lobby, tABC_U08Buf LP1, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/" ABC_SERVER_ACCOUNT_ACTIVATE; ServerReplyJson replyJson; char *szPost = NULL; json_t *pJSON_Root = NULL; // create the post data pJSON_Root = json_pack("{ssss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LP1_FIELD, base64Encode(LP1).c_str()); szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); // decode the result ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); exit: ABC_FREE_STR(szPost); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
/** * Changes the password for an account on the server. * * This function sends information to the server to change the password for an account. * Either the old LP1 or LRA1 can be used for authentication. * * @param oldLP1 Old password hash for the account (if this is empty, LRA1 is used instead) * @param LRA1 LRA1 for the account (used if oldP1 is empty) */ tABC_CC ABC_LoginServerChangePassword(const Lobby &lobby, tABC_U08Buf oldLP1, tABC_U08Buf newLP1, tABC_U08Buf newLRA1, const CarePackage &carePackage, const LoginPackage &loginPackage, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/" ABC_SERVER_CHANGE_PASSWORD_PATH; ServerReplyJson replyJson; char *szPost = NULL; std::string carePackageStr; std::string loginPackageStr; json_t *pJSON_OldLRA1 = NULL; json_t *pJSON_NewLRA1 = NULL; json_t *pJSON_Root = NULL; ABC_CHECK_NULL_BUF(oldLP1); ABC_CHECK_NULL_BUF(newLP1); ABC_CHECK_NEW(carePackage.encode(carePackageStr)); ABC_CHECK_NEW(loginPackage.encode(loginPackageStr)); // Encode those: pJSON_Root = json_pack("{ss, ss, ss, ss, ss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LP1_FIELD, base64Encode(oldLP1).c_str(), ABC_SERVER_JSON_NEW_LP1_FIELD, base64Encode(newLP1).c_str(), ABC_SERVER_JSON_CARE_PACKAGE_FIELD, carePackageStr.c_str(), ABC_SERVER_JSON_LOGIN_PACKAGE_FIELD, loginPackageStr.c_str()); // set up the recovery, if any: if (newLRA1.size()) { pJSON_NewLRA1 = json_string(base64Encode(newLRA1).c_str()); json_object_set(pJSON_Root, ABC_SERVER_JSON_NEW_LRA1_FIELD, pJSON_NewLRA1); } // create the post data szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); exit: ABC_FREE_STR(szPost); if (pJSON_OldLRA1) json_decref(pJSON_OldLRA1); if (pJSON_NewLRA1) json_decref(pJSON_NewLRA1); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
/** * Uploads the pin package. * * @param LP1 Login + Password hash * @param DID Device Id * @param LPIN1 Hashed pin * @param szPinPackage Pin package * @param szAli auto-logout interval */ tABC_CC ABC_LoginServerUpdatePinPackage(const Lobby &lobby, tABC_U08Buf LP1, tABC_U08Buf DID, tABC_U08Buf LPIN1, const std::string &pinPackage, time_t ali, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/" ABC_SERVER_PIN_PACK_UPDATE_PATH; ServerReplyJson replyJson; char *szPost = NULL; json_t *pJSON_Root = NULL; char szALI[DATETIME_LENGTH]; ABC_CHECK_NULL_BUF(LP1); ABC_CHECK_NULL_BUF(DID); ABC_CHECK_NULL_BUF(LPIN1); // format the ali strftime(szALI, DATETIME_LENGTH, "%Y-%m-%dT%H:%M:%S", gmtime(&ali)); // Encode those: pJSON_Root = json_pack("{ss, ss, ss, ss, ss, ss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LP1_FIELD, base64Encode(LP1).c_str(), ABC_SERVER_JSON_DID_FIELD, base64Encode(DID).c_str(), ABC_SERVER_JSON_LPIN1_FIELD, base64Encode(LPIN1).c_str(), JSON_ACCT_PIN_PACKAGE, pinPackage.c_str(), ABC_SERVER_JSON_ALI_FIELD, szALI); // create the post data szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); exit: ABC_FREE_STR(szPost); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
tABC_CC ABC_LoginServerGetPinPackage(tABC_U08Buf DID, tABC_U08Buf LPIN1, char **szPinPackage, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/" ABC_SERVER_PIN_PACK_GET_PATH; ServerReplyJson replyJson; json_t *pJSON_Value = NULL; json_t *pJSON_Root = NULL; char *szPost = NULL; ABC_CHECK_NULL_BUF(DID); ABC_CHECK_NULL_BUF(LPIN1); pJSON_Root = json_pack("{ss, ss}", ABC_SERVER_JSON_DID_FIELD, base64Encode(DID).c_str(), ABC_SERVER_JSON_LPIN1_FIELD, base64Encode(LPIN1).c_str()); szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); // Check the result ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); // get the results field pJSON_Value = replyJson.results().get(); ABC_CHECK_ASSERT((pJSON_Value && json_is_object(pJSON_Value)), ABC_CC_JSONError, "Error parsing server JSON pin package results"); // get the pin_package field pJSON_Value = json_object_get(pJSON_Value, JSON_ACCT_PIN_PACKAGE); ABC_CHECK_ASSERT((pJSON_Value && json_is_string(pJSON_Value)), ABC_CC_JSONError, "Error pin package JSON results"); // copy the value ABC_STRDUP(*szPinPackage, json_string_value(pJSON_Value)); exit: if (pJSON_Root) json_decref(pJSON_Root); ABC_FREE_STR(szPost); return cc; }
/** * Creates an account on the server. * * This function sends information to the server to create an account. * If the account was created, ABC_CC_Ok is returned. * If the account already exists, ABC_CC_AccountAlreadyExists is returned. * * @param LP1 Password hash for the account */ tABC_CC ABC_LoginServerCreate(const Lobby &lobby, tABC_U08Buf LP1, const CarePackage &carePackage, const LoginPackage &loginPackage, const char *szRepoAcctKey, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/" ABC_SERVER_ACCOUNT_CREATE_PATH; ServerReplyJson replyJson; char *szPost = NULL; std::string carePackageStr; std::string loginPackageStr; json_t *pJSON_Root = NULL; ABC_CHECK_NULL_BUF(LP1); ABC_CHECK_NEW(carePackage.encode(carePackageStr)); ABC_CHECK_NEW(loginPackage.encode(loginPackageStr)); // create the post data pJSON_Root = json_pack("{ssssssssss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LP1_FIELD, base64Encode(LP1).c_str(), ABC_SERVER_JSON_CARE_PACKAGE_FIELD, carePackageStr.c_str(), ABC_SERVER_JSON_LOGIN_PACKAGE_FIELD, loginPackageStr.c_str(), ABC_SERVER_JSON_REPO_FIELD, szRepoAcctKey); szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); // decode the result ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); exit: ABC_FREE_STR(szPost); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
/** * Serializes a LoginPackage object to a JSON string. */ tABC_CC ABC_LoginPackageEncode(tABC_LoginPackage *pSelf, char **pszLoginPackage, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; json_t *pJSON_Root = NULL; // Build the main body: pJSON_Root = json_object(); ABC_CHECK_NULL(pJSON_Root); // Write master key: if (pSelf->EMK_LP2) { ABC_CHECK_JSON(json_object_set(pJSON_Root, JSON_ACCT_EMK_LP2_FIELD, pSelf->EMK_LP2)); } if (pSelf->EMK_LRA3) { ABC_CHECK_JSON(json_object_set(pJSON_Root, JSON_ACCT_EMK_LRA3_FIELD, pSelf->EMK_LRA3)); } // Write sync key: ABC_CHECK_JSON(json_object_set(pJSON_Root, JSON_ACCT_ESYNCKEY_FIELD, pSelf->ESyncKey)); // Write server keys: if (pSelf->ELP1) { ABC_CHECK_JSON(json_object_set(pJSON_Root, JSON_ACCT_ELP1_FIELD, pSelf->ELP1)); } if (pSelf->ELRA1) { ABC_CHECK_JSON(json_object_set(pJSON_Root, JSON_ACCT_ELRA1_FIELD, pSelf->ELRA1)); } // Write out: *pszLoginPackage = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_INDENT(4) | JSON_PRESERVE_ORDER); ABC_CHECK_NULL(*pszLoginPackage); exit: if (pJSON_Root) json_decref(pJSON_Root); return cc; }
tABC_CC ABC_LoginServerOtpRequest(const char *szUrl, const Lobby &lobby, tABC_U08Buf LP1, JsonPtr *results, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; ServerReplyJson replyJson; char *szPost = NULL; json_t *pJSON_Root = NULL; // create the post data pJSON_Root = json_pack("{ss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str()); // If there is a LP1 provided if (LP1.data()) { json_object_set_new(pJSON_Root, ABC_SERVER_JSON_LP1_FIELD, json_string(base64Encode(LP1).c_str())); } { auto key = lobby.otpKey(); if (key) json_object_set_new(pJSON_Root, ABC_SERVER_JSON_OTP_FIELD, json_string(key->totp().c_str())); } json_object_set_new(pJSON_Root, ABC_SERVER_JSON_OTP_RESET_AUTH, json_string(gOtpResetAuth.c_str())); szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, szUrl, szPost)); ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); if (results) *results = replyJson.results(); exit: ABC_FREE_STR(szPost); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
/** * Enables 2 Factor authentication * * @param LP1 Password hash for the account * @param timeout Amount of time needed for a reset to complete */ tABC_CC ABC_LoginServerOtpEnable(const Lobby &lobby, tABC_U08Buf LP1, const char *szOtpSecret, const long timeout, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/otp/on"; ServerReplyJson replyJson; char *szPost = NULL; json_t *pJSON_Root = NULL; ABC_CHECK_NULL_BUF(LP1); // create the post data pJSON_Root = json_pack("{sssssssi}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LP1_FIELD, base64Encode(LP1).c_str(), ABC_SERVER_JSON_OTP_SECRET_FIELD, szOtpSecret, ABC_SERVER_JSON_OTP_TIMEOUT, timeout); { auto key = lobby.otpKey(); if (key) json_object_set_new(pJSON_Root, ABC_SERVER_JSON_OTP_FIELD, json_string(key->totp().c_str())); } szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); exit: ABC_FREE_STR(szPost); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
/** * Serializes a CarePackage object to a JSON string. */ tABC_CC ABC_CarePackageEncode(tABC_CarePackage *pSelf, char **pszCarePackage, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; json_t *pJSON_Root = NULL; json_t *pJSON_SNRP2 = NULL; json_t *pJSON_SNRP3 = NULL; json_t *pJSON_SNRP4 = NULL; // Build the SNRP's: ABC_CHECK_RET(ABC_CryptoCreateJSONObjectSNRP(pSelf->pSNRP2, &pJSON_SNRP2, pError)); ABC_CHECK_RET(ABC_CryptoCreateJSONObjectSNRP(pSelf->pSNRP3, &pJSON_SNRP3, pError)); ABC_CHECK_RET(ABC_CryptoCreateJSONObjectSNRP(pSelf->pSNRP4, &pJSON_SNRP4, pError)); // Build the main body: pJSON_Root = json_pack("{s:O, s:O, s:O}", JSON_ACCT_SNRP2_FIELD, pJSON_SNRP2, JSON_ACCT_SNRP3_FIELD, pJSON_SNRP3, JSON_ACCT_SNRP4_FIELD, pJSON_SNRP4); ABC_CHECK_NULL(pJSON_Root); // Build the ERQ, if any: if (pSelf->ERQ) { ABC_CHECK_JSON(json_object_set(pJSON_Root, JSON_ACCT_ERQ_FIELD, pSelf->ERQ)); } // Write out: *pszCarePackage = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_INDENT(4) | JSON_PRESERVE_ORDER); ABC_CHECK_NULL(*pszCarePackage); exit: if (pJSON_Root) json_decref(pJSON_Root); if (pJSON_SNRP2) json_decref(pJSON_SNRP2); if (pJSON_SNRP3) json_decref(pJSON_SNRP3); if (pJSON_SNRP4) json_decref(pJSON_SNRP4); return cc; }
/** * Creates the json package with a single field and its int value */ tABC_CC ABC_UtilCreateIntJSONString(int value, const char *szFieldName, char **pszJSON, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; json_t *pJSON_Root = NULL; ABC_CHECK_NULL(szFieldName); ABC_CHECK_NULL(pszJSON); // create the jansson object pJSON_Root = json_pack("{si}", szFieldName, value); *pszJSON = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_INDENT(4) | JSON_PRESERVE_ORDER); exit: if (pJSON_Root) json_decref(pJSON_Root); return cc; }
static tABC_CC ABC_WalletServerRepoPost(const Lobby &lobby, tABC_U08Buf LP1, const char *szWalletAcctKey, const char *szPath, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/" + std::string(szPath); ServerReplyJson replyJson; char *szPost = NULL; json_t *pJSON_Root = NULL; ABC_CHECK_NULL_BUF(LP1); // create the post data pJSON_Root = json_pack("{ssssss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LP1_FIELD, base64Encode(LP1).c_str(), ABC_SERVER_JSON_REPO_WALLET_FIELD, szWalletAcctKey); szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); exit: ABC_FREE_STR(szPost); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
tABC_CC ABC_LoginServerOtpPending(std::list<DataChunk> users, std::list<bool> &isPending, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; std::string url = ABC_SERVER_ROOT "/otp/pending/check"; ServerReplyJson replyJson; JsonArray arrayJson; json_t *pJSON_Root = NULL; char *szPost = NULL; std::map<std::string, bool> userMap; std::list<std::string> usersEncoded; std::string param; for (const auto &u : users) { std::string username = base64Encode(u); param += (username + ","); userMap[username] = false; usersEncoded.push_back(username); } // create the post data pJSON_Root = json_pack("{ss}", "l1s", param.c_str()); szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, url, szPost)); ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); arrayJson = replyJson.results(); if (arrayJson) { size_t rows = arrayJson.size(); for (size_t i = 0; i < rows; i++) { json_t *pJSON_Row = arrayJson[i].get(); ABC_CHECK_ASSERT((pJSON_Row && json_is_object(pJSON_Row)), ABC_CC_JSONError, "Error parsing JSON array element object"); json_t *pJSON_Value = json_object_get(pJSON_Row, "login"); ABC_CHECK_ASSERT((pJSON_Value && json_is_string(pJSON_Value)), ABC_CC_JSONError, "Error otp/pending/login JSON"); std::string username(json_string_value(pJSON_Value)); pJSON_Value = json_object_get(pJSON_Row, ABC_SERVER_JSON_OTP_PENDING); ABC_CHECK_ASSERT((pJSON_Value && json_is_boolean(pJSON_Value)), ABC_CC_JSONError, "Error otp/pending/pending JSON"); if (json_is_true(pJSON_Value)) { userMap[username] = json_is_true(pJSON_Value);; } } } isPending.clear(); for (auto &username: usersEncoded) { isPending.push_back(userMap[username]); } exit: ABC_FREE_STR(szPost); if (pJSON_Root) json_decref(pJSON_Root); return cc; }
/** * Helper function for getting CarePackage or LoginPackage. */ static tABC_CC ABC_LoginServerGetString(const Lobby &lobby, tABC_U08Buf LP1, tABC_U08Buf LRA1, const char *szURL, const char *szField, char **szResponse, tABC_Error *pError) { tABC_CC cc = ABC_CC_Ok; HttpReply reply; ServerReplyJson replyJson; json_t *pJSON_Value = NULL; json_t *pJSON_Root = NULL; char *szPost = NULL; // create the post data with or without LP1 if (LP1.data() == NULL && LRA1.data() == NULL) { pJSON_Root = json_pack("{ss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str()); } else { if (LP1.data() == NULL) { pJSON_Root = json_pack("{ssss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LRA1_FIELD, base64Encode(LRA1).c_str()); } else { pJSON_Root = json_pack("{ssss}", ABC_SERVER_JSON_L1_FIELD, base64Encode(lobby.authId()).c_str(), ABC_SERVER_JSON_LP1_FIELD, base64Encode(LP1).c_str()); } } { auto key = lobby.otpKey(); if (key) json_object_set_new(pJSON_Root, ABC_SERVER_JSON_OTP_FIELD, json_string(key->totp().c_str())); } szPost = ABC_UtilStringFromJSONObject(pJSON_Root, JSON_COMPACT); // send the command ABC_CHECK_NEW(AirbitzRequest().post(reply, szURL, szPost)); // Check the results, and store json if successful ABC_CHECK_NEW(replyJson.decode(reply.body)); ABC_CHECK_NEW(replyJson.ok()); // get the care package pJSON_Value = replyJson.results().get(); ABC_CHECK_ASSERT((pJSON_Value && json_is_object(pJSON_Value)), ABC_CC_JSONError, "Error parsing server JSON care package results"); pJSON_Value = json_object_get(pJSON_Value, szField); ABC_CHECK_ASSERT((pJSON_Value && json_is_string(pJSON_Value)), ABC_CC_JSONError, "Error care package JSON results"); ABC_STRDUP(*szResponse, json_string_value(pJSON_Value)); exit: if (pJSON_Root) json_decref(pJSON_Root); ABC_FREE_STR(szPost); return cc; }