check file owner when attaching files or using them as avatar
This commit is contained in:
parent
290f0a123e
commit
0460702710
|
@ -1,5 +1,7 @@
|
||||||
package eu.siacs.conversations.persistance;
|
package eu.siacs.conversations.persistance;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
@ -9,8 +11,13 @@ import android.graphics.Canvas;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.provider.OpenableColumns;
|
import android.provider.OpenableColumns;
|
||||||
|
import android.system.ErrnoException;
|
||||||
|
import android.system.Os;
|
||||||
|
import android.system.StructStat;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Base64OutputStream;
|
import android.util.Base64OutputStream;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -19,6 +26,7 @@ import android.webkit.MimeTypeMap;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,6 +403,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
|
||||||
public void attachFileToConversation(final Conversation conversation,
|
public void attachFileToConversation(final Conversation conversation,
|
||||||
final Uri uri,
|
final Uri uri,
|
||||||
final UiCallback<Message> callback) {
|
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;
|
final Message message;
|
||||||
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
|
if (conversation.getNextEncryption() == Message.ENCRYPTION_PGP) {
|
||||||
message = new Message(conversation, "", Message.ENCRYPTION_DECRYPTED);
|
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) {
|
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();
|
final String compressPictures = getCompressPicturesPreference();
|
||||||
if ("never".equals(compressPictures)
|
if ("never".equals(compressPictures)
|
||||||
|| ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))) {
|
|| ("auto".equals(compressPictures) && getFileBackend().useImageAsIs(uri))) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.io.File;
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
import eu.siacs.conversations.utils.FileUtils;
|
import eu.siacs.conversations.utils.FileUtils;
|
||||||
import eu.siacs.conversations.utils.PhoneHelper;
|
import eu.siacs.conversations.utils.PhoneHelper;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
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) {
|
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
|
Uri source = data.getData();
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_CHOOSE_FILE_AND_CROP:
|
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);
|
String original = FileUtils.getPath(this, source);
|
||||||
if (original != null) {
|
if (original != null) {
|
||||||
source = Uri.parse("file://"+original);
|
source = Uri.parse("file://"+original);
|
||||||
|
@ -199,7 +204,11 @@ public class PublishProfilePictureActivity extends XmppActivity {
|
||||||
Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this);
|
Crop.of(source, destination).asSquare().withMaxSize(size, size).start(this);
|
||||||
break;
|
break;
|
||||||
case REQUEST_CHOOSE_FILE:
|
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) {
|
if (xmppConnectionServiceBound) {
|
||||||
loadImageIntoPreview(this.avatarUri);
|
loadImageIntoPreview(this.avatarUri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -609,4 +609,5 @@
|
||||||
<string name="no_keys_just_confirm">You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference.</string>
|
<string name="no_keys_just_confirm">You already trust this contact. By selecting \'done\' you are just confirming that %s is part of this conference.</string>
|
||||||
<string name="select_image_and_crop">Select image and crop</string>
|
<string name="select_image_and_crop">Select image and crop</string>
|
||||||
<string name="this_account_is_disabled">You have disabled this account</string>
|
<string name="this_account_is_disabled">You have disabled this account</string>
|
||||||
|
<string name="security_error_invalid_file_access">Security error: Invalid file access</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue