Revision 0fc4c33f
| trustedintents/src/info/guardianproject/trustedintents/TrustedIntents.java | ||
|---|---|---|
| 13 | 13 |
import android.content.pm.ResolveInfo; |
| 14 | 14 |
import android.content.pm.Signature; |
| 15 | 15 |
import android.text.TextUtils; |
| 16 |
import android.util.Log; |
|
| 16 | 17 |
|
| 17 | 18 |
import java.lang.reflect.Constructor; |
| 18 | 19 |
import java.security.cert.CertificateException; |
| ... | ... | |
| 93 | 94 |
} |
| 94 | 95 |
|
| 95 | 96 |
/** |
| 96 |
* Check if an {@link Intent} is from a trusted sender.
|
|
| 97 |
* |
|
| 98 |
* @param intent the {@code Intent} to check
|
|
| 99 |
* @return boolean whether {@code intent} is from a trusted sender
|
|
| 100 |
* @see #addTrustedSigner(Class) |
|
| 101 |
*/ |
|
| 102 |
public boolean isIntentFromTrustedSender(Intent intent) {
|
|
| 103 |
if (!isIntentSane(intent)) {
|
|
| 104 |
return false; |
|
| 105 |
} |
|
| 106 |
String packageName = intent.getPackage(); |
|
| 107 |
if (TextUtils.isEmpty(packageName)) {
|
|
| 108 |
packageName = intent.getComponent().getPackageName(); |
|
| 109 |
} |
|
| 110 |
if (TextUtils.isEmpty(packageName)) {
|
|
| 111 |
return false; |
|
| 112 |
} |
|
| 113 |
return isPackageNameTrusted(packageName); |
|
| 114 |
} |
|
| 115 |
|
|
| 116 |
/** |
|
| 117 | 97 |
* Returns an {@link Intent} if the sending app is signed by one of
|
| 118 | 98 |
* the trusted signing keys as set in {@link #addTrustedSigner(Class)}.
|
| 119 | 99 |
* |
| ... | ... | |
| 123 | 103 |
*/ |
| 124 | 104 |
public Intent getIntentFromTrustedSender(Activity activity) {
|
| 125 | 105 |
Intent intent = activity.getIntent(); |
| 126 |
if (isIntentFromTrustedSender(intent)) {
|
|
| 106 |
String packageName = getCallingPackageName(activity); |
|
| 107 |
if (TextUtils.isEmpty(packageName)) {
|
|
| 108 |
return null; |
|
| 109 |
} |
|
| 110 |
if (isPackageNameTrusted(packageName)) {
|
|
| 127 | 111 |
return intent; |
| 128 | 112 |
} |
| 129 | 113 |
return null; |
| 130 | 114 |
} |
| 131 | 115 |
|
| 116 |
/** |
|
| 117 |
* Get the package name of the {@link Activity} that sent the
|
|
| 118 |
* {@link Intent} that started this {@code Activity}.
|
|
| 119 |
* <p/> |
|
| 120 |
* <strong>WARNING</strong>: If the {@code Activity} has
|
|
| 121 |
* {@code android:launchMode="singleInstance"} or {@code "singleTask"}, then
|
|
| 122 |
* this method will not disconnect because it is not possible to get the |
|
| 123 |
* calling {@code Activity}, as set by
|
|
| 124 |
* {@link Activity#startActivityForResult(Intent, int)}
|
|
| 125 |
* |
|
| 126 |
* @param activity the {@code Activity} to check for the {@code Intent}
|
|
| 127 |
* @return the package of the sending app or {@code null} if it was not a
|
|
| 128 |
* {@code ACTION_CONNECT Intent} or the {@code Intent} was not sent
|
|
| 129 |
* with {@link Activity#startActivityForResult(Intent, int)}
|
|
| 130 |
*/ |
|
| 131 |
public static String getCallingPackageName(Activity activity) {
|
|
| 132 |
// getCallingPackage() was unstable until android-18, use this |
|
| 133 |
ComponentName componentName = activity.getCallingActivity(); |
|
| 134 |
if (componentName == null) |
|
| 135 |
return null; |
|
| 136 |
String packageName = componentName.getPackageName(); |
|
| 137 |
if (TextUtils.isEmpty(packageName)) {
|
|
| 138 |
Log.e(activity.getClass().getSimpleName(), |
|
| 139 |
"Received Intent without sender! The Intent must be sent using startActivityForResult() and received without launchMode singleTask or singleInstance!"); |
|
| 140 |
} |
|
| 141 |
return packageName; |
|
| 142 |
} |
|
| 143 |
|
|
| 144 |
/** |
|
| 145 |
* This is used to check whether an {@link Intent} that will be sent is
|
|
| 146 |
* complete. It should <strong>not</strong> be used with {@code Intent}s
|
|
| 147 |
* that have been received already. |
|
| 148 |
*/ |
|
| 132 | 149 |
private boolean isIntentSane(Intent intent) {
|
| 133 | 150 |
if (intent == null) |
| 134 | 151 |
return false; |
Also available in: Unified diff