Seguridad en la Plataforma Java 2 JDK 1.2

Esta lecci�n desmuestra c�mo escribir una clase que defina nuestro propio permiso especial. Los componentes b�sicos de esta lecci�n incluyen.

  1. Un programa de ejemplo llamado TerrysGame.
  2. Una clase llamada HighScore, que es usada por TerrysGame para almacenar los �ltimos valores m�s altos del usuario.
  3. Una clase llamada HighScorePermission, que es usada para proteger el acceso del usuario a los valores m�ximos almacenados.
  4. Un fichero de pol�cia de usuario, que concede permiso a TerrysGame para actualizar las puntuaciones.

El escenario b�sico es el siguiente.

  1. Un usuario juega a TerrysGame.
  2. Si el usuario alcanza la puntuaci�n m�s alta, TerrysGame usa la clase HighScore para grabar el nuevo valor.
  3. La clase HighScore busca en el fichero de pol�tica del usuario para ver si TerrysGame tiene permiso para actualizar las puntuaciones del usuario.
  4. Si TerrysGame tiene el permiso, la clase HighScore actualiza el resultado.

Describiremos los puntos claves de cada uno de los componentes b�sicos y luego veremos un ejemplo de ejecuci�n.

.�TerrysGame

Abajo est� el c�digo fuente de TerrysGame. Por simplicidad, TerrysGame ahora no contiene c�digo para jugar. Simplemente recupera y actualiza las puntuaciones m�ximas del usuario.

Para ver la m�xima puntuaci�n del usuairo, podremos ejecutar.

java TerrysGame get

Para ver el nuevo valor de la maxima puntuaci�n del usuario, podemos ejecutar.

java TerrysGame set score 

Para recuperar la m�xima puntuaci�n actual del usuario, TerrysGame simplemente ejemplariza un objeto HighScore y hace que llame a su m�todo getHighScore. Para ver una nueva puntuaci�n m�xima del usuario, TerrysGame ejemplariza un objeto HighScore y llama a setHighScore, pas�ndole la nueva puntuaci�n m�xima del usuario.

Aqu� est� el c�digo fuente de TerrysGame, TerrysGame.java.

package com.gamedev.games;

import java.io.*;
import java.security.*;
import java.util.Hashtable;
import com.scoredev.scores.*;

public class TerrysGame
{
    public static void main(String args[])
	throws Exception 
    {
	HighScore hs = new HighScore("TerrysGame");

	if (args.length == 0)
	    usage();

	if (args[0].equals("set")) {
	    hs.setHighScore(Integer.parseInt(args[1]));
	} else if (args[0].equals("get")) {
	    System.out.println("score = "+ hs.getHighScore());
	} else {
	    usage();
	}
    }

    public static void usage()
    {
	System.out.println("TerrysGame get");
	System.out.println("TerrysGame set <score>");
	System.exit(1);
    }
}

.�La Clase HighScore

La clase HighScore almacena y protege el acceso a la m�xima puntuaci�n del usuario de TerrysGame (y de cualquier otro juego que la llame). Por simplicidad, esta clase graba la m�xima puntuaci�n en un fichero, llamado .highscore, en el directorio home del usuario. Sin embargo, antes de permitir a TerrysGame que recupere y actualice el valor de m�xima puntuaci�n del usuario, esta clase chequea para asegurarse de que el usuario ha concedido a TerrysGame el permiso para acceder a la m�xima puntuaci�n en su fichero de pol�tica de seguridad.

.�Comprobar que TerrysGame tiene el HighScorePermission

Para comprobar si TerrysGame tiene o no permiso para acceder a la m�xima puntuaci�n del usuario, la clase HighScore debe.

  1. Llamar a System.getSecurityManager() para obtener el controlador de seguridad instalado realmente.
  2. Si el resultado no es null (es decir, es un controlador de seguridad, lo opuesto a cuando el llamador es una aplicaci�n que no tiene restricciones), entonces
    1. Construye un objeto HighScorePermission, y
    2. llama al m�todo checkPermission del controlador de seguridad, y el pasa el objeto HighScorePermission recientemente construido.

Aqu� est� el c�digo.

SecurityManager sm = System.getSecurityManager();
if (sm != null) {
    sm.checkPermission(new HighScorePermission(gameName));
}

Esencialmente el m�todo checkPermission lepreginta al controlador de seguridad si TerrysGame tiene el HighScorePermission especificado. En otras palabras, le pregunta al controlador de seguridad si TerrysGame tiene permiso para actualizar la m�xima puntuaci�n del usuario para el juego espec�ficado (TerrysGame). El marco de trabajo de seguridad en segundo plano consultar� el fichero de pol�tica del usuario para ver si realmente TerrysGame tiene este permiso.

.�El c�digo HighScore

