Is is possible to make content provider read-only? I know that this question was asked few times but according to all of them (eg. this) I have to write my own custom write permission.
<permission android:name="com.test.WRITE_DATABASE" android:protectionLevel="normal" />
<permission android:name="com.test.READ_DATABASE" android:protectionLevel="normal" />
//...
<provider
android:authorities="xxx"
android:name="xxx"
android:exported="true"
android:readPermission="com.test.READ_DATABASE"
android:writePermission="com.test.WRITE_DATABASE" />
But hacker could decompile my app and look inside manifest file and then he can easily write his own app with:
<uses-permission android:name="com.test.WRITE_DATABASE" />
So it's almost useless...
I have several apps to use one Content Provider inside my main application. Only this application should have write permission - other should only read from this database. Any ideas how to solve this?
See documentation about permissions here: https://developer.android.com/guide/topics/manifest/permission-element.html
Answer to your question is a android:protectionLevel property of a permission. You can set it to signature so only applications that signed with same key will be able to request this permissions.
Related
My application accepts certain files to be opened with the application but I've seen a couple crashes recently that say
java.lang.RuntimeException: Unable to start activity java.lang.SecurityException: Permission Denial: opening provider com.yahoo.mobile.client.android.mail.provider.MailProvider from ProcessRecord{42cb5ff0 7953:com.my.package/u0a10163} (pid=7953, uid=10163) that is not exported from uid 10147
In my AndroidManifest.XML I have the following permissions
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="com.android.setting.permission.ALLSHARE_CAST_SERVICE" />
<uses-permission android:name="com.android.vending.BILLING" />
Is there any permission that I might be missing for specifically Yahoo?
I'm getting the feeling that it's specifically blocked. If so is there any way I can block attachments in Yahoo from being opened with my app? Thanks
Is there any permission that I might be missing for specifically Yahoo?
Not based on that error. That error indicates that Yahoo created a ContentProvider (com.yahoo.mobile.client.android.mail.provider.MailProvider) and screwed up their security. They should be using FLAG_GRANT_READ_URI_PERMISSION with their ACTION_VIEW Intent, to allow its otherwise-not-exported provider to provide you with the file contents.
If so is there any way I can block attachments in Yahoo from being opened with my app?
Catch the exception and point out to the user that the app that started you up is broken.
There is nothing you can put in the manifest to say "...but not Yahoo Mail".
i agree with CommonsWare that yahoo's app data provider is not configured right, they should do one of the following:
Declaring android:exported=true (without declaring any specific
permissions) which will give a free access to the content provider to
the external apps.
Declaring temporary permission specifying
android:grantUriPermissions=true on the provider tag in the manifest
and setting FLAG_GRANT_READ_URI_PERMISSION flag on the action intent.
But in my case i found another soulution:
Context.grantUriPermission((String toPackage, Uri uri, int modeFlags)
Normally this method should be called from the provider app granting access to another package, but in our case calling this method from our app:
grantUriPermission(BuildConfig.APPLICATION_ID, fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
gained access to the specified file, and we were able to open yahoo attachments.
If I create a ContentProvider and want it to be available to certain 3rd party apps but not too others.
How would one go about that?
Use permissions. Read about them here:
https://developer.android.com/guide/topics/providers/content-provider-creating.html#Permissions
Then you just need to publish those permissions to only those parties you wish to allow access.
You can add permission to provider. like
<provider
android:name="com.example.app.provider.MyProvider"
android:authorities="com.example.myprovider"
android:label="#string/app_name"
android:readPermission="com.example.permission.READ_PROVIDER" />
and write your own permission into manifest
<permission
android:name="com.example.permission.READ_PROVIDER"
android:description="provider_desc"
android:label="#string/permission_access_label"
android:protectionLevel="signature" />
Write this permission to manifest of the application which want to access provider.
Where signature insures that applications (which access provider and original are signed with same certificate)
Read more about Writing your own Content Provider
is there any way to make an external content provider available to only one package?
for example available only to my app?
Thanks in advance.
Although its too late, I would like to share the answer which I have found,
You need to declare your own custom permission inside manifest file of content provider application like this..
<permission android:name= "com.android.testpermission" android:protectionLevel="signature" >
And inside your Content Provider tag you have to specify a permission that a client is required to have like this way...
<provider android:name=".MyProvider"
android:authorities="com.example.contentproviderexample.MyProvider" android:exported="true" android:permission="com.android.testpermission" android:multiprocess="true" ></provider>
And inside your 2nd application to access content provider data you need to specify the uses permission inside manifest file,like this..
<uses-permission android:name="com.android.testpermission"/>
Now sign both the application using same keystore signature & this way any other application can't access your content provider data. Only applications that hold those permissions & signed with same keystore signature will be able to access the provider data.
You can add permissions to the manifest declaration for the content provider. Only applications that hold those permissions will be able to access the provider.
I noticed that there are two types of permissions in the manifest file, "permission" and "uses-permission" like the two shown below;
<permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
for the following 4 permissions which do I use when I put them in my manifest.xml file? uses-permissions or permissions?
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.INTERNET
android.permission.CHANGE_WIFI_MULTICAST_STATE
For
<permission>
The documentation states:
Declares a security permission that can be used to limit access to specific components or features of this or other applications.
Therefore, since you are accessing Android's permissions, you want uses-permission instead. The documentation for this element states:
Requests a permission that the application must be granted in order
for it to operate correctly.
<permission> is normally used when making a custom permission (e.g. when making an app that other apps can tie in to, limiting access is a must), and <uses-permission> is used when your app actually needs a permission it doesn't have normally.
Lets start with "uses-permission...": Suppose you want to use GoogleMap in your application as an example to find a nearest location of any office such as bank or any other office. You need internet. So you need to give the permission to your android device to access INTERNET. This is done by using android permission called .
<uses-permission android:name="android.permission.INTERNET" />
Now come to "permission..": what it does is it Declares a security permission that can be used to limit access to specific components or features of this or other applications.If your application need some resources or some feature from other application, you can use by giving the specific class or package.
<permission android:name="com.example.project.DEBIT_ACCT" . . . />
Thanks. for more information, you can read
http://developer.android.com/guide/topics/manifest/manifest-intro.html
In short, the one you needed is the uses-permission statement.
Androird Document now has a dedicated page discussing these two usages.
In the Using Permissions part, it explains that
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.app.myapp" >
<uses-permission android:name="android.permission.RECEIVE_SMS" />
...
</manifest>
is used to declare what permissions you'd like to use.
While in Defining and Enforcing Permissions you can see that
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.me.app.myapp" >
<permission android:name="com.me.app.myapp.permission.DEADLY_ACTIVITY"
android:label="#string/permlab_deadlyActivity"
android:description="#string/permdesc_deadlyActivity"
android:permissionGroup="android.permission-group.COST_MONEY"
android:protectionLevel="dangerous" />
...
</manifest>
is used to define your own permission.
In layman terms, <uses-permission> specifies permissions your app needs to access some component restrict by another app that is the owner of that component.
<permission> specifies the restrictions you are placing on your components are the component owner.
permissions don't seem to make any difference...
In the manifest, I have only one <uses-permission> (permission.INTERNET), and I have two <permission> elements:
<permission android:name="myapp.permission.READ"
android:permissionGroup="myapp.permission-group.MYAPP_DATA"
android:label="#string/perm_read"
android:description="#string/perm_read_summary"
android:protectionLevel="signature" />
<permission android:name="myapp.permission.WRITE"
android:permissionGroup="myapp.permission-group.MYAPP_DATA"
android:label="#string/perm_write"
android:description="#string/perm_write_summary"
android:protectionLevel="signature" />
And then there is the provider:
<provider
android:name=".data.DataProvider"
android:multiprocess="true"
android:authorities="myapp.data.DataProvider"
android:readPermission="myapp.permission.READ"
android:writePermission="myapp.permission.WRITE" />
Right now, I have normal access to the ContentProvider, and it works just fine.
Why does it work if I didn't enforce with <uses-permission>?
Shouldn't it be needed also in the app where the provider is
declared?
Adding <uses-permission> with my own permissions make no difference. The permissions are not even listed in the app info. Why?
ps.: yes, I've read questions here on SO and on Google Groups (ones with Hackborn answering, too). I've followed (as you can see) what is described everywhere, but still... You could say that it's working, but the point is exactly that I want to see when it doesn't.
Shouldn't it be needed also in the app where the provider is declared?
AFAIK, your own app holds all your own permissions that you declare. Third parties would need <uses-permission>.
The permissions are not even listed in the app info. Why?
See above.
You could say that it's working, but the point is exactly that I want to see when it doesn't.
Write another app, in its own package, to test your permissions.