AccountArchive: allow to unlock with raw key instead of password

Change-Id: Ic8b28a32f64862ac2dfae074d06f4eac470ab7e1
This commit is contained in:
Adrien Béraud
2024-01-02 14:44:42 -05:00
parent b627aa9c57
commit c1519ba4ec
24 changed files with 334 additions and 263 deletions

View File

@ -21,7 +21,7 @@
<tp:docstring>
Get all parameters of the specified account.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
<tp:docstring>
The account ID
</tp:docstring>
@ -75,7 +75,7 @@
</method>
<method name="getVolatileAccountDetails" tp:name-for-bindings="getVolatileAccountDetails">
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
<tp:docstring>
The account ID
</tp:docstring>
@ -99,7 +99,7 @@
<tp:rationale>Account settings are written to the configuration file when ring properly quits.</tp:rationale>
<tp:rationale>After calling this method, the core will emit the signal <tp:member-ref>accountDetailsChanged</tp:member-ref> with the updated data. The client must subscribe to this signal and use it to update its internal data structure.</tp:rationale>
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="MapStringString"/>
<arg type="a{ss}" name="details" direction="in" tp:type="String_String_Map">
@ -111,7 +111,7 @@
Set if this account is currently enabled (can be used).
It is only a runtime proprety with no impact on the "enabled" state of the account.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
<tp:docstring>
The account ID
</tp:docstring>
@ -124,7 +124,7 @@
</method>
<method name="setCredentials" tp:name-for-bindings="setCredentials">
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorMapStringString"/>
<arg type="aa{ss}" name="credentialInformation" direction="in" tp:type="String_String_Map">
@ -132,7 +132,7 @@
</method>
<method name="getCredentials" tp:name-for-bindings="getCredentials">
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
<arg type="aa{ss}" name="credentialInformation" direction="out">
@ -162,7 +162,7 @@
<tp:docstring>
Export account on the DHT using the given password and generated PIN (returned through exportOnRingEnded signal).
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="password" direction="in">
</arg>
@ -174,14 +174,24 @@
</method>
<method name="exportToFile" tp:name-for-bindings="exportToFile">
<tp:added version="5.1.0"/>
<tp:added version="15.0.0"/>
<tp:docstring>
Copy the account archive to the path provided in argument.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="destinationPath" direction="in">
</arg>
<arg type="s" name="scheme" direction="in">
<tp:docstring>
The password scheme. Accepted values:
<ul>
<li>(empty string): no encryption.</li>
<li>password: plain-text password string.</li>
<li>key: base64-encoded binary key.</li>
</ul>
</tp:docstring>
</arg>
<arg type="s" name="password" direction="in">
</arg>
<arg type="b" name="success" direction="out">
@ -195,7 +205,7 @@
<tp:docstring>
Notify clients when the exportOnRing operation ended.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="i" name="status">
<tp:docstring>
@ -215,15 +225,18 @@
</signal>
<method name="revokeDevice" tp:name-for-bindings="revokeDevice">
<tp:added version="15.0.0"/>
<tp:docstring>
Revoke device attached to the given Ring account, and publish the new revocation list.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
</arg>
<arg type="s" name="password" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="deviceId" direction="in">
</arg>
<arg type="s" name="scheme" direction="in">
</arg>
<arg type="s" name="password" direction="in">
</arg>
<arg type="b" name="success" direction="out">
<tp:docstring>
True if the operation was performed successfully.
@ -234,7 +247,7 @@
<tp:docstring>
Notify clients when the revokeDevice operation ended.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="s" name="deviceId">
</arg>
@ -254,7 +267,7 @@
<tp:docstring>
Notify clients when a newly created account's profile is available for storage.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="s" name="displayName">
</arg>
@ -266,7 +279,7 @@
<tp:docstring>
Notify clients when a new device linked to this account is found.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="MapStringString"/>
<arg type="a{ss}" name="devices" tp:type="String_String_Map">
@ -280,7 +293,7 @@
<tp:docstring>
Gets list of known devices for this account.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/>
<arg type="a{ss}" name="devices" direction="out">
@ -294,7 +307,7 @@
<tp:docstring>
Change the account archive password.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="oldPassword" direction="in">
</arg>
@ -311,11 +324,11 @@
<tp:docstring>
Performs name lookup for the specified account (if any) or using the default nameserver.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
The account to use. If empty, use the default nameserver.
</arg>
<arg type="s" name="nameserverUri" direction="in">
The name server URI to use, considered only if accountID is empty.
The name server URI to use, considered only if accountId is empty.
</arg>
<arg type="s" name="name" direction="in">
</arg>
@ -329,11 +342,11 @@
<tp:docstring>
Performs address lookup for the specified account (if any) or using the default nameserver.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
The account to use. If empty, use the default nameserver.
</arg>
<arg type="s" name="nameserverUri" direction="in">
The name server URI to use, considered only if accountID is empty.
The name server URI to use, considered only if accountId is empty.
</arg>
<arg type="s" name="address" direction="in">
<tp:docstring>
@ -352,7 +365,7 @@
Notify clients when a new registered address-name mapping is known.
If status is not success (0), requested field (name or address) is left empty.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="i" name="status">
<tp:docstring>
@ -375,18 +388,17 @@
<tp:docstring>
Performs name registration with RingNS protocol for the specified account.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
</arg>
<arg type="s" name="password" direction="in">
<tp:docstring>
Ring account main password.
</tp:docstring>
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="name" direction="in">
<tp:docstring>
Name to register. Must be lower-case ASCII, digits or "-" or "_".
</tp:docstring>
</arg>
<arg type="s" name="scheme" direction="in">
</arg>
<arg type="s" name="password" direction="in">
</arg>
<arg type="b" name="success" direction="out">
<tp:docstring>
True if the operation was initialized successfully. nameRegistrationEnded will be trigered on completion.
@ -398,7 +410,7 @@
<tp:docstring>
Notify clients when the registerName operation ended.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="i" name="status">
<tp:docstring>
@ -423,7 +435,7 @@
<tp:docstring>
Performs name registration with RingNS protocol for the specified account.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="query" direction="in">
<tp:docstring>
@ -440,7 +452,7 @@
<tp:docstring>
Notify clients when the registerName operation ended.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="i" name="status">
</arg>
@ -503,7 +515,7 @@
Send account registration (REGISTER) to the registrar.
Register the account if enable=true, unregister if enable=false.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
<tp:docstring>
The account ID
</tp:docstring>
@ -517,7 +529,7 @@
</method>
<method name="sendTextMessage" tp:name-for-bindings="sendTextMessage">
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="s" name="to" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="MapStringString"/>
<arg type="a{ss}" name="payloads" direction="in"/>
@ -536,7 +548,7 @@
</method>
<method name="cancelMessage" tp:name-for-bindings="cancelMessage">
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="t" name="id" direction="in"/>
<arg type="b" name="success" direction="out">
<tp:docstring>
@ -546,7 +558,7 @@
</method>
<method name="getLastMessages" tp:name-for-bindings="getLastMessages">
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="t" name="base_timestamp" direction="in"/>
<arg type="a(sa{ss}t)" name="messages" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="messages"/>
@ -554,7 +566,7 @@
<method name="getNearbyPeers" tp:name-for-bindings="getNearbyPeers">
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/>
<arg type="a{ss}" name="result" direction="out" tp:type="String_String_Map"/>
<tp:docstring>
@ -583,7 +595,7 @@
<tp:docstring>
Notify clients that a new text message has been received at the account level.
</tp:docstring>
<arg type="s" name="accountID"/>
<arg type="s" name="accountId"/>
<arg type="s" name="messageID"/>
<arg type="s" name="from"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out3" value="MapStringString"/>
@ -595,7 +607,7 @@
<tp:docstring>
Notify clients that a sent text message status have changed
</tp:docstring>
<arg type="s" name="accountID"/>
<arg type="s" name="accountId"/>
<arg type="s" name="conversationId"/>
<arg type="s" name="peer"/>
<arg type="s" name="id"/>
@ -629,7 +641,7 @@
<tp:docstring>
Notify clients that a vCard has been received
</tp:docstring>
<arg type="s" name="accountID"/>
<arg type="s" name="accountId"/>
<arg type="s" name="from"/>
<arg type="s" name="path"/>
</signal>
@ -881,7 +893,7 @@
</method>
<method name="getCodecDetails" tp:name-for-bindings="getCodecDetails">
<arg type="s" name="accountID" direction="in"></arg>
<arg type="s" name="accountId" direction="in"></arg>
<arg type="u" name="codecId" direction="in"></arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/>
<arg type="a{ss}" name="details" direction="out" tp:type="String_String_Map">
@ -890,7 +902,7 @@
<method name="setCodecDetails" tp:name-for-bindings="setCodecDetails">
<arg type="b" name="result" direction="out"></arg>
<arg type="s" name="accountID" direction="in"></arg>
<arg type="s" name="accountId" direction="in"></arg>
<arg type="u" name="codecId" direction="in"></arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="MapStringString"/>
<arg type="a{ss}" name="details" direction="in" tp:type="String_String_Map">
@ -899,7 +911,7 @@
<method name="getActiveCodecList" tp:name-for-bindings="getActiveCodecList">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorUInt"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="au" name="list" direction="out">
</arg>
@ -907,7 +919,7 @@
<method name="setActiveCodecList" tp:name-for-bindings="setActiveCodecList">
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="VectorUInt"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="au" name="list" direction="in">
</arg>
@ -1082,7 +1094,7 @@
</signal>
<signal name="accountDetailsChanged" tp:name-for-bindings="accountDetailsChanged">
<arg type="s" name="accountID">
<arg type="s" name="accountId">
<tp:docstring>
The account ID
</tp:docstring>
@ -1096,7 +1108,7 @@
</signal>
<signal name="registrationStateChanged" tp:name-for-bindings="registrationStateChanged">
<arg type="s" name="accountID"/>
<arg type="s" name="accountId"/>
<arg type="s" name="registrationState"/>
<arg type="i" name="registrationDetail">
<tp:docstring>
@ -1111,7 +1123,7 @@
</signal>
<signal name="volatileAccountDetailsChanged" tp:name-for-bindings="volatileAccountDetailsChanged">
<arg type="s" name="accountID">
<arg type="s" name="accountId">
<tp:docstring>
The account ID
</tp:docstring>
@ -1152,7 +1164,7 @@
Returns a list of supported encryption ciphers used to encrypt SIP messages. The list depends on the TLS library being used.
Only registered SIP accounts currently support setting custom ciphers. This method returns an empty list if TLS support is disabled in either pjproject or Jami.
</tp:docstring>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
<tp:docstring>
A SIP account id, other account IDs will be rejected.
</tp:docstring>
@ -1448,7 +1460,7 @@
<method name="getTrustRequests" tp:name-for-bindings="getTrustRequests">
<tp:added version="2.2.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
<arg type="aa{ss}" name="requests" direction="out">
@ -1463,7 +1475,7 @@
<method name="acceptTrustRequest" tp:name-for-bindings="acceptTrustRequest">
<tp:added version="2.2.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="from" direction="in">
</arg>
@ -1476,7 +1488,7 @@
<method name="discardTrustRequest" tp:name-for-bindings="discardTrustRequest">
<tp:added version="2.2.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="from" direction="in">
</arg>
@ -1492,7 +1504,7 @@
<tp:docstring>
Notify clients that a new contact request has been received.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="s" name="conversationId">
</arg>
@ -1506,7 +1518,7 @@
<method name="sendTrustRequest" tp:name-for-bindings="sendTrustRequest">
<tp:added version="2.2.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="to" direction="in">
</arg>
@ -1516,7 +1528,7 @@
<method name="addContact" tp:name-for-bindings="addContact">
<tp:added version="3.0.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="uri" direction="in">
</arg>
@ -1524,7 +1536,7 @@
<method name="removeContact" tp:name-for-bindings="removeContact">
<tp:added version="3.0.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="uri" direction="in">
</arg>
@ -1538,7 +1550,7 @@
<method name="getContactDetails" tp:name-for-bindings="getContactDetails">
<tp:added version="3.0.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<arg type="s" name="uri" direction="in">
</arg>
@ -1552,7 +1564,7 @@
<method name="getContacts" tp:name-for-bindings="getContacts">
<tp:added version="3.0.0"/>
<arg type="s" name="accountID" direction="in">
<arg type="s" name="accountId" direction="in">
</arg>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/>
<arg type="aa{ss}" name="contacts" direction="out">
@ -1567,7 +1579,7 @@
<tp:docstring>
Notify clients that a new contact has been added.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="s" name="uri">
</arg>
@ -1580,7 +1592,7 @@
<tp:docstring>
Notify clients that a new contact has been removed.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
</arg>
<arg type="s" name="uri">
</arg>
@ -1917,7 +1929,7 @@
<tp:docstring>
Notify clients that a media parameter changed.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
<tp:docstring>
An account id.
</tp:docstring>
@ -1939,7 +1951,7 @@
<tp:docstring>
Notify clients when migration is ended.
</tp:docstring>
<arg type="s" name="accountID">
<arg type="s" name="accountId">
<tp:docstring>
An account id.
</tp:docstring>
@ -2382,14 +2394,14 @@
<method name="setDefaultModerator" tp:name-for-bindings="setDefaultModerator">
<tp:added version="9.9.0"/>
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="s" name="peerURI" direction="in"/>
<arg type="b" name="state" direction="in"/>
</method>
<method name="getDefaultModerators" tp:name-for-bindings="getDefaultModerators">
<tp:added version="9.9.0"/>
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/>
<arg type="as" name="list" direction="out">
</arg>
@ -2397,23 +2409,23 @@
<method name="enableLocalModerators" tp:name-for-bindings="enableLocalModerators">
<tp:added version="9.9.0"/>
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="b" name="isModEnabled" direction="in"/>
</method>
<method name="isLocalModeratorsEnabled" tp:name-for-bindings="isLocalModeratorsEnabled">
<tp:added version="9.9.0"/>
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="b" name="isModEnabled" direction="out"/>
</method>
<method name="setAllModerators" tp:name-for-bindings="setAllModerators">
<tp:added version="9.10.0"/>
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="b" name="allModerators" direction="in"/>
</method>
<method name="isAllModerators" tp:name-for-bindings="isAllModerators">
<tp:added version="9.10.0"/>
<arg type="s" name="accountID" direction="in"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="b" name="allModerators" direction="out"/>
</method>

