kopia lustrzana https://github.com/ryukoposting/Signal-Android
Log out sender key state for internal users.
rodzic
b8cf0cc1be
commit
3574be913a
|
@ -10,11 +10,13 @@ import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
import org.thoughtcrime.securesms.util.CursorUtil;
|
import org.thoughtcrime.securesms.util.CursorUtil;
|
||||||
import org.thoughtcrime.securesms.util.SqlUtil;
|
import org.thoughtcrime.securesms.util.SqlUtil;
|
||||||
import org.whispersystems.libsignal.groups.state.SenderKeyRecord;
|
import org.whispersystems.libsignal.groups.state.SenderKeyRecord;
|
||||||
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -110,6 +112,17 @@ public class SenderKeyDatabase extends Database {
|
||||||
db.delete(TABLE_NAME, query, args);
|
db.delete(TABLE_NAME, query, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get metadata for all sender keys created by the local user. Used for debugging.
|
||||||
|
*/
|
||||||
|
public Cursor getAllCreatedBySelf() {
|
||||||
|
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||||
|
String query = ADDRESS + " = ?";
|
||||||
|
String[] args = SqlUtil.buildArgs(Recipient.self().requireAci());
|
||||||
|
|
||||||
|
return db.query(TABLE_NAME, new String[]{ ID, DISTRIBUTION_ID, CREATED_AT }, query, args, null, null, CREATED_AT + " DESC");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all database state.
|
* Deletes all database state.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -157,4 +157,12 @@ public class SenderKeySharedDatabase extends Database {
|
||||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||||
db.delete(TABLE_NAME, null, null);
|
db.delete(TABLE_NAME, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the shared state of all of our sender keys. Used for debugging.
|
||||||
|
*/
|
||||||
|
public Cursor getAllSharedWithCursor() {
|
||||||
|
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
|
||||||
|
return db.query(TABLE_NAME, null, null, null, null, null, DISTRIBUTION_ID + ", " + ADDRESS + ", " + DEVICE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
|
||||||
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
|
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
|
||||||
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient));
|
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient));
|
||||||
|
|
||||||
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(address, access, message, groupId.getDecodedId()).get(0);
|
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, groupId.getDecodedId()).get(0);
|
||||||
|
|
||||||
if (result.isSuccess()) {
|
if (result.isSuccess()) {
|
||||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package org.thoughtcrime.securesms.logsubmit;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.signal.core.util.AsciiArt;
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
|
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders data pertaining to sender key. While all private info is obfuscated, this is still only intended to be printed for internal users.
|
||||||
|
*/
|
||||||
|
public class LogSectionSenderKey implements LogSection {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull String getTitle() {
|
||||||
|
return "SENDER KEY";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull CharSequence getContent(@NonNull Context context) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
builder.append("--- Sender Keys").append("\n\n");
|
||||||
|
try (Cursor cursor = DatabaseFactory.getSenderKeyDatabase(context).getAllCreatedBySelf()) {
|
||||||
|
builder.append(AsciiArt.tableFor(cursor)).append("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("--- Sender Key Shared State").append("\n\n");
|
||||||
|
try (Cursor cursor = DatabaseFactory.getSenderKeySharedDatabase(context).getAllSharedWithCursor()) {
|
||||||
|
builder.append(AsciiArt.tableFor(cursor)).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor;
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||||
import org.thoughtcrime.securesms.util.ByteUnit;
|
import org.thoughtcrime.securesms.util.ByteUnit;
|
||||||
|
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||||
import org.thoughtcrime.securesms.util.Stopwatch;
|
import org.thoughtcrime.securesms.util.Stopwatch;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
@ -86,6 +87,9 @@ public class SubmitDebugLogRepository {
|
||||||
add(new LogSectionTrace());
|
add(new LogSectionTrace());
|
||||||
add(new LogSectionThreads());
|
add(new LogSectionThreads());
|
||||||
add(new LogSectionBlockedThreads());
|
add(new LogSectionBlockedThreads());
|
||||||
|
if (FeatureFlags.internalUser()) {
|
||||||
|
add(new LogSectionSenderKey());
|
||||||
|
}
|
||||||
add(new LogSectionLogcat());
|
add(new LogSectionLogcat());
|
||||||
add(new LogSectionLoggerHeader());
|
add(new LogSectionLoggerHeader());
|
||||||
}};
|
}};
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package org.signal.core.util
|
||||||
|
|
||||||
|
import android.database.Cursor
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
class AsciiArt {
|
||||||
|
|
||||||
|
private class Table (
|
||||||
|
private val columns: List<String>,
|
||||||
|
private val rows: List<List<String>>
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
val columnWidths = columns.map { column -> column.length }.toIntArray()
|
||||||
|
|
||||||
|
rows.forEach { row: List<String> ->
|
||||||
|
columnWidths.forEachIndexed { index, currentMax ->
|
||||||
|
columnWidths[index] = max(row[index].length, currentMax)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val builder = StringBuilder()
|
||||||
|
|
||||||
|
columns.forEachIndexed { index, column ->
|
||||||
|
builder.append(COLUMN_DIVIDER).append(" ").append(rightPad(column, columnWidths[index])).append(" ")
|
||||||
|
}
|
||||||
|
builder.append(COLUMN_DIVIDER)
|
||||||
|
|
||||||
|
builder.append("\n")
|
||||||
|
|
||||||
|
columnWidths.forEach { width ->
|
||||||
|
builder.append(COLUMN_DIVIDER)
|
||||||
|
builder.append(ROW_DIVIDER.repeat(width + 2))
|
||||||
|
}
|
||||||
|
builder.append(COLUMN_DIVIDER)
|
||||||
|
|
||||||
|
builder.append("\n")
|
||||||
|
|
||||||
|
rows.forEach { row ->
|
||||||
|
row.forEachIndexed { index, column ->
|
||||||
|
builder.append(COLUMN_DIVIDER).append(" ").append(rightPad(column, columnWidths[index])).append(" ")
|
||||||
|
}
|
||||||
|
builder.append(COLUMN_DIVIDER)
|
||||||
|
builder.append("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val COLUMN_DIVIDER = "|"
|
||||||
|
private const val ROW_DIVIDER = "-"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will return a string representing a table of the provided cursor. The caller is responsible for the lifecycle of the cursor.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun tableFor(cursor: Cursor): String {
|
||||||
|
val columns: MutableList<String> = mutableListOf()
|
||||||
|
val rows: MutableList<List<String>> = mutableListOf()
|
||||||
|
|
||||||
|
columns.addAll(cursor.columnNames)
|
||||||
|
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
val row: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
|
for (i in 0 until columns.size) {
|
||||||
|
row += cursor.getString(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows += row
|
||||||
|
}
|
||||||
|
|
||||||
|
return Table(columns, rows).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rightPad(value: String, length: Int): String {
|
||||||
|
if (value.length >= length) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
val out = java.lang.StringBuilder(value)
|
||||||
|
while (out.length < length) {
|
||||||
|
out.append(" ")
|
||||||
|
}
|
||||||
|
return out.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -360,7 +360,8 @@ public class SignalServiceMessageSender {
|
||||||
/**
|
/**
|
||||||
* Sends the provided {@link SenderKeyDistributionMessage} to the specified recipients.
|
* Sends the provided {@link SenderKeyDistributionMessage} to the specified recipients.
|
||||||
*/
|
*/
|
||||||
public List<SendMessageResult> sendSenderKeyDistributionMessage(List<SignalServiceAddress> recipients,
|
public List<SendMessageResult> sendSenderKeyDistributionMessage(DistributionId distributionId,
|
||||||
|
List<SignalServiceAddress> recipients,
|
||||||
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
|
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
|
||||||
SenderKeyDistributionMessage message,
|
SenderKeyDistributionMessage message,
|
||||||
byte[] groupId)
|
byte[] groupId)
|
||||||
|
@ -371,7 +372,7 @@ public class SignalServiceMessageSender {
|
||||||
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.of(groupId));
|
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.of(groupId));
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
Log.d(TAG, "[" + timestamp + "] Sending SKDM to " + recipients.size() + " recipients.");
|
Log.d(TAG, "[" + timestamp + "] Sending SKDM to " + recipients.size() + " recipients for DistributionId " + distributionId);
|
||||||
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null);
|
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +412,7 @@ public class SignalServiceMessageSender {
|
||||||
SenderKeyGroupEvents sendEvents)
|
SenderKeyGroupEvents sendEvents)
|
||||||
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
|
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
|
||||||
{
|
{
|
||||||
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients.");
|
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients using DistributionId " + distributionId);
|
||||||
|
|
||||||
Content content = createMessageContent(message);
|
Content content = createMessageContent(message);
|
||||||
Optional<byte[]> groupId = message.getGroupId();
|
Optional<byte[]> groupId = message.getGroupId();
|
||||||
|
@ -1600,6 +1601,8 @@ public class SignalServiceMessageSender {
|
||||||
|
|
||||||
if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) {
|
if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) {
|
||||||
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices());
|
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices());
|
||||||
|
} else if (content.getContent().isPresent() && content.getContent().get().hasSenderKeyDistributionMessage()) {
|
||||||
|
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a SKDM to " + messages.getDestination() + " for devices: " + messages.getDevices());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancelationSignal != null && cancelationSignal.isCanceled()) {
|
if (cancelationSignal != null && cancelationSignal.isCanceled()) {
|
||||||
|
@ -1709,7 +1712,7 @@ public class SignalServiceMessageSender {
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
List<SendMessageResult> results = sendSenderKeyDistributionMessage(needsSenderKey, access, message, groupId);
|
List<SendMessageResult> results = sendSenderKeyDistributionMessage(distributionId, needsSenderKey, access, message, groupId);
|
||||||
|
|
||||||
List<SignalServiceAddress> successes = results.stream()
|
List<SignalServiceAddress> successes = results.stream()
|
||||||
.filter(SendMessageResult::isSuccess)
|
.filter(SendMessageResult::isSuccess)
|
||||||
|
|
Ładowanie…
Reference in New Issue