Aqu� est� el c�digo fuente completo de la clase HighScore.

Nota: las llamadas al m�todo doPrivileged se utilizan para permitir a HighScore un acceso temporal a los recursos que tiene disponibles, pero no est� disponible para el c�digo que llam� a (TerrysGame). Por ejemplo, espera que el fichero de pol�tica conceda permiso a HighScore para acceder al fichero .highscore en el directorio home del usuario, pero no concede este permiso a los juegos, como TerrysGame. Para m�s informaci�n sobre el uso de los m�todos doPrivileged puedes visitar New Privileged Block API en la web site de java.sun.com.

.�La clase HighScorePermission

La clase HighScorePermission define el permiso que TerrysGame necesita para actualizar la m�xima puntuaci�n del usuario.

Todas las clases permission tienen que ser una subclase de java.security.Permission o de java.security.BasicPermission. La diferencia b�sica entre las dos es que java.security.Permission define permisos m�s complejos que requieren nombres y acciones. Por ejemplo, un java.io.FilePermission desciende de java.security.Permission, y requiere un nombre (un nombre de fichero) y las acciones permitidas para ese fichero (leer/escribir/borrar).

En contraste, java.security.BasicPermission define permisos sencillos que s�lo requieren un nombre. Por ejemplo, java.lang.RuntimePermission desciende de java.security.BasicPermission y s�lo necesita un nombre (como "exitVM"), que permite a los programas salir de la Maquina Virtual Java.

Nuestro HighScorePermission es un permiso sencillo, y de hecho puede descender de java.security.BasicPermission.

Frecuentemente, la implementaci�n de los m�todos de la propia clase BasicPermission no tiene que ser sobreescrita por sus subclases. Este es el caso de nuestro HighScorePermission, por eso todo lo que tenemos que implementar son los constructores, que s�lo invocan a los constructores de la superclase, como se ve en el c�digo.

package com.scoredev.scores;

import java.security.*;

public final class HighScorePermission extends BasicPermission {

    public HighScorePermission(String name)
    {
	super(name);
    }

    // note that actions is ignored and not used,
    // but this constructor is still needed
    public HighScorePermission(String name, String actions) 
    {
	super(name, actions);
    }
}

.�Un Fichero de Pol�tica de Ejemplo

Abajo hay un fichero de pol�tica completo usado por un usuario que est� esperando para ejecutar TerrysGame.

La s�ntaxis del fichero de pol�tica no se describe aqu�; si est�s interesado puedes ver Default Policy Implementation and Policy File Syntax en el web site de java.sun.com.

No necesitamos conocer la s�ntaxis, siempre podemos usar Policy Tool para crear ficheros de pol�tica, como se muestra en las lecciones Visi�n R�pida para Controlar Applets, Visi�n R�pida para Controlar Aplicaciones, y Firmar C�digo y Conceder Permisos.

Abajo est� el fichero de pol�tica de ejemplo, seguida por una descripci�n de las entradas individuales. Asume que.

  • El fichero de pol�tica est� en el ordenador de Kim, y su keystore se llama kim.keystore.
  • TerrysGame ha sido firmado por la clave privada de Terry, su creador, y la correspondiente clave p�blica est� en el keystore con el alias de "terry".
  • Las clases HighScore y HighScorePermissions fueron firmadas con la clave privada de la persona que las implement� (Chris), y su correspondiente clave p�blica est� en el keystore con el alias de "chris".

Aqu� est� el fichero de pol�tica.

keystore "kim.keystore";

// Here is the permission TerrysGame needs.
// It grants code signed by "terry" the HighScorePermission, if the
// HighScorePermission was signed by "chris"
grant SignedBy "terry" {
  permission com.scoredev.scores.HighScorePermission
      "TerrysGame", signedBy "chris";
};

// Here is the set of permissions the HighScore class needs.
grant SignedBy "chris" {
  // The HighScore class needs permission to read "user.home" to find
  // the location of the highscore file

  permission java.util.PropertyPermission "user.home", "read";

  // It needs permission to read and write the high score file itself

  permission java.io.FilePermission
      "${user.home}${/}.highscore", "read,write";

  // It needs to get granted its own permission,
  // so it can call checkPermission
  // to see if its caller has permission.
  // Only grant it the permission
  // if the permission itself was signed by "chris"

  permission com.scoredev.scores.HighScorePermission 
      "*", signedBy "chris";
};

.�La Entrada Keystore

Un keystore es un repositorio de claves y certificados, y se usa para buscar las claves p�blicas de los firmantes especificados en el fichero de pol�tica ("terry" y "chris" en este ejemplo).

La utilidad keytool se utiliza para crear y administrar keystores.

Para esta lecci�n, asumimos que Kim quiere jugar a TerrysGame. Si el keystore de Kim tiene el nombre de kim.keystore, el fichero de pol�tica de Kim necesita tener la siguiente l�nea lo m�s al principio posible.