View File

@ -99,19 +99,21 @@ public:
auto
exportToFile(const std::string& accountID,
const std::string& destinationPath,
const std::string& scheme,
const std::string& password)
-> decltype(libjami::exportToFile(accountID, destinationPath, password))
-> decltype(libjami::exportToFile(accountID, destinationPath, scheme, password))
{
return libjami::exportToFile(accountID, destinationPath, password);
return libjami::exportToFile(accountID, destinationPath, scheme, password);
}
auto
revokeDevice(const std::string& accountID,
const std::string& password,
const std::string& device)
-> decltype(libjami::revokeDevice(accountID, password, device))
const std::string& device,
const std::string& scheme,
const std::string& password)
-> decltype(libjami::revokeDevice(accountID, device, scheme, password))
{
return libjami::revokeDevice(accountID, password, device);
return libjami::revokeDevice(accountID, device, scheme, password);
}
auto
@ -150,11 +152,12 @@ public:
auto
registerName(const std::string& account,
const std::string& password,
const std::string& name)
-> decltype(libjami::registerName(account, password, name))
const std::string& name,
const std::string& scheme,
const std::string& password)
-> decltype(libjami::registerName(account, name, scheme, password))
{
return libjami::registerName(account, password, name);
return libjami::registerName(account, name, scheme, password);
}
auto

View File

@ -84,48 +84,48 @@ struct Message
uint64_t received;
};
std::map<std::string, std::string> getAccountDetails(const std::string& accountID);
std::map<std::string, std::string> getVolatileAccountDetails(const std::string& accountID);
void setAccountDetails(const std::string& accountID, const std::map<std::string, std::string>& details);
void setAccountActive(const std::string& accountID, bool active);
std::map<std::string, std::string> getAccountDetails(const std::string& accountId);
std::map<std::string, std::string> getVolatileAccountDetails(const std::string& accountId);
void setAccountDetails(const std::string& accountId, const std::map<std::string, std::string>& details);
void setAccountActive(const std::string& accountId, bool active);
std::map<std::string, std::string> getAccountTemplate(const std::string& accountType);
void monitor(bool continuous);
std::vector<std::map<std::string, std::string>> getConnectionList(const std::string& accountId, const std::string& conversationId);
std::vector<std::map<std::string, std::string>> getChannelList(const std::string& accountId, const std::string& connectionId);
std::string addAccount(const std::map<std::string, std::string>& details);
void removeAccount(const std::string& accountID);
void removeAccount(const std::string& accountId);
std::vector<std::string> getAccountList();
void sendRegister(const std::string& accountID, bool enable);
void sendRegister(const std::string& accountId, bool enable);
void registerAllAccounts(void);
uint64_t sendAccountTextMessage(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& message, const int32_t& flag);
std::vector<libjami::Message> getLastMessages(const std::string& accountID, uint64_t base_timestamp);
uint64_t sendAccountTextMessage(const std::string& accountId, const std::string& to, const std::map<std::string, std::string>& message, const int32_t& flag);
std::vector<libjami::Message> getLastMessages(const std::string& accountId, uint64_t base_timestamp);
int getMessageStatus(uint64_t id);
int getMessageStatus(const std::string& accountID, uint64_t id);
bool cancelMessage(const std::string& accountID, uint64_t id);
void setIsComposing(const std::string& accountID, const std::string& conversationUri, bool isWriting);
bool setMessageDisplayed(const std::string& accountID, const std::string& conversationUri, const std::string& messageId, int status);
bool changeAccountPassword(const std::string& accountID, const std::string& password_old, const std::string& password_new);
int getMessageStatus(const std::string& accountId, uint64_t id);
bool cancelMessage(const std::string& accountId, uint64_t id);
void setIsComposing(const std::string& accountId, const std::string& conversationUri, bool isWriting);
bool setMessageDisplayed(const std::string& accountId, const std::string& conversationUri, const std::string& messageId, int status);
bool changeAccountPassword(const std::string& accountId, const std::string& password_old, const std::string& password_new);
bool isPasswordValid(const std::string& accountId, const std::string& password);
std::vector<uint8_t> getPasswordKey(const std::string& accountId, const std::string& password);
bool lookupName(const std::string& account, const std::string& nameserver, const std::string& name);
bool lookupAddress(const std::string& account, const std::string& nameserver, const std::string& address);
bool registerName(const std::string& account, const std::string& password, const std::string& name);
bool registerName(const std::string& account, const std::string& name, const std::string& scheme, const std::string& password);
bool searchUser(const std::string& account, const std::string& query);
std::vector<unsigned> getCodecList();
std::vector<std::string> getSupportedTlsMethod();
std::vector<std::string> getSupportedCiphers(const std::string& accountID);
std::map<std::string, std::string> getCodecDetails(const std::string& accountID, const unsigned& codecId);
bool setCodecDetails(const std::string& accountID, const unsigned& codecId, const std::map<std::string, std::string>& details);
std::vector<unsigned> getActiveCodecList(const std::string& accountID);
bool exportOnRing(const std::string& accountID, const std::string& password);
bool exportToFile(const std::string& accountID, const std::string& destinationPath, const std::string& password);
std::vector<std::string> getSupportedCiphers(const std::string& accountId);
std::map<std::string, std::string> getCodecDetails(const std::string& accountId, const unsigned& codecId);
bool setCodecDetails(const std::string& accountId, const unsigned& codecId, const std::map<std::string, std::string>& details);
std::vector<unsigned> getActiveCodecList(const std::string& accountId);
bool exportOnRing(const std::string& accountId, const std::string& password);
bool exportToFile(const std::string& accountId, const std::string& destinationPath, const std::string& scheme, const std::string& password);
std::map<std::string, std::string> getKnownRingDevices(const std::string& accountID);
bool revokeDevice(const std::string& accountID, const std::string& password, const std::string& deviceID);
std::map<std::string, std::string> getKnownRingDevices(const std::string& accountId);
bool revokeDevice(const std::string& accountId, const std::string& deviceId, const std::string& scheme, const std::string& password);
void setActiveCodecList(const std::string& accountID, const std::vector<unsigned>& list);
void setActiveCodecList(const std::string& accountId, const std::vector<unsigned>& list);
std::vector<std::map<std::string, std::string>> getActiveCalls(const std::string& accountId, const std::string& convId);
std::vector<std::string> getAudioPluginList();
@ -175,8 +175,8 @@ int32_t getRingingTimeout();
void setAccountsOrder(const std::string& order);
std::vector<std::map<std::string, std::string> > getCredentials(const std::string& accountID);
void setCredentials(const std::string& accountID, const std::vector<std::map<std::string, std::string> >& details);
std::vector<std::map<std::string, std::string> > getCredentials(const std::string& accountId);
void setCredentials(const std::string& accountId, const std::vector<std::map<std::string, std::string> >& details);
std::string getAddrFromInterfaceName(const std::string& interface);
@ -235,12 +235,12 @@ void pushNotificationReceived(const std::string& from, const std::map<std::strin
bool isAudioMeterActive(const std::string& id);
void setAudioMeterState(const std::string& id, bool state);
void setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state);
std::vector<std::string> getDefaultModerators(const std::string& accountID);
void enableLocalModerators(const std::string& accountID, bool isModEnabled);
bool isLocalModeratorsEnabled(const std::string& accountID);
void setAllModerators(const std::string& accountID, bool allModerators);
bool isAllModerators(const std::string& accountID);
void setDefaultModerator(const std::string& accountId, const std::string& peerURI, bool state);
std::vector<std::string> getDefaultModerators(const std::string& accountId);
void enableLocalModerators(const std::string& accountId, bool isModEnabled);
bool isLocalModeratorsEnabled(const std::string& accountId);
void setAllModerators(const std::string& accountId, bool allModerators);
bool isAllModerators(const std::string& accountId);
}

View File

@ -2,7 +2,7 @@ dnl Jami - configure.ac
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([Jami Daemon],[14.0.0],[jami@gnu.org],[jami])
AC_INIT([Jami Daemon],[15.0.0],[jami@gnu.org],[jami])
dnl Clear the implicit flags that default to '-g -O2', otherwise they
dnl take precedence over the values we set via the

View File

