Export the key share trail in rageshake (opt-in)

This commit is contained in:
Benoit Marty 2020-10-29 16:04:07 +01:00
parent 41e3ff381f
commit 077bcb3f2a
6 changed files with 127 additions and 59 deletions

View File

@ -69,6 +69,9 @@ class BugReportActivity : VectorBaseActivity() {
bug_report_button_include_crash_logs.isChecked = false
bug_report_button_include_crash_logs.isVisible = false
bug_report_button_include_key_share_history.isChecked = false
bug_report_button_include_key_share_history.isVisible = false
// Keep the screenshot
} else {
supportActionBar?.setTitle(R.string.title_activity_bug_report)
@ -121,6 +124,7 @@ class BugReportActivity : VectorBaseActivity() {
forSuggestion,
bug_report_button_include_logs.isChecked,
bug_report_button_include_crash_logs.isChecked,
bug_report_button_include_key_share_history.isChecked,
bug_report_button_include_screenshot.isChecked,
bug_report_edit_text.text.toString(),
object : BugReporter.IMXBugReportListener {

View File

@ -33,6 +33,7 @@ import im.vector.app.core.extensions.getAllChildFragments
import im.vector.app.core.extensions.toOnOff
import im.vector.app.features.settings.VectorLocale
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.devtools.GossipingEventsSerializer
import im.vector.app.features.settings.locale.SystemLocaleProvider
import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.version.VersionProvider
@ -74,6 +75,7 @@ class BugReporter @Inject constructor(
private const val LOG_CAT_FILENAME = "logcat.log"
private const val LOG_CAT_SCREENSHOT_FILENAME = "screenshot.png"
private const val CRASH_FILENAME = "crash.log"
private const val KEY_REQUESTS_FILENAME = "keyRequests.log"
private const val BUFFER_SIZE = 1024 * 1024 * 50
}
@ -143,6 +145,7 @@ class BugReporter @Inject constructor(
* @param forSuggestion true to send a suggestion
* @param withDevicesLogs true to include the device log
* @param withCrashLogs true to include the crash logs
* @param withKeyRequestHistory true to include the crash logs
* @param withScreenshot true to include the screenshot
* @param theBugDescription the bug description
* @param listener the listener
@ -152,6 +155,7 @@ class BugReporter @Inject constructor(
forSuggestion: Boolean,
withDevicesLogs: Boolean,
withCrashLogs: Boolean,
withKeyRequestHistory: Boolean,
withScreenshot: Boolean,
theBugDescription: String,
listener: IMXBugReportListener?) {
@ -207,6 +211,22 @@ class BugReporter @Inject constructor(
}
}
activeSessionHolder.getSafeActiveSession()
?.takeIf { !mIsCancelled && withKeyRequestHistory }
?.cryptoService()
?.getGossipingEvents()
?.let { GossipingEventsSerializer().serialize(it) }
?.toByteArray()
?.let { rawByteArray ->
File(context.cacheDir.absolutePath, KEY_REQUESTS_FILENAME)
.also {
it.outputStream()
.use { os -> os.write(rawByteArray) }
}
}
?.let { compressFile(it) }
?.let { gzippedFiles.add(it) }
var deviceId = "undefined"
var userId = "undefined"
var olmVersion = "undefined"

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.settings.devtools
import im.vector.app.core.resources.DateProvider
import me.gujun.android.span.span
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.internal.crypto.model.event.OlmEventContent
import org.matrix.android.sdk.internal.crypto.model.event.SecretSendEventContent
import org.matrix.android.sdk.internal.crypto.model.rest.ForwardedRoomKeyContent
import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject
import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyShareRequest
import org.matrix.android.sdk.internal.crypto.model.rest.SecretShareRequest
import org.threeten.bp.format.DateTimeFormatter
class GossipingEventsSerializer {
private val full24DateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
fun serialize(eventList: List<Event>): String {
return buildString {
eventList.forEach {
val clearType = it.getClearType()
append("[${getFormattedDate(it.ageLocalTs)}] $clearType from:${it.senderId} - ")
when (clearType) {
EventType.ROOM_KEY_REQUEST -> {
val content = it.getClearContent().toModel<RoomKeyShareRequest>()
append("reqId:${content?.requestId} action:${content?.action} ")
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
append("sessionId: ${content.body?.sessionId} ")
}
append("requestedBy: ${content?.requestingDeviceId}")
}
EventType.FORWARDED_ROOM_KEY -> {
val encryptedContent = it.content.toModel<OlmEventContent>()
val content = it.getClearContent().toModel<ForwardedRoomKeyContent>()
append("sessionId:${content?.sessionId} From Device (sender key):${encryptedContent?.senderKey}")
span("\nFrom Device (sender key):") {
textStyle = "bold"
}
}
EventType.ROOM_KEY -> {
val content = it.getClearContent()
append("sessionId:${content?.get("session_id")} roomId:${content?.get("room_id")} dest:${content?.get("_dest") ?: "me"}")
}
EventType.SEND_SECRET -> {
val content = it.getClearContent().toModel<SecretSendEventContent>()
append("requestId:${content?.requestId} From Device:${it.mxDecryptionResult?.payload?.get("sender_device")}")
}
EventType.REQUEST_SECRET -> {
val content = it.getClearContent().toModel<SecretShareRequest>()
append("reqId:${content?.requestId} action:${content?.action} ")
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
append("secretName:${content.secretName} ")
}
append("requestedBy:${content?.requestingDeviceId}")
}
EventType.ENCRYPTED -> {
append("Failed to Decrypt")
}
else -> {
append("??")
}
}
append("\n")
}
}
}
private fun getFormattedDate(ageLocalTs: Long?): String {
return ageLocalTs
?.let { DateProvider.toLocalDateTime(it) }
?.let { full24DateFormatter.format(it) }
?: "?"
}
}

View File

@ -70,10 +70,6 @@ class KeyRequestViewModel @AssistedInject constructor(
fun create(initialState: KeyRequestViewState): KeyRequestViewModel
}
private val full24DateFormatter by lazy {
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
}
companion object : MvRxViewModelFactory<KeyRequestViewModel, KeyRequestViewState> {
@JvmStatic
@ -98,54 +94,7 @@ class KeyRequestViewModel @AssistedInject constructor(
// this can take long
val eventList = session.cryptoService().getGossipingEvents()
// clean it a bit to
val raw = buildString {
eventList.forEach {
val clearType = it.getClearType()
append("[${getFormattedDate(it.ageLocalTs)}] $clearType from:${it.senderId} - ")
when (clearType) {
EventType.ROOM_KEY_REQUEST -> {
val content = it.getClearContent().toModel<RoomKeyShareRequest>()
append("reqId:${content?.requestId} action:${content?.action} ")
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
append("sessionId: ${content.body?.sessionId} ")
}
append("requestedBy: ${content?.requestingDeviceId}")
}
EventType.FORWARDED_ROOM_KEY -> {
val encryptedContent = it.content.toModel<OlmEventContent>()
val content = it.getClearContent().toModel<ForwardedRoomKeyContent>()
append("sessionId:${content?.sessionId} From Device (sender key):${encryptedContent?.senderKey}")
span("\nFrom Device (sender key):") {
textStyle = "bold"
}
}
EventType.ROOM_KEY -> {
val content = it.getClearContent()
append("sessionId:${content?.get("session_id")} roomId:${content?.get("room_id")} dest:${content?.get("_dest") ?: "me"}")
}
EventType.SEND_SECRET -> {
val content = it.getClearContent().toModel<SecretSendEventContent>()
append("requestId:${content?.requestId} From Device:${it.mxDecryptionResult?.payload?.get("sender_device")}")
}
EventType.REQUEST_SECRET -> {
val content = it.getClearContent().toModel<SecretShareRequest>()
append("reqId:${content?.requestId} action:${content?.action} ")
if (content?.action == GossipingToDeviceObject.ACTION_SHARE_REQUEST) {
append("secretName:${content.secretName} ")
}
append("requestedBy:${content?.requestingDeviceId}")
}
EventType.ENCRYPTED -> {
append("Failed to Decrypt")
}
else -> {
append("??")
}
}
append("\n")
}
}
val raw = GossipingEventsSerializer().serialize(eventList)
setState {
copy(exporting = Success(Unit))
}
@ -157,11 +106,4 @@ class KeyRequestViewModel @AssistedInject constructor(
}
}
}
private fun getFormattedDate(ageLocalTs: Long?): String {
return ageLocalTs
?.let { DateProvider.toLocalDateTime(it) }
?.let { full24DateFormatter.format(it) }
?: "?"
}
}

View File

@ -125,6 +125,15 @@
android:checked="true"
android:text="@string/send_bug_report_include_crash_logs" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/bug_report_button_include_key_share_history"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:checked="false"
android:text="@string/send_bug_report_include_key_share_history" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/bug_report_button_include_screenshot"
android:layout_width="match_parent"

View File

@ -192,6 +192,7 @@
<string name="send_bug_report_include_logs">Send logs</string>
<string name="send_bug_report_include_crash_logs">Send crash logs</string>
<string name="send_bug_report_include_key_share_history">Send key share requests history</string>
<string name="send_bug_report_include_screenshot">Send screenshot</string>
<string name="send_bug_report">Report bug</string>
<string name="send_bug_report_description">Please describe the bug. What did you do? What did you expect to happen? What actually happened?</string>