keystore "kim.keystore";

.�La Entrada TerrysGame

Una entrada de fichero de pol�tica especifica uno o m�s permisos para el c�digo de un c�digo fuente particular - o bien c�digo de una localizaci�n particular (URL) o c�digo firmado por una entidad particular o ambos.

Nuestro fichero de pol�tica necesita una entrada para cada juego, concediendo al c�digo firmado por el creador del juego un HighScorePermission cuyo nombre es el nombre del juego. Este permiso permite al juego llamar a los m�todos HighScore para obtener o actualizar el valor de la m�xima puntuaci�n de un usuario en un juego particular.

La entrada requerida para TerrysGame es.

grant SignedBy "terry" {
  permission com.scoredev.scores.HighScorePermission 
      "TerrysGame", signedBy "chris";
};

Requerir que el juego TerrysGame est� firmado por "terry" permite a Kim saber que el juego es realmente el juego que desarroll� Terry. Para este trabajo, Kim debe terner almacenado el certificado de la clave p�blica de Terry en kim.keystore usando el alias "terry".

Observa que HighScorePermission necesita estar firmado por "chris", la persona que realmente implement� el permiso. Esto asegura que a TerrysGame se le concede el permiso que realmente implement� "chris", y no el de otra persona. Como antes, para hacer esto Kim debe tener almacenado el certificado de la clave p�blica de Chris en kim.keystore usando el alias "chris".

.�La Entrada HighScore

La entrada final del fichero de pol�tica concede permiso a la clase HighScore. M�s espec�fiamente concede permiso al c�digo firmado por "chris", que fue quien creo y firm� la clase. Requiriendo que la clase est� firmada por "chris" aseguramos que cuando TerrysGame llama a esta clase para actualizar la puntuaci�n m�xima del usuario, TerrysGame da por seguro que est� suando la clase original implementada por "chris".

Para actualizar el valor de la puntuaci�n m�xima del usuario por cualquier juego que lo llame, la clase HighScore requiere tres permisos.

.�1. Permiso para leer el valor de la propiedad "user.home".

La clase HighScore almacena la puntuaci�n m�xima del usuario en un fichero .highscore en el directorio home del usuario. Por lo tanto est� clase necesita un java.util.PropertyPermission que le permita leer el valor de la propiedad "user.home" para encontrar ex�ctamente d�nde se encuenra el directorio home del usuario.

permission java.util.PropertyPermission 
    "user.home", "read";

.�2. Permiso para leer y escribir el propio fichero de la m�xima puntuaci�n.

Este permiso se necesita porque los m�todos getHighScore y setHighScore pueden acceder al fichero del usuario .highscore para obtener o seleccionar, respectivamente, el valor actual de la m�xima puntuaci�n del usuario en el juego actual.

Aqu� est� el permiso requerido.

permission java.io.FilePermission
    "${user.home}${/}.highscore", "read,write";

Nota: la notaci�n ${propName} espec�fica el valor de una propiedad. As�, ${user.home} ser� reempalzao por el valor de la propiedad "user.home". La notaci�n ${/} es una forma independiente de la plataforma de identificar un separador de ficheros.

.�3. Todos los HighScorePermissions (es decir, HighScorePermissions de cualquier nombre).

Este permiso es necesario para que la HighScore se asegure de que el juego llamante tiene concedido un HighScorePermission cuyo nombre es el nombre del juego para el que trabaja. Es decir, la clase HighScore tambi�n debe conceder este permiso, ya que un chequeo de permiso requiere que todo el c�digo que hay en la pila tenga el permiso espec�ficado.

Aqu� est� el permiso requerido.

permission com.scoredev.scores.HighScorePermission
    "*", signedBy "chris";

Como antes, el propio HighScorePermission necesita estar firmado por "chris", la persona que realmente implement� el permiso.

.�Poni�ndolo Todo Junto

Aqu�, hemos simulado ser, por turnos, el desarrallador de HighScore (Chris), el desarrollador de TerrysGame (Terry), y el usuario del juego (Kim).

Podemos ejecutar todos los pasos espec�ficados, y luego jugar con TerrysGame.

Los pasos se presentan sin explicaci�n, Para m�s informaic�n sobre los pasos necesarios tomados por los firmantes de c�digo (como Chris y Terry) y por los receptores de c�digo (como Kim), puedes ver la lecci�n: Firmar C�digo y Concerderle Permisos.

Aqu� est�n los pasos.

.�Pasos del Desarrollador de HighScore (Chris)

Los pasos que Chirs deber�a realizar, despu�s de crear las clases HighScore y HighScorePermission, son.

.�Compilar las Clases

javac HighScore*.java -d .

.�Meter los ficheros class en un fichero JAR

