aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel@gultsch.de>2016-04-07 20:29:40 +0200
committerDaniel Gultsch <daniel@gultsch.de>2016-04-07 20:29:40 +0200
commit0460702710fd46cac0850224f34a275ceb8e2c1f (patch)
tree561776fae8ca69b81adb3c630fdd52178e2d5018 /src/main/java
parent290f0a123e117ce8e31ef3f9a2d1e896fb4c1ab9 (diff)
check file owner when attaching files or using them as avatar
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/eu/siacs/conversations/persistance/FileBackend.java33
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java10
-rw-r--r--src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java13
3 files changed, 54 insertions, 2 deletions
diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
index 21ba4509..69b81569 100644
--- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java
@@ -1,5 +1,7 @@
package eu.siacs.conversations.persistance;
+import android.annotation.TargetApi;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -9,8 +11,13 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.net.Uri;
+import android.os.Build;
import android.os.Environment;
+import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
import android.util.Base64;
import android.util.Base64OutputStream;
import android.util.Log;
@@ -19,6 +26,7 @@ import android.webkit.MimeTypeMap;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -646,4 +654,29 @@ public class FileBackend {
}
}
}
+
+
+ public static boolean weOwnFile(Uri uri) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ return false;
+ } else {
+ return uri != null
+ && ContentResolver.SCHEME_FILE.equals(uri.getScheme())
+ && weOwnFileLollipop(uri);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private static boolean weOwnFileLollipop(Uri uri) {
+ try {
+ File file = new File(uri.getPath());
+ FileDescriptor fd = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY).getFileDescriptor();
+ StructStat st = Os.fstat(fd);
+ return st.st_uid == android.os.Process.myUid();
+ } catch (ErrnoException e) {
+ return true;
+ } catch (FileNotFoundException e) {
+ return false;
+ }
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index e9ac3832..2aaf9b62 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -403,6 +403,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public void attachFileToConversation(final Conversation conversation,
final Uri uri,
final UiCallback<Message> callback) {
+ if (FileBackend.weOwnFile(uri)) {
+ Log.d(Config.LOGTAG,"trying to attach file that belonged to us");
+ callback.error(R.string.security_error_invalid_file_access, null);
+ return;
+ }
final Message message;
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED);
@@ -441,6 +446,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public void attachImageToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) {
+ if (FileBackend.weOwnFile(uri)) {
+ Log.d(Config.LOGTAG,"trying to attach file that belonged to us");
+ callback.error(R.string.security_error_invalid_file_access, null);
+ return;
+ }
final String compressPictures = getCompressPicturesPreference();
if ("never".equals(compressPictures)
|| ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))) {
diff --git a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
index 88645c4a..27a3efe5 100644
--- a/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/PublishProfilePictureActivity.java
@@ -23,6 +23,7 @@ import java.io.File;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.utils.FileUtils;
import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.xmpp.pep.Avatar;
@@ -187,9 +188,13 @@ public class PublishProfilePictureActivity extends XmppActivity {
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
+ Uri source = data.getData();
switch (requestCode) {
case REQUEST_CHOOSE_FILE_AND_CROP:
- Uri source = data.getData();
+ if (FileBackend.weOwnFile(source)) {
+ Toast.makeText(this,R.string.security_error_invalid_file_access,Toast.LENGTH_SHORT).show();
+ return;
+ }
String original = FileUtils.getPath(this, source);
if (original != null) {
source = Uri.parse("file://"+original);
@@ -199,7 +204,11 @@ public class PublishProfilePictureActivity extends XmppActivity {
Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this);
break;
case REQUEST_CHOOSE_FILE:
- this.avatarUri = data.getData();
+ if (FileBackend.weOwnFile(source)) {
+ Toast.makeText(this,R.string.security_error_invalid_file_access,Toast.LENGTH_SHORT).show();
+ return;
+ }
+ this.avatarUri = source;
if (xmppConnectionServiceBound) {
loadImageIntoPreview(this.avatarUri);
}