@ -346,19 +346,20 @@ exportOnRing(const std::string& accountId, const std::string& password)
bool
exportToFile(const std::string& accountId,
const std::string& destinationPath,
const std::string& scheme,
const std::string& password)
{
if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
return account->exportArchive(destinationPath, password);
return account->exportArchive(destinationPath, scheme, password);
}
return false;
}
bool
revokeDevice(const std::string& accountId, const std::string& password, const std::string& deviceID)
revokeDevice(const std::string& accountId, const std::string& deviceId, const std::string& scheme, const std::string& password)
{
if (const auto account = jami::Manager::instance().getAccount<jami::JamiAccount>(accountId)) {
return account->revokeDevice(password, deviceID);
return account->revokeDevice(deviceId, scheme, password);
}
return false;
}
@ -1046,11 +1047,11 @@ searchUser(const std::string& account, const std::string& query)
}
bool
registerName(const std::string& account, const std::string& password, const std::string& name)
registerName(const std::string& account, const std::string& name, const std::string& scheme, const std::string& password)
{
#if HAVE_RINGNS
if (auto acc = jami::Manager::instance().getAccount<JamiAccount>(account)) {
acc->registerName(password, name);
acc->registerName(name, scheme, password);
return true;
}
#endif

View File

@ -22,6 +22,8 @@
#include "fileutils.h"
#include "archiver.h"
#include "compiler_intrinsics.h"
#include "base64.h"
#include <opendht/crypto.h>
#ifdef __APPLE__
@ -302,10 +304,10 @@ loadCacheTextFile(const std::filesystem::path& path, std::chrono::system_clock::
return loadTextFile(path);
}
std::vector<uint8_t>
readArchive(const std::filesystem::path& path, const std::string& pwd)
ArchiveStorageData
readArchive(const std::filesystem::path& path, std::string_view scheme, const std::string& pwd)
{
JAMI_LOG("Reading archive from {}", path);
JAMI_LOG("Reading archive from {} with scheme '{}'", path, scheme);
auto isUnencryptedGzip = [](const std::vector<uint8_t>& data) {
// NOTE: some webserver modify gzip files and this can end with a gunzip in a gunzip
@ -325,45 +327,69 @@ readArchive(const std::filesystem::path& path, const std::string& pwd)
}
};
std::vector<uint8_t> data;
ArchiveStorageData ret;
// Read file
try {
data = dhtnet::fileutils::loadFile(path);
ret.data = dhtnet::fileutils::loadFile(path);
} catch (const std::exception& e) {
JAMI_ERR("Error loading archive: %s", e.what());
throw e;
}
if (isUnencryptedGzip(data)) {
if (isUnencryptedGzip(ret.data)) {
if (!pwd.empty())
JAMI_WARNING("A gunzip in a gunzip is detected. A webserver may have a bad config");
decompress(data);
decompress(ret.data);
}
if (!pwd.empty()) {
// Decrypt
if (scheme == ARCHIVE_AUTH_SCHEME_KEY) {
try {
data = dht::crypto::aesDecrypt(data, pwd);
ret.salt = dht::crypto::aesGetSalt(ret.data);
ret.data = dht::crypto::aesDecrypt(dht::crypto::aesGetEncrypted(ret.data), base64::decode(pwd));
} catch (const std::exception& e) {
JAMI_ERROR("Error decrypting archive: {}", e.what());
throw e;
}
decompress(data);
} else if (isUnencryptedGzip(data)) {
JAMI_WARNING("A gunzip in a gunzip is detected. A webserver may have a bad config");
decompress(data);
} else if (scheme == ARCHIVE_AUTH_SCHEME_PASSWORD) {
try {
ret.salt = dht::crypto::aesGetSalt(ret.data);
ret.data = dht::crypto::aesDecrypt(ret.data, pwd);
} catch (const std::exception& e) {
JAMI_ERROR("Error decrypting archive: {}", e.what());
throw e;
}
return data;
}
decompress(ret.data);
} else if (isUnencryptedGzip(ret.data)) {
JAMI_WARNING("A gunzip in a gunzip is detected. A webserver may have a bad config");
decompress(ret.data);
}
return ret;
}
void
writeArchive(const std::string& archive_str,
const std::filesystem::path& path,
const std::string& password)
std::string_view scheme,
const std::string& password,
const std::vector<uint8_t>& password_salt)
{
JAMI_LOG("Writing archive to {}", path);
if (not password.empty()) {
if (scheme == ARCHIVE_AUTH_SCHEME_KEY) {
// Encrypt using provided key
try {
auto key = base64::decode(password);
auto newArchive = dht::crypto::aesEncrypt(archiver::compress(archive_str), key);
saveFile(path, dht::crypto::aesBuildEncrypted(newArchive, password_salt));
} catch (const std::runtime_error& ex) {
JAMI_ERROR("Export failed: {}", ex.what());
return;
}
} else if (scheme == ARCHIVE_AUTH_SCHEME_PASSWORD and not password.empty()) {
// Encrypt using provided password
try {
saveFile(path, dht::crypto::aesEncrypt(archiver::compress(archive_str), password));

View File

@ -17,6 +17,8 @@
#pragma once
#include "jami/def.h"
#include <dhtnet/fileutils.h>
#include <string>
#include <vector>
#include <chrono>
@ -24,8 +26,7 @@
#include <cstdio>
#include <ios>
#include <filesystem>
#include <dhtnet/fileutils.h>
#include <string_view>
#ifndef _WIN32
#include <sys/stat.h> // mode_t
@ -42,6 +43,8 @@
namespace jami {
namespace fileutils {
using namespace std::literals;
std::filesystem::path get_home_dir();
std::filesystem::path get_config_dir(const char* pkg);
std::filesystem::path get_data_dir(const char* pkg);
@ -100,10 +103,20 @@ std::vector<uint8_t> loadCacheFile(const std::filesystem::path& path,
std::chrono::system_clock::duration maxAge);
std::string loadCacheTextFile(const std::filesystem::path& path, std::chrono::system_clock::duration maxAge);
std::vector<uint8_t> readArchive(const std::filesystem::path& path, const std::string& password = {});
static constexpr auto ARCHIVE_AUTH_SCHEME_NONE = ""sv;
static constexpr auto ARCHIVE_AUTH_SCHEME_PASSWORD = "password"sv;
static constexpr auto ARCHIVE_AUTH_SCHEME_KEY = "key"sv;
struct ArchiveStorageData {
std::vector<uint8_t> data;
std::vector<uint8_t> salt;
};
ArchiveStorageData readArchive(const std::filesystem::path& path, std::string_view scheme, const std::string& pwd);
void writeArchive(const std::string& data,
const std::filesystem::path& path,
const std::string& password = {});
std::string_view scheme,
const std::string& password = {}, const std::vector<uint8_t>& password_salt = {});
int64_t size(const std::filesystem::path& path);

View File

@ -132,6 +132,7 @@ constexpr static const char HAS_CUSTOM_USER_AGENT[] = "Account.hasCustomUserAgen
constexpr static const char ALLOW_CERT_FROM_HISTORY[] = "Account.allowCertFromHistory";
constexpr static const char ALLOW_CERT_FROM_CONTACT[] = "Account.allowCertFromContact";
constexpr static const char ALLOW_CERT_FROM_TRUSTED[] = "Account.allowCertFromTrusted";
constexpr static const char ARCHIVE_PASSWORD_SCHEME[] = "Account.archivePasswordScheme";
constexpr static const char ARCHIVE_PASSWORD[] = "Account.archivePassword";
constexpr static const char ARCHIVE_HAS_PASSWORD[] = "Account.archiveHasPassword";
constexpr static const char ARCHIVE_PATH[] = "Account.archivePath";

View File

@ -53,36 +53,38 @@ struct LIBJAMI_PUBLIC Message
uint64_t received;
};
LIBJAMI_PUBLIC std::map<std::string, std::string> getAccountDetails(const std::string& accountID);
LIBJAMI_PUBLIC std::map<std::string, std::string> getAccountDetails(const std::string& accountId);
LIBJAMI_PUBLIC std::map<std::string, std::string> getVolatileAccountDetails(
const std::string& accountID);
LIBJAMI_PUBLIC void setAccountDetails(const std::string& accountID,
const std::string& accountId);
LIBJAMI_PUBLIC void setAccountDetails(const std::string& accountId,
const std::map<std::string, std::string>& details);
LIBJAMI_PUBLIC void setAccountActive(const std::string& accountID,
LIBJAMI_PUBLIC void setAccountActive(const std::string& accountId,
bool active,
bool shutdownConnections = false);
LIBJAMI_PUBLIC std::map<std::string, std::string> getAccountTemplate(const std::string& accountType);
LIBJAMI_PUBLIC std::string addAccount(const std::map<std::string, std::string>& details,
const std::string& accountID = {});
const std::string& accountId = {});
LIBJAMI_PUBLIC void monitor(bool continuous);
LIBJAMI_PUBLIC std::vector<std::map<std::string, std::string>> getConnectionList(
const std::string& accountId, const std::string& conversationId);
LIBJAMI_PUBLIC std::vector<std::map<std::string, std::string>> getChannelList(
const std::string& accountId, const std::string& connectionId);
LIBJAMI_PUBLIC bool exportOnRing(const std::string& accountID, const std::string& password);
LIBJAMI_PUBLIC bool exportToFile(const std::string& accountID,
LIBJAMI_PUBLIC bool exportOnRing(const std::string& accountId, const std::string& password);
LIBJAMI_PUBLIC bool exportToFile(const std::string& accountId,
const std::string& destinationPath,
const std::string& scheme = {},
const std::string& password = {});
LIBJAMI_PUBLIC bool revokeDevice(const std::string& accountID,
const std::string& password,
const std::string& deviceID);
LIBJAMI_PUBLIC std::map<std::string, std::string> getKnownRingDevices(const std::string& accountID);
LIBJAMI_PUBLIC bool changeAccountPassword(const std::string& accountID,
LIBJAMI_PUBLIC bool revokeDevice(const std::string& accountId,
const std::string& deviceId,
const std::string& scheme = {},
const std::string& password = {});
LIBJAMI_PUBLIC std::map<std::string, std::string> getKnownRingDevices(const std::string& accountId);
LIBJAMI_PUBLIC bool changeAccountPassword(const std::string& accountId,
const std::string& password_old,
const std::string& password_new);
LIBJAMI_PUBLIC bool isPasswordValid(const std::string& accountID, const std::string& password);
LIBJAMI_PUBLIC std::vector<uint8_t> getPasswordKey(const std::string& accountID, const std::string& password);
LIBJAMI_PUBLIC bool isPasswordValid(const std::string& accountId, const std::string& password);
LIBJAMI_PUBLIC std::vector<uint8_t> getPasswordKey(const std::string& accountId, const std::string& password);
LIBJAMI_PUBLIC bool lookupName(const std::string& account,
const std::string& nameserver,
@ -91,43 +93,44 @@ LIBJAMI_PUBLIC bool lookupAddress(const std::string& account,
const std::string& nameserver,
const std::string& address);
LIBJAMI_PUBLIC bool registerName(const std::string& account,
const std::string& password,
const std::string& name);
const std::string& name,
const std::string& scheme = {},
const std::string& password = {});
LIBJAMI_PUBLIC bool searchUser(const std::string& account, const std::string& query);
LIBJAMI_PUBLIC void removeAccount(const std::string& accountID);
LIBJAMI_PUBLIC void removeAccount(const std::string& accountId);
LIBJAMI_PUBLIC std::vector<std::string> getAccountList();
LIBJAMI_PUBLIC void sendRegister(const std::string& accountID, bool enable);
LIBJAMI_PUBLIC void sendRegister(const std::string& accountId, bool enable);
LIBJAMI_PUBLIC void registerAllAccounts(void);
LIBJAMI_PUBLIC uint64_t sendAccountTextMessage(const std::string& accountID,
LIBJAMI_PUBLIC uint64_t sendAccountTextMessage(const std::string& accountId,
const std::string& to,
const std::map<std::string, std::string>& payloads,
int32_t flags);
LIBJAMI_PUBLIC bool cancelMessage(const std::string& accountID, uint64_t message);
LIBJAMI_PUBLIC std::vector<Message> getLastMessages(const std::string& accountID,
LIBJAMI_PUBLIC bool cancelMessage(const std::string& accountId, uint64_t message);
LIBJAMI_PUBLIC std::vector<Message> getLastMessages(const std::string& accountId,
const uint64_t& base_timestamp);
LIBJAMI_PUBLIC std::map<std::string, std::string> getNearbyPeers(const std::string& accountID);
LIBJAMI_PUBLIC std::map<std::string, std::string> getNearbyPeers(const std::string& accountId);
LIBJAMI_PUBLIC int getMessageStatus(uint64_t id);
LIBJAMI_PUBLIC int getMessageStatus(const std::string& accountID, uint64_t id);
LIBJAMI_PUBLIC void setIsComposing(const std::string& accountID,
LIBJAMI_PUBLIC int getMessageStatus(const std::string& accountId, uint64_t id);
LIBJAMI_PUBLIC void setIsComposing(const std::string& accountId,
const std::string& conversationUri,
bool isWriting);
LIBJAMI_PUBLIC bool setMessageDisplayed(const std::string& accountID,
LIBJAMI_PUBLIC bool setMessageDisplayed(const std::string& accountId,
const std::string& conversationUri,
const std::string& messageId,
int status);
LIBJAMI_PUBLIC std::vector<unsigned> getCodecList();
LIBJAMI_PUBLIC std::vector<std::string> getSupportedTlsMethod();
LIBJAMI_PUBLIC std::vector<std::string> getSupportedCiphers(const std::string& accountID);
LIBJAMI_PUBLIC std::map<std::string, std::string> getCodecDetails(const std::string& accountID,
LIBJAMI_PUBLIC std::vector<std::string> getSupportedCiphers(const std::string& accountId);
LIBJAMI_PUBLIC std::map<std::string, std::string> getCodecDetails(const std::string& accountId,
const unsigned& codecId);
LIBJAMI_PUBLIC bool setCodecDetails(const std::string& accountID,
LIBJAMI_PUBLIC bool setCodecDetails(const std::string& accountId,
const unsigned& codecId,
const std::map<std::string, std::string>& details);
LIBJAMI_PUBLIC std::vector<unsigned> getActiveCodecList(const std::string& accountID);
LIBJAMI_PUBLIC std::vector<unsigned> getActiveCodecList(const std::string& accountId);
LIBJAMI_PUBLIC void setActiveCodecList(const std::string& accountID,
LIBJAMI_PUBLIC void setActiveCodecList(const std::string& accountId,
const std::vector<unsigned>& list);
LIBJAMI_PUBLIC std::vector<std::string> getAudioPluginList();
@ -180,8 +183,8 @@ LIBJAMI_PUBLIC int32_t getRingingTimeout();
LIBJAMI_PUBLIC void setAccountsOrder(const std::string& order);
LIBJAMI_PUBLIC std::vector<std::map<std::string, std::string>> getCredentials(
const std::string& accountID);
LIBJAMI_PUBLIC void setCredentials(const std::string& accountID,
const std::string& accountId);
LIBJAMI_PUBLIC void setCredentials(const std::string& accountId,
const std::vector<std::map<std::string, std::string>>& details);
LIBJAMI_PUBLIC std::string getAddrFromInterfaceName(const std::string& iface);
@ -293,34 +296,34 @@ LIBJAMI_PUBLIC void setAudioMeterState(const std::string& id, bool state);
/**
* Add/remove default moderator for conferences
*/
LIBJAMI_PUBLIC void setDefaultModerator(const std::string& accountID,
LIBJAMI_PUBLIC void setDefaultModerator(const std::string& accountId,
const std::string& peerURI,
bool state);
/**
* Get default moderators for an account
*/
LIBJAMI_PUBLIC std::vector<std::string> getDefaultModerators(const std::string& accountID);
LIBJAMI_PUBLIC std::vector<std::string> getDefaultModerators(const std::string& accountId);
/**
* Enable/disable local moderators for conferences
*/
LIBJAMI_PUBLIC void enableLocalModerators(const std::string& accountID, bool isModEnabled);
LIBJAMI_PUBLIC void enableLocalModerators(const std::string& accountId, bool isModEnabled);
/**
* Get local moderators state
*/
LIBJAMI_PUBLIC bool isLocalModeratorsEnabled(const std::string& accountID);
LIBJAMI_PUBLIC bool isLocalModeratorsEnabled(const std::string& accountId);
/**
* Enable/disable all moderators for conferences
*/
LIBJAMI_PUBLIC void setAllModerators(const std::string& accountID, bool allModerators);
LIBJAMI_PUBLIC void setAllModerators(const std::string& accountId, bool allModerators);
/**
* Get all moderators state
*/
LIBJAMI_PUBLIC bool isAllModerators(const std::string& accountID);
LIBJAMI_PUBLIC bool isAllModerators(const std::string& accountId);
struct LIBJAMI_PUBLIC AudioSignal
{

View File

@ -105,6 +105,7 @@ public:
{
std::string scheme;
std::string uri;
std::string password_scheme;
std::string password;
virtual ~AccountCredentials() {};
};
@ -162,8 +163,9 @@ public:
using RevokeDeviceCallback = std::function<void(RevokeDeviceResult)>;
virtual void addDevice(const std::string& /*password*/, AddDeviceCallback) {};
virtual bool revokeDevice(const std::string& /*password*/,
const std::string& /*device*/,
virtual bool revokeDevice(const std::string& /*device*/,
std::string_view /*scheme*/,
const std::string& /*password*/,
RevokeDeviceCallback)
{
return false;
@ -260,8 +262,9 @@ public:
LookupCallback cb);
virtual void lookupAddress(const std::string& address, LookupCallback cb);
virtual bool searchUser(const std::string& /*query*/, SearchCallback /*cb*/) { return false; }
virtual void registerName(const std::string& password,
const std::string& name,
virtual void registerName(const std::string& name,
std::string_view scheme,
const std::string& password,
RegistrationCallback cb)
= 0;

View File

@ -27,10 +27,12 @@
namespace jami {
void
AccountArchive::deserialize(const std::vector<uint8_t>& dat)
AccountArchive::deserialize(const std::vector<uint8_t>& dat, const std::vector<uint8_t>& salt)
{
JAMI_DEBUG("Loading account archive ({:d} bytes)", dat.size());
password_salt = salt;
// Decode string
auto* char_data = reinterpret_cast<const char*>(&dat[0]);
std::string err;

View File

@ -57,26 +57,28 @@ struct AccountArchive
/** Account configuration */
std::map<std::string, std::string> config;
/** Salt for the archive encryption password. */
std::vector<uint8_t> password_salt;
AccountArchive() = default;
AccountArchive(const std::vector<uint8_t>& data) { deserialize(data); }
AccountArchive(const std::filesystem::path& path, const std::string& password) { load(path, password); }
AccountArchive(const std::vector<uint8_t>& data, const std::vector<uint8_t>& password_salt = {}) { deserialize(data, password_salt); }
AccountArchive(const std::filesystem::path& path, std::string_view scheme, const std::string& pwd) { load(path, scheme, pwd); }
/** Serialize structured archive data to memory. */
std::string serialize() const;
/** Deserialize archive from memory. */
void deserialize(const std::vector<uint8_t>& data);
void deserialize(const std::vector<uint8_t>& data, const std::vector<uint8_t>& salt);
/** Load archive from file, optionally encrypted with provided password. */
void load(const std::filesystem::path& path, const std::string& password = {})
{
deserialize(fileutils::readArchive(path, password));
void load(const std::filesystem::path& path, std::string_view scheme, const std::string& pwd) {
auto data = fileutils::readArchive(path, scheme, pwd);
deserialize(data.data, data.salt);
}
/** Save archive to file, optionally encrypted with provided password. */
void save(const std::filesystem::path& path, const std::string& password = {}) const
{
fileutils::writeArchive(serialize(), path, password);
void save(const std::filesystem::path& path, std::string_view scheme, const std::string& password) const {
fileutils::writeArchive(serialize(), path, scheme, password, password_salt);
}
};

View File

@ -161,12 +161,12 @@ ArchiveAccountManager::updateCertificates(AccountArchive& archive, dht::crypto::
}
bool
ArchiveAccountManager::setValidity(const std::string& password,
ArchiveAccountManager::setValidity(std::string_view scheme, const std::string& password,
dht::crypto::Identity& device,
const dht::InfoHash& id,
int64_t validity)
{
auto archive = readArchive(password);
auto archive = readArchive(scheme, password);
// We need the CA key to resign certificates
if (not archive.id.first or not *archive.id.first or not archive.id.second or not archive.ca_key
or not *archive.ca_key)
@ -201,7 +201,7 @@ ArchiveAccountManager::setValidity(const std::string& password,
}
if (updated) {
archive.save(fileutils::getFullPath(path_, archivePath_), password);
archive.save(fileutils::getFullPath(path_, archivePath_), scheme, password);
}
if (updated or not id or device.second->getId() == id) {
@ -241,7 +241,7 @@ ArchiveAccountManager::loadFromFile(AuthContext& ctx)
JAMI_WARN("[Auth] loading archive from: %s", ctx.credentials->uri.c_str());
AccountArchive archive;
try {
archive = AccountArchive(ctx.credentials->uri, ctx.credentials->password);
archive = AccountArchive(ctx.credentials->uri, ctx.credentials->password_scheme, ctx.credentials->password);
} catch (const std::exception& ex) {
JAMI_WARN("[Auth] can't read file: %s", ex.what());
ctx.onFailure(AuthError::INVALID_ARGUMENTS, ex.what());
@ -350,7 +350,7 @@ ArchiveAccountManager::migrateAccount(AuthContext& ctx)
JAMI_WARN("[Auth] account migration needed");
AccountArchive archive;
try {
archive = readArchive(ctx.credentials->password);
archive = readArchive(ctx.credentials->password_scheme, ctx.credentials->password);
} catch (...) {
JAMI_DBG("[Auth] Can't load archive");
ctx.onFailure(AuthError::INVALID_ARGUMENTS, "");
@ -374,7 +374,7 @@ ArchiveAccountManager::onArchiveLoaded(AuthContext& ctx,
auto ethAccount = dev::KeyPair(dev::Secret(a.eth_key)).address().hex();
dhtnet::fileutils::check_dir(path_, 0700);
a.save(fileutils::getFullPath(path_, archivePath_), ctx.credentials ? ctx.credentials->password : "");
a.save(fileutils::getFullPath(path_, archivePath_), ctx.credentials ? ctx.credentials->password_scheme : "", ctx.credentials ? ctx.credentials->password : "");
if (not a.id.second->isCA()) {
JAMI_ERR("[Auth] trying to sign a certificate with a non-CA.");
@ -568,10 +568,10 @@ ArchiveAccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnounce
}
AccountArchive
ArchiveAccountManager::readArchive(const std::string& pwd) const
ArchiveAccountManager::readArchive(std::string_view scheme, const std::string& pwd) const
{
JAMI_DBG("[Auth] reading account archive");
return AccountArchive(fileutils::getFullPath(path_, archivePath_), pwd);
return AccountArchive(fileutils::getFullPath(path_, archivePath_), scheme, pwd);
}
void
@ -625,13 +625,13 @@ ArchiveAccountManager::updateArchive(AccountArchive& archive) const
}
void
ArchiveAccountManager::saveArchive(AccountArchive& archive, const std::string& pwd)
ArchiveAccountManager::saveArchive(AccountArchive& archive, std::string_view scheme, const std::string& pwd)
{
try {
updateArchive(archive);
if (archivePath_.empty())
archivePath_ = "export.gz";
archive.save(fileutils::getFullPath(path_, archivePath_), pwd);
archive.save(fileutils::getFullPath(path_, archivePath_), scheme, pwd);
} catch (const std::runtime_error& ex) {
JAMI_ERR("[Auth] Can't export archive: %s", ex.what());
return;
@ -644,7 +644,8 @@ ArchiveAccountManager::changePassword(const std::string& password_old,
{
try {
auto path = fileutils::getFullPath(path_, archivePath_);
AccountArchive(path, password_old).save(path, password_new);
AccountArchive(path, fileutils::ARCHIVE_AUTH_SCHEME_PASSWORD, password_old)
.save(path, fileutils::ARCHIVE_AUTH_SCHEME_PASSWORD, password_new);
return true;
} catch (const std::exception&) {
return false;
@ -693,7 +694,7 @@ ArchiveAccountManager::addDevice(const std::string& password, AddDeviceCallback
try {
JAMI_DBG("[Auth] exporting account");
a = this_->readArchive(password);
a = this_->readArchive("password", password);
// Generate random PIN
pin_str = generatePIN();
@ -731,15 +732,15 @@ ArchiveAccountManager::addDevice(const std::string& password, AddDeviceCallback
}
bool
ArchiveAccountManager::revokeDevice(
ArchiveAccountManager::revokeDevice(const std::string& device,
std::string_view scheme,
const std::string& password,
const std::string& device,
RevokeDeviceCallback cb)
{
auto fa = dht::ThreadPool::computation().getShared<AccountArchive>(
[this, password] { return readArchive(password); });
[this, scheme=std::string(scheme), password] { return readArchive(scheme, password); });
findCertificate(DeviceId(device),
[fa = std::move(fa), password, device, cb, w=weak_from_this()](
[fa = std::move(fa), scheme=std::string(scheme), password, device, cb, w=weak_from_this()](
const std::shared_ptr<dht::crypto::Certificate>& crt) mutable {
if (not crt) {
cb(RevokeDeviceResult::ERROR_NETWORK);
@ -768,7 +769,7 @@ ArchiveAccountManager::revokeDevice(
auto h = a.id.second->getId();
this_->dht_->put(h, a.revoked, dht::DoneCallback {}, {}, true);
this_->saveArchive(a, password);
this_->saveArchive(a, scheme, password);
this_->info_->contacts->removeAccountDevice(crt->getLongId());
cb(RevokeDeviceResult::SUCCESS);
this_->syncDevices();
@ -777,22 +778,19 @@ ArchiveAccountManager::revokeDevice(
}
bool
ArchiveAccountManager::exportArchive(const std::string& destinationPath, const std::string& password)
ArchiveAccountManager::exportArchive(const std::string& destinationPath, std::string_view scheme, const std::string& password)
{
try {
// Save contacts if possible before exporting
AccountArchive archive = readArchive(password);
AccountArchive archive = readArchive(scheme, password);
updateArchive(archive);
archive.save(fileutils::getFullPath(path_, archivePath_), password);
auto archivePath = fileutils::getFullPath(path_, archivePath_);
archive.save(archivePath, scheme, password);
// Export the file
auto sourcePath = fileutils::getFullPath(path_, archivePath_);
std::ifstream src(sourcePath, std::ios::in | std::ios::binary);
if (!src)
return false;
std::ofstream dst(destinationPath, std::ios::out | std::ios::binary);
dst << src.rdbuf();
return true;
std::error_code ec;
std::filesystem::copy_file(archivePath, destinationPath, std::filesystem::copy_options::overwrite_existing, ec);
return !ec;
} catch (const std::runtime_error& ex) {
JAMI_ERR("[Auth] Can't export archive: %s", ex.what());
return false;
@ -806,7 +804,7 @@ bool
ArchiveAccountManager::isPasswordValid(const std::string& password)
{
try {
readArchive(password);
readArchive(fileutils::ARCHIVE_AUTH_SCHEME_PASSWORD, password);
return true;
} catch (...) {
return false;
@ -815,8 +813,9 @@ ArchiveAccountManager::isPasswordValid(const std::string& password)
#if HAVE_RINGNS
void
ArchiveAccountManager::registerName(const std::string& password,
const std::string& name,
ArchiveAccountManager::registerName(const std::string& name,
std::string_view scheme,
const std::string& password,
RegistrationCallback cb)
{
std::string signedName;
@ -827,7 +826,7 @@ ArchiveAccountManager::registerName(const std::string& password,
std::string ethAccount;
try {
auto archive = readArchive(password);
auto archive = readArchive(scheme, password);
auto privateKey = archive.id.first;
const auto& pk = privateKey->getPublicKey();
publickey = pk.toString();

View File

@ -57,25 +57,24 @@ public:
void syncDevices() override;
void addDevice(const std::string& password, AddDeviceCallback) override;
bool revokeDevice(
const std::string& password,
const std::string& device,
bool revokeDevice(const std::string& device,
std::string_view scheme, const std::string& password,
RevokeDeviceCallback) override;
bool exportArchive(const std::string& destinationPath, const std::string& password);
bool exportArchive(const std::string& destinationPath, std::string_view scheme, const std::string& password);
bool isPasswordValid(const std::string& password) override;
#if HAVE_RINGNS
/*void lookupName(const std::string& name, LookupCallback cb) override;
void lookupAddress(const std::string& address, LookupCallback cb) override;*/
void registerName(const std::string& password,
const std::string& name,
void registerName(const std::string& name,
std::string_view scheme, const std::string& password,
RegistrationCallback cb) override;
#endif
/**
* Change the validity of a certificate. If hash is empty, update all certificates
*/
bool setValidity(const std::string& password,
bool setValidity(std::string_view scheme, const std::string& password,
dht::crypto::Identity& device,
const dht::InfoHash& id,
int64_t validity);
@ -102,8 +101,8 @@ private:
const dht::crypto::Certificate& device,
const std::string& ethAccount);
void updateArchive(AccountArchive& content /*, const ContactList& syncData*/) const;
void saveArchive(AccountArchive& content, const std::string& pwd);
AccountArchive readArchive(const std::string& pwd) const;
void saveArchive(AccountArchive& content, std::string_view scheme, const std::string& pwd);
AccountArchive readArchive(std::string_view scheme, const std::string& password) const;
static std::pair<std::vector<uint8_t>, dht::InfoHash> computeKeys(const std::string& password,
const std::string& pin,
bool previous = false);

View File

@ -931,7 +931,7 @@ JamiAccount::loadConfig()
getAccountID().c_str(),
e.what());
}
loadAccount(config().archive_password, config().archive_pin, config().archive_path);
loadAccount(config().archive_password_scheme, config().archive_password, config().archive_pin, config().archive_path);
}
bool
@ -999,19 +999,19 @@ JamiAccount::addDevice(const std::string& password)
}
bool
JamiAccount::exportArchive(const std::string& destinationPath, const std::string& password)
JamiAccount::exportArchive(const std::string& destinationPath, std::string_view scheme, const std::string& password)
{
if (auto manager = dynamic_cast<ArchiveAccountManager*>(accountManager_.get())) {
return manager->exportArchive(destinationPath, password);
return manager->exportArchive(destinationPath, scheme, password);
}
return false;
}
bool
JamiAccount::setValidity(const std::string& pwd, const dht::InfoHash& id, int64_t validity)
JamiAccount::setValidity(std::string_view scheme, const std::string& pwd, const dht::InfoHash& id, int64_t validity)
{
if (auto manager = dynamic_cast<ArchiveAccountManager*>(accountManager_.get())) {
if (manager->setValidity(pwd, id_, id, validity)) {
if (manager->setValidity(scheme, pwd, id_, id, validity)) {
saveIdentity(id_, idPath_, DEVICE_ID_PATH);
return true;
}
@ -1062,12 +1062,12 @@ JamiAccount::isValidAccountDevice(const dht::crypto::Certificate& cert) const
}
bool
JamiAccount::revokeDevice(const std::string& password, const std::string& device)
JamiAccount::revokeDevice(const std::string& device, std::string_view scheme, const std::string& password)
{
if (not accountManager_)
return false;
return accountManager_
->revokeDevice(password, device, [this, device](AccountManager::RevokeDeviceResult result) {
->revokeDevice(device, scheme, password, [this, device](AccountManager::RevokeDeviceResult result) {
emitSignal<libjami::ConfigurationSignal::DeviceRevocationEnded>(getAccountID(),
device,
static_cast<int>(
@ -1091,7 +1091,8 @@ JamiAccount::saveIdentity(const dht::crypto::Identity id,
// must be called while configurationMutex_ is locked
void
JamiAccount::loadAccount(const std::string& archive_password,
JamiAccount::loadAccount(const std::string& archive_password_scheme,
const std::string& archive_password,
const std::string& archive_pin,
const std::string& archive_path)
{
@ -1283,6 +1284,10 @@ JamiAccount::loadAccount(const std::string& archive_password,
}
creds->password = archive_password;
bool hasPassword = !archive_password.empty();
if (hasPassword && archive_password_scheme.empty())
creds->password_scheme = fileutils::ARCHIVE_AUTH_SCHEME_PASSWORD;
else
creds->password_scheme = archive_password_scheme;
accountManager_->initAuthentication(
getAccountID(),
@ -1297,7 +1302,7 @@ JamiAccount::loadAccount(const std::string& archive_password,
if (not sthis) return;
JAMI_LOG("[Account {}] Auth success!", getAccountID());
dhtnet::fileutils::check_dir(idPath_.c_str(), 0700);
dhtnet::fileutils::check_dir(idPath_, 0700);
auto id = info.identity;
editConfig([&](JamiAccountConfig& conf) {
@ -1420,13 +1425,13 @@ JamiAccount::lookupAddress(const std::string& addr)
}
void
JamiAccount::registerName(const std::string& password, const std::string& name)
JamiAccount::registerName(const std::string& name, const std::string& scheme, const std::string& password)
{
std::lock_guard<std::recursive_mutex> lock(configurationMutex_);
if (accountManager_)
accountManager_->registerName(
password,
name,
scheme, password,
[acc = getAccountID(), name, w = weak()](NameDirectory::RegistrationResponse response) {
int res
= (response == NameDirectory::RegistrationResponse::success)

View File

@ -344,8 +344,8 @@ public:
* doesn't have a password
* @return if the archive was exported
*/
bool exportArchive(const std::string& destinationPath, const std::string& password = {});
bool revokeDevice(const std::string& password, const std::string& device);
bool exportArchive(const std::string& destinationPath, std::string_view scheme = {}, const std::string& password = {});
bool revokeDevice(const std::string& device, std::string_view scheme, const std::string& password = {});
std::map<std::string, std::string> getKnownDevices() const;
bool isPasswordValid(const std::string& password);
@ -361,7 +361,7 @@ public:
#if HAVE_RINGNS
void lookupName(const std::string& name);
void lookupAddress(const std::string& address);
void registerName(const std::string& password, const std::string& name);
void registerName(const std::string& name, const std::string& scheme, const std::string& password);
#endif
bool searchUser(const std::string& nameQuery);
@ -550,7 +550,7 @@ public:
* @param validity New validity
* @note forceReloadAccount may be necessary to retrigger the migration
*/
bool setValidity(const std::string& pwd, const dht::InfoHash& id, int64_t validity);
bool setValidity(std::string_view scheme, const std::string& pwd, const dht::InfoHash& id, int64_t validity);
/**
* Try to reload the account to force the identity to be updated
*/
@ -666,10 +666,9 @@ private:
void forEachPendingCall(const DeviceId& deviceId,
const std::function<void(const std::shared_ptr<SIPCall>&)>& cb);
void loadAccountFromFile(const std::string& archive_path, const std::string& archive_password);
void loadAccountFromDHT(const std::string& archive_password, const std::string& archive_pin);
void loadAccountFromArchive(AccountArchive&& archive, const std::string& archive_password);
void loadAccount(const std::string& archive_password = {},
void loadAccount(const std::string& archive_password_scheme = {},
const std::string& archive_password = {},
const std::string& archive_pin = {},
const std::string& archive_path = {});

View File

@ -200,6 +200,7 @@ JamiAccountConfig::fromMap(const std::map<std::string, std::string>& details)
// parseString(details, libjami::Account::ConfProperties::USERNAME, username);
parseString(details, libjami::Account::ConfProperties::ARCHIVE_PASSWORD, archive_password);
parseString(details, libjami::Account::ConfProperties::ARCHIVE_PASSWORD_SCHEME, archive_password_scheme);
parseString(details, libjami::Account::ConfProperties::ARCHIVE_PIN, archive_pin);
std::transform(archive_pin.begin(), archive_pin.end(), archive_pin.begin(), ::toupper);
parseString(details, libjami::Account::ConfProperties::ARCHIVE_PATH, archive_path);

View File

@ -68,6 +68,7 @@ struct JamiAccountConfig : public SipAccountBaseConfig {
std::string archivePath {"archive.gz"};
bool archiveHasPassword {true};
// not saved, only used client->daemon
std::string archive_password_scheme;
std::string archive_password;
std::string archive_pin;
std::string archive_path;

View File

@ -19,6 +19,7 @@
#include "server_account_manager.h"
#include "base64.h"
#include "jami/account_const.h"
#include "fileutils.h"
#include <opendht/http.h>
#include <opendht/log.h>
@ -578,11 +579,11 @@ ServerAccountManager::syncBlueprintConfig(SyncBlueprintCallback onSuccess)
}
bool
ServerAccountManager::revokeDevice(const std::string& password,
const std::string& device,
ServerAccountManager::revokeDevice(const std::string& device,
std::string_view scheme, const std::string& password,
RevokeDeviceCallback cb)
{
if (not info_) {
if (not info_ || scheme != fileutils::ARCHIVE_AUTH_SCHEME_PASSWORD) {
if (cb)
cb(RevokeDeviceResult::ERROR_CREDENTIALS);
return false;
@ -618,7 +619,7 @@ ServerAccountManager::revokeDevice(const std::string& password,
}
void
ServerAccountManager::registerName(const std::string&, const std::string&, RegistrationCallback cb)
ServerAccountManager::registerName(const std::string&, std::string_view scheme, const std::string&, RegistrationCallback cb)
{
cb(NameDirectory::RegistrationResponse::unsupported);
}

View File

@ -59,13 +59,13 @@ public:
void syncBlueprintConfig(SyncBlueprintCallback onSuccess);
bool revokeDevice(const std::string& password,
const std::string& device,
bool revokeDevice(const std::string& device,
std::string_view scheme, const std::string& password,
RevokeDeviceCallback cb) override;
bool searchUser(const std::string& query, SearchCallback cb) override;
void registerName(const std::string& password,
const std::string& name,
void registerName(const std::string& name,
std::string_view scheme, const std::string& password,
RegistrationCallback cb) override;
private:

View File

@ -149,7 +149,7 @@ AccountArchiveTest::testExportImportPassword()
{
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
CPPUNIT_ASSERT(bobAccount->exportArchive("test.gz", "test"));
CPPUNIT_ASSERT(bobAccount->exportArchive("test.gz", "password", "test"));
std::map<std::string, std::string> details = libjami::getAccountTemplate("RING");
details[ConfProperties::ARCHIVE_PATH] = "test.gz";
@ -168,7 +168,7 @@ AccountArchiveTest::testExportImportPasswordDoubleGunzip()
{
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
CPPUNIT_ASSERT(bobAccount->exportArchive("test.gz", "test"));
CPPUNIT_ASSERT(bobAccount->exportArchive("test.gz", "password", "test"));
auto dat = fileutils::loadFile("test.gz");
archiver::compressGzip(dat, "test.gz");

View File

@ -112,7 +112,7 @@ MigrationTest::testLoadExpiredAccount()
auto accountExpiration = archive.id.second->getExpiration();
// Update validity
CPPUNIT_ASSERT(aliceAccount->setValidity("", {}, 9));
CPPUNIT_ASSERT(aliceAccount->setValidity("", "", {}, 9));
archive = AccountArchive(archivePath, "");
deviceCert = dht::crypto::Certificate(fileutils::loadFile(devicePath));
auto newDeviceExpiration = deviceCert.getExpiration();
@ -295,7 +295,7 @@ MigrationTest::testExpiredDeviceInSwarm()
CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&]() { return aliceRegistering; }));
auto aliceDevice = std::string(aliceAccount->currentDeviceId());
CPPUNIT_ASSERT(aliceAccount->setValidity("", {}, 90));
CPPUNIT_ASSERT(aliceAccount->setValidity("", "", {}, 90));
auto now = std::chrono::system_clock::now();
aliceRegistered = false;
aliceAccount->forceReloadAccount();

View File

@ -196,7 +196,7 @@ NameDirectoryTest::testRegisterName()
cv.notify_one();
}));
libjami::registerSignalHandlers(confHandlers);
CPPUNIT_ASSERT(libjami::registerName(aliceId, "", "foo"));
CPPUNIT_ASSERT(libjami::registerName(aliceId, "", "password", "foo"));
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return nameRegistered; }));
}

View File

@ -118,7 +118,7 @@ RevokeTest::testRevokeDevice()
auto alice2Account = Manager::instance().getAccount<JamiAccount>(alice2Id);
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(60), [&] { return knownChanged; }));
alice2Device = std::string(alice2Account->currentDeviceId());
aliceAccount->revokeDevice("", alice2Device);
aliceAccount->revokeDevice(alice2Device);
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&] { return deviceRevoked; }));
std::remove("test.gz");
@ -143,7 +143,7 @@ RevokeTest::testRevokeInvalidDevice()
cv.notify_one();
}));
libjami::registerSignalHandlers(confHandlers);
aliceAccount->revokeDevice("", "foo");
aliceAccount->revokeDevice("foo");
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&] { return revokeFailed; }));
}