jar cvf hs.jar com/scoredev/scores/HighScore*.class

.�Crear un Keystore y las Claves para Firmar

keytool -genkey -keystore chris.keystore -alias signJars

Podemos especificar las passwords que queramos y la informaci�n de nombre distinguido.

.�Firmar el fichero JAR

jarsigner -keystore chris.keystore hs.jar signJars

.�Exportar el Certificado de la Clave P�blica

keytool -export -keystore chris.keystore
    -alias signJars -file Chris.cer

.�Suministrar los Ficheros y la Informaci�n Necesaria para los Usuarios y Desarrolladores del Juego

Esto es, suministrarles

  • El fichero JAR firmadohs.jar,
  • el fichero del certificado de la clave p�blica Chris.cer, y
  • y la informaci�n sobre los permisos que deben concederse en el fichero de pol�tica a las clases HighScore y HighScorePermission para poder funcionar. Para esto, Chirs deber�a suministrar la entrada de permiso exacta necesaria.

.�Pasos del Desarrollador de TerrysGame (Terry)

Los pasos que Terry deber�a realizar, desp�es de crear el juego (TerrysGame ) las llamadas a los m�todos getHighScore y setHighScore de HighScore, son.

.�Compilar la Clase del Juego

javac TerrysGame.java -classpath hs.jar -d .

.�Poner sus ficheros Class en un fichero JAR

jar cvf terry.jar com/gamedev/games/TerrysGame.class

.�Crear un Keystore y las Claves para Firmar

keytool -genkey -keystore terry.keystore -alias signTJars

Podemos especificar las passwords que queramos y la informaci�n de nombre distinguido.

.�Firmar el Fichero JAR

jarsigner -keystore terry.keystore terry.jar signTJars

.�Exportar el Certificado de la Clave P�blica

keytool -export -keystore terry.keystore
    -alias signTJars -file Terry.cer

.�Suministrar los Ficheros y la Informaci�n Necesaria para los Usuarios

Es decir, suministrales

  • El fichero JAR firmadoterry.jar,
  • el fichero del certificado de la clave p�blica terry.cer, y
  • y la informaci�n sobre los permisos que deben concederse en el fichero de pol�tica a las clases TerrysGame y HighScorePermission para poder funcionar. Para esto, Chirs deber�a suministrar la entrada de permiso exacta necesaria.

Lo usuarios del Juego tambi�n necesitar�n la informaci�n de Chris. Por conveniencia, Terry podr�a reenviarles est� informaci�n.

  • El fichero JAR firmadohs.jar,
  • el fichero del certificado de la clave p�blica Chris.cer, y
  • y la informaci�n sobre los permisos que deben concederse en el fichero de pol�tica a las clases HighScore y HighScorePermission para poder funcionar. Para esto, Chirs deber�a suministrar la entrada de permiso exacta necesaria.

.�Pasos para Ejecutar TerrysGame (Kim)

Los pasos que un usuario, como Kim, deber�a realizar son.

.�Importar los Certificados como Certificados Verdaderos

keytool -import -alias chris -file Chris.cer -keystore kim.keystore
keytool -import -alias terry -file Terry.cer -keystore kim.keystore

.�Configurar un fichero de Pol�tica con los Permisos Requeridos

Aqu� est� el fichero de pol�tica kim.policy, como se describi� en "Un Fichero de Pol�tica de Ejemplo".

.�Ejecutar el TerrysGame

Para seleccionar la puntuaci�n m�xima.

java -Djava.security.manager -Djava.security.policy=kim.policy
 -classpath hs.jar;terry.jar com.gamedev.games.TerrysGame set 456

Para obtener la m�xima puntuaci�n.

java -Djava.security.manager -Djava.security.policy=kim.policy
 -classpath hs.jar;terry.jar com.gamedev.games.TerrysGame get

Notas.

  • Si no especificamos -Djava.security.manager, la aplicaci�n se ejecutar� sin restricciones (no se chequear�n los ficheros de pol�tica ni los permisos
  • -Djava.security.policy=kim.policy dice donde se encuentra el fichero de pol�tica.

    Nota: Existen otras formas de especificar el fichero de pol�tica. Por ejemplo, podemos a�adir una netrada en el fichero de propiedades de seguridad que especifique la inclusi�n del kim.policy, como se explica al final de la lecci�n Ver los Efectos del Fichero de Pol�tica.

  • -classpath hs.jar;terry.jar especifica los ficheros JAR que contienen los ficheros class necesarios. En Windows se usa un punto y coma (";") para separar los ficheros JAR, en Unix se usan dos puntos (":").
  • El fichero de pol�tica kim.policy especifica el keystore kim.keystore. Como no se proporciona la localizaic�n URL del keystore, se asume que se encuentra en el mismo directorio que el fichero de pol�tica.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR