Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dbus methods: listIdentity, trust #728

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ local.properties
.settings/
out/
.DS_Store
/bin/
47 changes: 47 additions & 0 deletions man/signal-cli-dbus.5.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ Where <type> is according to DBus specification:
* <as> : String Array
* <ax> : Array of signed 64 bit integer
* <b> : Boolean (0|1)
* <v> : Variant
* <x> : Signed 64 bit integer
* <> : no return value
* {...} : dictionary

Exceptions are the names of the Java Exceptions returned in the body field. They typically contain an additional message with details. All Exceptions begin with "org.asamk.Signal.Error." which is omitted here for better readability.

Expand Down Expand Up @@ -189,6 +191,38 @@ setContactName(number<s>,name<>) -> <>::
* number : Phone number
* name : Name to be set in contacts (in local storage with signal-cli)

listIdentities() -> identities<a{sv}>::
* contactNumber : Phone number of contact
* identities : Array of dictionary entries with key contactNumber and values listed below
** trustLevel : String representation of trust level
** dateAdded : String representation of date added
** fingerprint : String representation of hexadecimal fingerprint
** safetyNumber : String representation of safety number (10 or 11 space-separated six-digit numbers)

Returns an array of dictionary entries for all contacts (obtained by listNumbers() and screened to exclude those with no identity information). For each dictionary, the key is the contactNumber and the value is a list of four strings: trustLevel, dateAdded, fingerprint, safetyNumber.

Exceptions: None

listIdentities(contactNumber<s>) -> identity<{sv}>::
* contactNumber : Phone number of contact
* identity : Dictionary with key contactNumber and values listed below
** trustLevel : String representation of trust level
** dateAdded : String representation of date added
** fingerprint : String representation of hexadecimal fingerprint
** safetyNumber : String representation of safety number (10 or 11 space-separated six-digit numbers)

Same as listIdentities(), but for one particular contact. Returns a dictionary where the key is the contactNumber and the value is a list of four strings: trustLevel, dateAdded, fingerprint, safetyNumber.

Exceptions: InvalidNumber

trust(number<s>, safetyNumber<s>) -> <>::
* number : Phone number
* safetyNumber : String representation of safety number (10 or 11 space-separated six-digit numbers)

Verify the safety number associated with the phone number.

Exceptions: Failure, InvalidNumber

getGroupIds() -> groupList<aay>::
groupList : Array of Byte arrays representing the internal group identifiers

Expand Down Expand Up @@ -229,6 +263,19 @@ isGroupBlocked(groupId<ay>) -> state<b>::

Exceptions: None, for unknown groups 0 (false) is returned

removePin() -> <>::

Removes registration PIN protection.

Exception: Failure

setPin(pin<s>) -> <>::
* pin : PIN you set after registration (resets after 7 days of inactivity)

Sets a registration lock PIN, to prevent others from registering your number.

Exception: Failure

version() -> version<s>::
* version : Version string of signal-cli

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/asamk/Signal.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import org.freedesktop.dbus.exceptions.DBusExecutionException;
import org.freedesktop.dbus.interfaces.DBusInterface;
import org.freedesktop.dbus.messages.DBusSignal;
import org.freedesktop.dbus.types.Variant;

import java.util.List;
import java.util.Map;

