sábado, 30 de agosto de 2014

Permisos del sistema

Android es un sistema operativo en el las aplicaciones se ejecutan de manera aislada y cuentan con su propia identidad (un ID de usuario y un ID de grupo Linux). Partes del sistema también cuentan con su propia identidad. De este modo, Linux aísla las aplicaciones entre sí y del propio sistema.

Adicionalmente, existen otros mecanismos basados en permisos que podremos otorgar de manera explícita a un proceso sobre ciertos datos, o también, podremos especificar que una URI (enlace a contenido) sea accesible temporalmente.

Arquitectura.

Por defecto, Android no permite que una aplicación tenga permisos para realizar operaciones que puedan comprometer el funcionamiento de otras aplicaciones o el sistema operativo. Esto incluye el poder leer o escribir datos privados del usuario (contactos, correos electrónicos), leer o escribir archivos de otras aplicaciones, realizar operaciones de red, operaciones sobre el estado de reposo del dispositivo, entre otros.

Debido a que cada aplicación se ejecuta en su propio entorno seguro y acotado, las aplicaciones tendrán que declarar de manera explícita la compartición de recursos y datos. Los permisos que una aplicación vaya a requerir, son declarados de manera estática y tendrán que ser aprovados por el usuario antes de instalar la aplicación. Android no cuenta con un mecanismo para gestionar permisos en tiempo de ejecución (dinámico) debido a que complica la experiencia de usuario y va en detrimento de la seguridad.

Todas las aplicaciones Android se ejecutan en un entorno seguro y acotado, independientemente de si se han desarrollado en Java, sean nativas o híbridas.

Firma de aplicaciones.

Todas las aplicaciones (sus archivos .apk)  deberán ser firmadas con un certificado cuya clave privada esté en manos de sus desarrolladores. Este certificado identificará al autor de la aplicación. El certificado no necesita ser firmado por una autoridad de certificación. Es perfectamente lícito, y típico, que para la firma de aplicaciones se utilicen certificados auto-firmados. El propósito de los certificados en Android es el de poder distinguir a los autores de las aplicaciones. Esto permitirá al sistema conceder o denegar permisos a nivel de firma y conceder o denegar la petición que una aplicación pueda hacer para adoptar la identidad de otra aplicación. 

IDs de usuario y acceso a los archivos.

Android proporciona un nuevo ID de usuario a una aplicación durante su proceso de instalación. Este ID de usuario durará el tiempo que dure la aplicación instalada en el dispositivo. En un dispositivo diferente, la misma aplicación, contará con un UID (User ID - ID de usuario) diferente. Lo que importa es que cada paquete tiene un UID único en cada dispositivo.

Debido a que la seguridad tiene lugar a nivel de proceso, el código de dos paquetes no podrá ejecutarse dentro del mismo proceso, ya que se ejecutan con usuarios distintos. Para romper con esta limitación, puedes usar el atributo sharedUserId en el archivo AndroidManifest.xml para que ambos paquetes se ejecuten con el mismo ID de usuario. Con ello, los paquetes serán tratados como si formaran parte de la misma aplicación, con el mismo ID de usuario y con los mismos permisos sobre archivos. Por razones de seguridad, este mecanismo solo funciona entre aplicaciones que hayan sido firmadas con el mismo certificado.

Los datos almacenados a través de una aplicación determinada, serán accesibles solo por el usuario de esa aplicación y no serán accesibles desde otra aplicación con un usuario distinto. Si creamos un nuevo archivo haciendo uso de los métodos getSharedPreferences(String, int), openfileOutput(String, int) o openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), podremos usar los valores MODE_WORLD_READABLE (acceso de lectura) y/o MODEL_WORLD_WRITEABLE (acceso de lectura y escritura) como argumentos de dichos métodos. Con ello conseguiremos que los archivos, creados para diferentes propósitos, sean accesibles por otras aplicaciones en modo de lectura o escritura.

Usando permisos.

Una aplicación en Android no tiene permisos asociados por defecto. Esto significa que una aplicación, por defecto, no podrá causar daños a datos del dispositivo.  Para que una aplicación tenga permisos concretos, tendremos que declararlo de manera explícita en el archivo AndroidManifest.xml a través de elementos <uses-permission>. Por ejemplo, una aplicación que necesita acceso a los mensajes SMS del usuario, debería declararlo de esta manera:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.app.myapp" >
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    ...
</manifest>
Estos permisos serán otorgados por el usuario durante el proceso de instalación de la aplicación. Una vez hayan sido otorgados, la aplicación no necesitará chequear en tiempo de ejecución por dichos permisos porque ya cuenta con ellos. Si por alguna razón, intentásemos acceder a cierto permiso que no hayamos solicitado al usuario durante el proceso de instalación, la aplicación fallará.

Generalmente un error de permisos suele dar como resultado en una excepción del tipo SecurityException. Pero esto no tiene por qué suceder siempre. Por ejemplo, el método sendBroadcast(Intent) chequea los permisos conforme los datos son entregados a sus receptores y retorna la llamada, sin más. En este caso no se generará una excepción si hay algún problema de permisos. En cualquier caso, siempre podremos consultar el registro del sistema.

No obstante, el proceso habitual de instalación de una aplicación a través de la tienda Google Play, nos garantiza que el usuario tendrá que otorgar los permisos necesarios para que la aplicación sea instalada y pueda ejecutarse sin problemas. Es por ello que no tendremos que gestionar las excepciones asociadas a permisos.

Algunos permisos vienen derivados de ciertas operaciones que nuestra aplicación puede realizar:
  • Cuando iniciamos una actividad.
  • Cuando enviamos o recibimos avisos.
  • Cuando accedemos a los contenidos de un proveedor de contenido.
  • Cuando enlazamos o iniciamos un servicio.

Declarando y haciendo cumplir los permisos.

Android nos permite definir nuestros propios permisos. Para ello, tendremos que declararlos en nuestro AndroidManifest.xml utilizando elementos <permission>.

Por ejemplo, una aplicación en la que queramos controlar quién puede iniciar sus actividades podría declarar el siguiente permiso:

<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>

Permisos URI.

No hay comentarios:

Publicar un comentario