/**
* DBus interface for the org.asamk.Signal service.
Expand Down Expand Up @@ -63,6 +65,12 @@ long sendGroupMessageReaction(
String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, byte[] groupId
) throws Error.GroupNotFound, Error.Failure, Error.InvalidNumber, Error.InvalidGroupId;

Map<String, Variant<?>> listIdentities();

Map<String, Variant<?>> listIdentities(String number) throws Error.InvalidNumber;

void trust(String number, String safetyNumber) throws Error.Failure, Error.InvalidNumber;

String getContactName(String number) throws Error.InvalidNumber;

void setContactName(String number, String name) throws Error.InvalidNumber;
Expand Down
91 changes: 91 additions & 0 deletions src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.asamk.Signal;
import org.asamk.signal.BaseConfig;
import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.AttachmentInvalidException;
import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.NotMasterDeviceException;
Expand All @@ -16,22 +17,30 @@
import org.asamk.signal.manager.groups.LastGroupAdminException;
import org.asamk.signal.manager.groups.NotAGroupMemberException;
import org.asamk.signal.manager.storage.identities.IdentityInfo;
import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.asamk.signal.util.CommandUtil;
import org.asamk.signal.util.ErrorUtils;
import org.asamk.signal.util.Util;
import org.asamk.signal.util.Hex;

import org.freedesktop.dbus.exceptions.DBusExecutionException;
import org.freedesktop.dbus.types.Variant;
import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
import org.whispersystems.signalservice.api.messages.SendMessageResult;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.api.util.InvalidNumberException;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
Expand Down Expand Up @@ -267,6 +276,88 @@ public long sendGroupMessageReaction(
}
}

@Override
public Map<String, Variant<?>> listIdentities(String number) {
List<IdentityInfo> identities;
HashMap<String, Variant<?>> result = new HashMap<>();
try {
RecipientIdentifier.Single recipient = CommandUtil.getSingleRecipientIdentifier(number, m.getUsername());
identities = m.getIdentities(recipient);
} catch (UserErrorException e) {
throw new Error.InvalidNumber("Invalid number: " + e.getMessage());
}
if (identities.isEmpty()) {return result;}
IdentityInfo theirId = identities.get(0);

final SignalServiceAddress address = m.resolveSignalServiceAddress(theirId.getRecipientId());
String safetyNumber = Util.formatSafetyNumber(m.computeSafetyNumber(address, theirId.getIdentityKey()));
result.put(number, new Variant<String[]>(new String[]{
theirId.getTrustLevel().toString(),
theirId.getDateAdded().toString(),
Hex.toString(theirId.getFingerprint()),
safetyNumber}));
return result;
}

@Override
public Map<String, Variant<?>> listIdentities() {
List<String> numbers = listNumbers();
Map<String, Variant<?>> result = new HashMap<>();
if (numbers.isEmpty()) {return result;}
for (String number:numbers) {
Map<String, Variant<?>> identity = listIdentities(number);
if (! identity.isEmpty()) {
result.put(number, identity.get(number));
}
}
return result;
}

@Override
public void trust(String number, String safetyNumber){
if (safetyNumber != null) {
safetyNumber = safetyNumber.replaceAll(" ", "");
if (safetyNumber.length() == 66) {
byte[] fingerprintBytes;
try {
fingerprintBytes = Hex.toByteArray(safetyNumber.toLowerCase(Locale.ROOT));
} catch (Exception e) {
throw new Error.Failure(
"Failed to parse the fingerprint, make sure the fingerprint is a correctly encoded hex string without additional characters.");
}
boolean res;
try {
RecipientIdentifier.Single recipient = CommandUtil.getSingleRecipientIdentifier(number, m.getUsername());
res = m.trustIdentityVerified(recipient, fingerprintBytes);
} catch (UserErrorException e) {
throw new Error.Failure("Failed to parse recipient: " + e.getMessage());
}
if (!res) {
throw new Error.Failure(
"Failed to set the trust for the fingerprint of this number, make sure the number and the fingerprint are correct.");
}
} else if (safetyNumber.length() == 60) {
boolean res;
try {
RecipientIdentifier.Single recipient = CommandUtil.getSingleRecipientIdentifier(number, m.getUsername());
res = m.trustIdentityVerifiedSafetyNumber(recipient, safetyNumber);
} catch (UserErrorException e) {
throw new Error.InvalidNumber("Failed to parse recipient: " + e.getMessage());
}
if (!res) {
throw new Error.Failure(
"Failed to set the trust for the safety number of this phone number, make sure the phone number and the safety number are correct.");
}
} else {
throw new Error.Failure(
"Safety number has invalid format, either specify the old hex fingerprint or the new safety number");
}
} else {
throw new Error.Failure(
"You need to specify the fingerprint/safety number you have verified with -v SAFETY_NUMBER");
}
}

// Since contact names might be empty if not defined, also potentially return
// the profile name
@Override
Expand Down